-2
我寫Kanali這是一個開源的Kubernetes入口/ API管理工具和我收到以下致命錯誤約1/200K請求:非常分散轉到HTTP錯誤:多response.WriteHeader調用
2017/08/16 12:40:57 http: multiple response.WriteHeader calls
{"level":"error","method":"GET","msg":"unknown error","time":"2017-08-16T12:40:57Z","uri":"/ommitted/path"}
{"level":"fatal","msg":"write tcp4 192.168.2.160:8443-\u003e192.168.4.0:54554: write: broken pipe","time":"2017-08-16T12:40:57Z"}
我很難再現它,但這裏是相關的代碼。 Kanali是一個很大的項目,但td; lr是在執行第一個代碼片段之後,第二個被剪切的代碼被執行來處理錯誤。
func (step WriteResponseStep) Do(ctx context.Context, m *metrics.Metrics, c *controller.Controller, w http.ResponseWriter, r *http.Request, resp *http.Response, trace opentracing.Span) error {
for k, v := range resp.Header {
for _, value := range v {
w.Header().Set(k, value)
}
}
closer, str, err := utils.DupReaderAndString(resp.Body)
if err != nil {
logrus.Errorf("error copying response body, response may not be as expected: %s", err.Error())
}
trace.SetTag("http.status_code", resp.StatusCode)
trace.SetTag("http.response_body", str)
w.WriteHeader(resp.StatusCode)
if _, err := io.Copy(w, closer); err != nil {
return err
}
return nil
}
代碼後...
if err != nil {
w.Header().Set("Content-Type", "application/json")
switch e := err.(type) {
case utils.Error:
logrus.WithFields(logrus.Fields{
"method": r.Method,
"uri": r.RequestURI,
}).Error(e.Error())
errStatus, err := json.Marshal(utils.JSONErr{Code: e.Status(), Msg: e.Error()})
if err != nil {
logrus.Warnf("could not marsah request headers into JSON - tracing data maybe not be as expected")
}
w.WriteHeader(e.Status())
if err := json.NewEncoder(w).Encode(utils.JSONErr{Code: e.Status(), Msg: e.Error()}); err != nil {
logrus.Fatal(err.Error())
}
default:
logrus.WithFields(logrus.Fields{
"method": r.Method,
"uri": r.RequestURI,
}).Error("unknown error")
errStatus, err := json.Marshal(utils.JSONErr{Code: http.StatusInternalServerError, Msg: "unknown error"})
if err != nil {
logrus.Warnf("could not marsah request headers into JSON - tracing data maybe not be as expected")
}
w.WriteHeader(http.StatusInternalServerError)
if err := json.NewEncoder(w).Encode(utils.JSONErr{Code: http.StatusInternalServerError, Msg: "unknown error"}); err != nil {
logrus.Fatal(err.Error())
}
}
}
錯誤消息告訴您WriteHeader被多次調用(直接或間接通過調用Write來調用)。標題只能寫入網絡一次。這兩個片段都有一個WriteHeader ... –
的調用,所以它很零星的原因是隻有在執行該錯誤時纔會發生錯誤:https://github.com/northwesternmutual/kanali/blob/master/steps/writeresponse。去#L66-L68 – frankgreco
@CeriseLimón如果你把你的評論變成答案,我會把它標記爲正確的答案:) – frankgreco