Go http client 连接池不复用的问题

Posted 码农桃花源

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go http client 连接池不复用的问题相关的知识,希望对你有一定的参考价值。

当 http client 返回值为不为空,只读取 response header,但不读 body 内容就执行 response.Body.Close(),那么连接会被主动关闭,得不到复用。

测试代码如下:

// xiaorui.cc

func HttpGet() {
 for {
  fmt.Println("new")
  resp, err := http.Get("http://www.baidu.com")
  if err != nil {
   fmt.Println(err)
   continue
  }

  if resp.StatusCode == http.StatusOK {
   continue
  }

  resp.Body.Close()
    
  fmt.Println("go num", runtime.NumGoroutine())
 }
}

正如大家所想,除了 HEAD Method 外,很少会有只读取 header 的需求吧。

话说,golang httpclient 需要注意的地方着实不少。

  • 如没有 response.Body.Close(),有些小场景造成 persistConn 的 writeLoop 泄露。
  • 如 header 和 body 都不管,那么会造成泄露的连接干满连接池,后面的请求只能是 短连接

上下文

由于某几个业务系统会疯狂调用各区域不同的 k8s 集群,为减少跨机房带来的时延、兼容新老 k8s 集群 api、减少k8s api-server 的负载,故而开发了 k8scache 服务。在部署运行后开始对该服务进行监控,发现 metrics 呈现的 QPS 跟连接数不成正比,qps 为 1500,连接数为 10 个。开始以为触发 idle timeout 被回收,但通过历史监控图分析到连接依然很少。

以上是关于Go http client 连接池不复用的问题的主要内容,如果未能解决你的问题,请参考以下文章

为什么数据库连接池不采用 IO 多路复用?

面试官:为什么数据库连接池不采用 IO 多路复用?我懵逼了。。

面试官:为什么数据库连接池不采用 IO 多路复用?我懵逼了。。

聊一个不常见的面试题:为什么数据库连接池不采用 IO 多路复用

聊一个不常见的面试题:为什么数据库连接池不采用 IO 多路复用

不常见的面试题:为什么数据库连接池不采用IO多路复用?