按部分回答中的方法全局使用同一个 client 和 transport 之后,依然出现 goroutine 泄露 导致的 fd 增长
发现 如果同时设置 http.client timeout 和 transport dial timeout 则会出现 socket too many open files 的错误,我在程序中通过一个 queueChan 的 bufferd channel 控制同时请求数量。但是根据 pprof 调试和 /proc/pid/fd 中的 socket 文件数量, 得出结论为旧的请求还未彻底关闭 新的请求又被创建最终导出的 fd 满了 同时 nestat 中有大量TIME_WAIT
如果只设置 transport dial timeout,不设置 http.client timeout 则 goroutine 数量和 queueChan 长度一致,fd 数量也正常,但是 netstat 出现大量的ESTABLISHED
, 并且请求超过 timeout 也不结束
那回到最初的问题 :
1
wnanbei 2019-12-28 20:01:11 +08:00
1.不同的 proxy 肯定不能复用连接
2.因为 transport 默认限制单个域名最大是两个可以复用的长连接,所以单个域名访问量过大,会产生非常多短连接,造成大量 time_wait. 尝试把你的 client 的单个域名连接量设置的大一点。 |
4
freestyle 2019-12-29 10:12:26 +08:00 via iPhone
1. 不能 可以用个 map[proxyUrl]Tranposrt 管理 proxy Transport 2. http.Request 有 Close 字段,设置后就是短连接,请求后关闭连接. 也可以设置 httpClient 的 Tranport disableKeepAlive=true 使得默认不 keepAlive,这样也是请求后关闭连接
|
5
wnanbei 2019-12-29 13:26:33 +08:00
@tim0991 是的,如果你每个请求一个不同的 proxy,那么第二点设置多大都没用,因为从网络原理来说,你在跟不同的代理服务器建立连接,根本无法复用。
这种时候只能调低点访问速度。连接关闭之后是有个等待时间的,如果在短时间内关闭太多连接,新发起请求时连接都还处于正在关闭的状态中,没有新的连接能建立,这时候就会报你这样的错。 |
6
tim0991 OP @freestyle 谢谢你的手机回复,但是从我目前测试结果来看 就算加了 close 的 header 也没有效果 connection 还是不关闭
|
10
freestyle 2019-12-29 23:17:03 +08:00 via iPhone
@tim0991 除了转化 header 还会在 transport 连接池中处理这个 flag 不扔进池里而是复用
|
11
freestyle 2019-12-29 23:17:28 +08:00 via iPhone
@tim0991 除了转化 header 还会在 transport 连接池中处理这个 flag 不扔进池里而是关闭
|
12
goofool 2019-12-30 09:49:16 +08:00
你怎么知道代理一定能连接成功,这块需要处理吧
|
15
zdt3476 2019-12-30 13:48:38 +08:00
看了上个帖子的代码,感觉还是并发太高导致的。time_wait 持续期间这个 fd 是没法释放的。尝试下并发数改为 ulimit -n 的一半?
|