2017-08-16 14 views
-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()) 
     } 
    } 
} 
+4

錯誤消息告訴您WriteHeader被多次調用(直接或間接通過調用Write來調用)。標題只能寫入網絡一次。這兩個片段都有一個WriteHeader ... –

+1

的調用,所以它很零星的原因是隻有在執行該錯誤時纔會發生錯誤:https://github.com/northwesternmutual/kanali/blob/master/steps/writeresponse。去#L66-L68 – frankgreco

+0

@CeriseLimón如果你把你的評論變成答案,我會把它標記爲正確的答案:) – frankgreco

回答

3

錯誤信息是告訴你,WriteHeader被稱爲不止一次(直接或間接通過調用寫)。標題只能寫入網絡一次。這兩個片段都調用了WriteHeader。

相關問題