【问题标题】:HTTP Requests, JSON, reusing connectionsHTTP 请求、JSON、重用连接
【发布时间】:2016-01-18 17:04:54
【问题描述】:

我正在使用 Go 通过 HTTPS 发出许多请求,但我遇到了不重用连接和端口不足的问题。我发出的请求是对返回 JSON 格式数据的 API 的请求,然后我将其 json.Decode 转换为 Go 值。

根据我在这个网站上遇到的问题(#1#2),为了让 Go 将连接重用于另一个请求,我必须在关闭之前阅读整个响应正文(注意这个如here 所述,并非总是如此。

Previously the HTTP client's (*Response).Body.Close would try to keep
reading until EOF, hoping to reuse the keep-alive HTTP connection...

在典型情况下,我会使用前面链接中显示的示例,如下所示:

ioutil.ReadAll(resp.Body)

但由于我是通过如下代码从 JSON 中提取数据:

...

req, _ := http.NewRequest("GET", urlString, nil)
req.Header.Add("Connection", "keep-alive")
resp, err = client.Do(req)
defer resp.Body.Close()

...

decoder := json.NewDecoder(resp.Body)
decoder.Decode(data)

我不确定这两种方法会如何交互。

所以问题是,我如何确保已读取整个响应,以便稍后可以将连接重用于另一个请求?

【问题讨论】:

  • 嗯。也许最简单的方法是自己实现旧行为:defer func() { io.Copy(ioutil.Discard, resp.Body); resp.Body.Close() }().
  • 也许在 decoder.Decode(data), 返回之后你已经读取了所有数据。
  • 如果您只期望正文中有 1 个合理大小的 json 响应,请不要使用解码器。使用 ReadAll 和 json.Unmarshal。
  • 我希望 JSON 的大小合理,但可能有许多并发/并行 goroutine,每个都处理响应。目前我使用的系统有足够的 RAM 来处理这个问题,但我不想依赖它。

标签: json http go request connection


【解决方案1】:

如果您只想使用解码器解码单个对象,则可以使用More() 方法查看流中是否还有更多需要读取的对象。

decoder := json.NewDecoder(resp.Body)
err := decoder.Decode(data)
if err != nil {
    // handle err
}
if decoder.More() {
    // there's more data in the stream, so discard whatever is left
    io.Copy(ioutil.Discard, resp.Body)
}

您也可以在每次调用时推迟复制,但这样您可以更轻松地处理或记录意外数据或错误。

【讨论】:

  • 是的,我遇到了More(),我不确定它是否完全符合我的要求。谢谢!
猜你喜欢
  • 2013-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 2017-04-30
  • 2020-07-28
  • 1970-01-01
  • 2015-12-30
  • 2016-02-02
相关资源
最近更新 更多