V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
tim0991
V2EX  ›  Go 编程语言

如何立即关闭 http client 产生的 connection

  •  
  •   tim0991 · 2019-12-28 18:28:20 +08:00 · 4500 次点击
    这是一个创建于 1791 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://v2ex.com/t/631536

    按部分回答中的方法全局使用同一个 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 ?
    16 条回复    2019-12-30 17:17:13 +08:00
    wnanbei
        1
    wnanbei  
       2019-12-28 20:01:11 +08:00
    1.不同的 proxy 肯定不能复用连接
    2.因为 transport 默认限制单个域名最大是两个可以复用的长连接,所以单个域名访问量过大,会产生非常多短连接,造成大量 time_wait. 尝试把你的 client 的单个域名连接量设置的大一点。
    tim0991
        2
    tim0991  
    OP
       2019-12-28 20:19:33 +08:00
    @wnanbei #1 这好像不对啊,既然 proxy 不能复用,那你第二点说的 不管设置多大 就没有意义了吧
    tim0991
        3
    tim0991  
    OP
       2019-12-28 20:22:03 +08:00
    @wnanbei 另外你的 direwolf 包源代码我略微看过了,是不是也存在我的这个问题?
    freestyle
        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,这样也是请求后关闭连接
    wnanbei
        5
    wnanbei  
       2019-12-29 13:26:33 +08:00
    @tim0991 是的,如果你每个请求一个不同的 proxy,那么第二点设置多大都没用,因为从网络原理来说,你在跟不同的代理服务器建立连接,根本无法复用。

    这种时候只能调低点访问速度。连接关闭之后是有个等待时间的,如果在短时间内关闭太多连接,新发起请求时连接都还处于正在关闭的状态中,没有新的连接能建立,这时候就会报你这样的错。
    tim0991
        6
    tim0991  
    OP
       2019-12-29 19:27:46 +08:00
    @freestyle 谢谢你的手机回复,但是从我目前测试结果来看 就算加了 close 的 header 也没有效果 connection 还是不关闭
    tim0991
        7
    tim0991  
    OP
       2019-12-29 19:28:16 +08:00
    @wnanbei 照你这么说的话 那等于无解了 🤦‍♂️
    freestyle
        8
    freestyle  
       2019-12-29 20:26:03 +08:00 via iPhone
    @tim0991 不是自己加 header 是 req.Close=true
    tim0991
        9
    tim0991  
    OP
       2019-12-29 22:17:30 +08:00
    @freestyle 也加了 我记得源代码中 好像会解析 req.Close 把他转化成 header
    freestyle
        10
    freestyle  
       2019-12-29 23:17:03 +08:00 via iPhone
    @tim0991 除了转化 header 还会在 transport 连接池中处理这个 flag 不扔进池里而是复用
    freestyle
        11
    freestyle  
       2019-12-29 23:17:28 +08:00 via iPhone
    @tim0991 除了转化 header 还会在 transport 连接池中处理这个 flag 不扔进池里而是关闭
    goofool
        12
    goofool  
       2019-12-30 09:49:16 +08:00
    你怎么知道代理一定能连接成功,这块需要处理吧
    tim0991
        13
    tim0991  
    OP
       2019-12-30 09:49:52 +08:00
    @freestyle 你自己不是都说 Proxy 不同不能复用吗 😂
    tim0991
        14
    tim0991  
    OP
       2019-12-30 09:50:21 +08:00
    @goofool 大部分代理都是失败的
    zdt3476
        15
    zdt3476  
       2019-12-30 13:48:38 +08:00
    看了上个帖子的代码,感觉还是并发太高导致的。time_wait 持续期间这个 fd 是没法释放的。尝试下并发数改为 ulimit -n 的一半?
    wnanbei
        16
    wnanbei  
       2019-12-30 17:17:13 +08:00
    @tim0991 确实很无解
    不过我有次好像看到 time_wait 的持续期是好像是可以在系统里修改的,你可以查查
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2795 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 14:22 · PVG 22:22 · LAX 06:22 · JFK 09:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.