【问题标题】:Call to ExecuteTemplate receives an i/o timeout error调用 ExecuteTemplate 收到 i/o 超时错误
【发布时间】:2023-04-06 21:47:01
【问题描述】:

我有一个函数,它使用 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(有和没有这些选项),但无济于事。我还尝试将请求的自动关闭值设置为 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)
}

【问题讨论】:

  • 你真的能用这个精简的版本重现错误吗?我认为没有,因为 1) 响应已下载并且 then 模板运行 - 所以在 ExecuteTemplate 内不能有任何 tcp 超时; 2)您的模板根本不使用响应(正文)。
  • 1.在完整版中运行模板之前,也会下载响应。在所有情况下,api_response 对象都会在超时投诉之前从服务器fmt.Printf 向控制台发出正确的响应。 2. 我的模板只是从响应正文中打印出文本,但如上所述,我是fmt.Printf 响应,就在超时之前,所以它到达了。我想知道客户端是否由于某种原因没有正确关闭其连接。

标签: go


【解决方案1】:

这一行的超时时间:

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

表示 outgoing 响应在写入时超时,因此您在本地创建的客户端中所做的任何更改都不会影响它。来自该客户端的缓慢响应增加了w 上的超时机会也是有道理的,因为截止日期是在创建响应时设置的,在调用您的处理程序之前,因此您的处理程序的缓慢活动将增加超时的机会。

http.ListenAndServe 使用的 http.Server 实例没有写入超时,因此您必须在创建的服务器上显式设置 Server.WriteTimeout 字段。

附带说明,在该处理程序中会忽略一些错误,这是一种强烈不鼓励的做法。

【讨论】:

  • 为简洁起见删除了错误检查,因此我将代码称为“精简”。
  • 就是这样。感谢您对传出响应位的澄清。这非常有帮助,并且准确地解决了问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-11
  • 2021-09-11
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多