Golang Go语言中如何立即关闭 http client 产生的 connection
Golang Go语言中如何立即关闭 http client 产生的 connection
按部分回答中的方法全局使用同一个 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 也不结束
那回到最初的问题 :
- tranport 中 不同的 protocol 和 proxy host 能否复用 tcp connection ?
- 请求结束时如何立即关闭 connection ?
更多关于Golang Go语言中如何立即关闭 http client 产生的 connection的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
#1 这好像不对啊,既然 proxy 不能复用,那你第二点说的 不管设置多大 就没有意义了吧
另外你的 direwolf 包源代码我略微看过了,是不是也存在我的这个问题?
- 不能 可以用个 map[proxyUrl]Tranposrt 管理 proxy Transport 2. http.Request 有 Close 字段,设置后就是短连接,请求后关闭连接. 也可以设置 httpClient 的 Tranport disableKeepAlive=true 使得默认不 keepAlive,这样也是请求后关闭连接
是的,如果你每个请求一个不同的 proxy,那么第二点设置多大都没用,因为从网络原理来说,你在跟不同的代理服务器建立连接,根本无法复用。
这种时候只能调低点访问速度。连接关闭之后是有个等待时间的,如果在短时间内关闭太多连接,新发起请求时连接都还处于正在关闭的状态中,没有新的连接能建立,这时候就会报你这样的错。
谢谢你的手机回复,但是从我目前测试结果来看 就算加了 close 的 header 也没有效果 connection 还是不关闭
照你这么说的话 那等于无解了 🤦♂️
不是自己加 header 是 req.Close=true
也加了 我记得源代码中 好像会解析 req.Close 把他转化成 header
除了转化 header 还会在 transport 连接池中处理这个 flag 不扔进池里而是复用
除了转化 header 还会在 transport 连接池中处理这个 flag 不扔进池里而是关闭
你怎么知道代理一定能连接成功,这块需要处理吧
你自己不是都说 Proxy 不同不能复用吗 😂
大部分代理都是失败的
看了上个帖子的代码,感觉还是并发太高导致的。time_wait 持续期间这个 fd 是没法释放的。尝试下并发数改为 ulimit -n 的一半?
确实很无解
不过我有次好像看到 time_wait 的持续期是好像是可以在系统里修改的,你可以查查
在 Go 语言中,HTTP 客户端(http.Client
)默认情况下会管理连接池,以复用连接来提高性能。然而,在某些情况下,你可能需要立即关闭一个 HTTP 客户端产生的连接。
需要明确的是,直接关闭底层的 TCP 连接在 Go 的 net/http
包中并不总是直接暴露出来的。标准库提供了高级的接口来管理连接池,但没有直接的方法来关闭一个特定的连接。
不过,你可以通过以下几种方式间接实现类似的效果:
-
取消请求:使用
context.Context
来取消正在进行的 HTTP 请求。这会导致连接被尽早释放回连接池,虽然不直接关闭连接,但可以减少连接占用时间。 -
调整
Transport
设置:你可以配置http.Client
的Transport
字段,设置IdleConnTimeout
和MaxIdleConns
等参数,来限制空闲连接的生命周期和数量。 -
自定义
http.RoundTripper
:实现一个自定义的http.RoundTripper
,在每次请求后关闭连接。这通常涉及到底层 TCP 连接的管理,需要小心处理以避免资源泄漏。 -
关闭
http.Client
:如果你确定不再需要使用该客户端,可以通过将http.Client
的Transport
字段设为nil
(如果它使用了默认的Transport
),然后让垃圾回收器回收资源。不过,这不会立即关闭所有连接,只是释放了客户端的引用。
总的来说,直接关闭特定连接在 Go 的 net/http
包中并不简单,通常需要通过调整客户端的行为和配置来间接实现。