0

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)
}
4

1 に答える 1

3

この行のタイムアウト:

err = t.ExecuteTemplate(w, "page.html", tmpl)

送信応答が書き込まれているときにタイムアウトになることを意味するため、ローカルに作成されたクライアントで変更を加えても、それに影響することはありません。また、そのクライアントからの応答が遅いと、 でのタイムアウトの可能性が高くなることも理にかなっていますw。これは、ハンドラーが呼び出される前に、応答が作成されたときに期限が設定されるためです。したがって、ハンドラーからの遅いアクティビティは、タイムアウト。

http.ListenAndServeで使用されるhttp.Serverインスタンスには書き込みタイムアウトがないため、作成したサーバーでServer.WriteTimeoutフィールドを明示的に設定する必要があります。

補足として、そのハンドラーで無視されるエラーがありますが、これは強くお勧めできません。

于 2013-09-12T14:45:07.897 に答える