调用 Go 的 HTTP Client 的 Get\Post 之类的方法时,默认是开启 HTTP keepalive 的,不过直接使用还是会遇到一些情况导致持久连接失效。首先,Client 构造好 HTTP 请求后,利用 Transport 来发送请求并等待结果,默认使用 DefaultTransport 来实现,大多数情况下,自定义 Client 时,配置一下自带的 Transport 即可。

transport 主要围绕着 persistConn 来实现,通过当前请求的 proxyschemeaddr 作为 Key,对已经建立的连接进行缓存,新的请求来时,先从缓存中取一个连接,如果没有,再新发起一个连接。按照 Go 的基本法,毫无疑问会有两个 goroutine 来分别处理连接上的读和写,然后各种 channel 就开始飞来飞去,于是便让人深思这真的会比基于事件回调的实现简单吗。

可见每次都会有一个请求是新建了个 TCP 连接的,也就是说默认只保持两条持久连接,这是因为这里自定义的的 http.Transport 没有设置 MaxIdleConnsPerHost,于是便采用了默认的 DefaultMaxIdleConnsPerHost,这个值是 2,这是 RFC2616 建议的单个客户端发起的持久连接数,不过在大部分情况下,这个值有点过于保守了。如果把 MaxIdleConnsPerHost 设置为 3,结果便和第一种情况一样。

参考链接https://doc.xuwenliang.com/docs/go/1201