Go http.Client を使用して外部 API を呼び出し、結果を解析し、後で実行されるテンプレートで結果を使用する関数があります。時折、外部 API の応答が遅くなり (~20 秒)、テンプレートの実行が「i/o タイムアウト」を理由に失敗します。具体的には、
template: :1:0: executing "page.html" at <"\n\t\t\t\t\t\t\t\t\...>: write tcp 127.0.0.1:35107: i/o timeout
これは常に遅い API 応答と一致しますが、JSON オブジェクトには常に有効な応答があるため、http.Client は適切な応答を受け取っています。誰かが ExecuteTemplate 呼び出しで i/o タイムアウトを引き起こしている可能性があることを指摘できるかどうか疑問に思っています。
クライアント トランスポートで ResponseHeaderTimeout と DisableKeepAlives を (これらのオプションの有無にかかわらず) 試してみましたが、役に立ちませんでした。また、リクエストの auto-close 値を true に設定しようとしましたが、役に立ちませんでした。テンプレート生成コードの簡素化されたバージョンを以下に示します。
func viewPage(w http.ResponseWriter, r *http.Request) {
tmpl := pageTemplate{}
duration, _ := time.ParseDuration("120s")
tr := &http.Transport{
ResponseHeaderTimeout: duration,
DisableKeepAlives: true,
}
client := &http.Client{Transport: tr}
req, _ := http.NewRequest("GET", "http://example.com/some_function", nil)
req.Close = true
resp, _ := client.Do(req)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
var res api_response // some struct that matches the JSON response
err = json.Unmarshal(body, &res)
t, _ := template.New("page.html")
err = t.ExecuteTemplate(w, "page.html", tmpl)
}