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

反向代理出错后,会出现线程泄露?

  •  
  •   Pengxiguaa ·
    pengxiguaa · 2022-01-18 16:19:37 +08:00 · 17770 次点击
    这是一个创建于 828 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我用 GO 写了一个很简单的反向代理程序,代码如下:

    func main() {
    	go func() {
    		log.Fatal( http.ListenAndServe(":5050", nil))
    	}()
    	link, err := url.Parse("http://127.0.0.1:8908")
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Fatal( http.ListenAndServe(":10086", httputil.NewSingleHostReverseProxy(link)))
    }
    

    端口 8908 后边是一个 NodeJS socket.io 服务端,现在我通过 NodeJS 向 10086 端口同时发起 1000 个 websocket 连接,这些链接均会被代理到 8908 端口服务,然后将所有连接断开,重复几轮后可见控制台报如下错误:

    2022/01/18 14:06:54 http: proxy error: dial tcp 127.0.0.1:8908: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.
    

    此时通过 windows 资源监视器可看到反向代理程序线程数为 298 ,通过 Process Explorer 可以看到 Handles 数为 1855 ,并且存在大量 Thread 。

    再次建立连接再断开,反向代理程序的线程数持续增长,通过 pprof 可见 threadcreate 此时达到了惊人的 472 ,并一直保持。

    似乎是系统端口数量限制导致的错误,然后错误导致线程未被回收?

    我是 GO 新手,大家有遇到过这个问题吗?

    14 条回复    2022-05-24 11:24:29 +08:00
    pathletboy
        1
    pathletboy  
       2022-01-19 08:27:14 +08:00
    不是你断开,反代和 8908 之间的连接就马上断开,和你系统的 TCP 的 TIME_WAIT 有关
    参考 https://help.socketlabs.com/docs/how-to-fix-error-only-one-usage-of-each-socket-address-protocolnetwork-addressport-is-normally-permitted
    Pengxiguaa
        2
    Pengxiguaa  
    OP
       2022-01-19 11:56:26 +08:00
    @pathletboy 感谢回复

    目前我已将系统 TCP 释放时间( TcpTimedWaitDelay )调整为了 30 秒,并重新进行了测试。
    几轮 websocket 连接-断开 之后,通过资源监视器看到反代程序积累了 465 个线程,此时 websoket 客户端处于断开的状态(进程已退出),8908 websocket 服务端正常运行,等待了 10 分钟线程数并未减少。紧接着关闭 8908 服务(退出进程),等待 10 分钟,线程数依然保持不变。
    pathletboy
        3
    pathletboy  
       2022-01-19 11:59:13 +08:00
    @Pengxiguaa 有条件的话可以测试下 caddy 反代是不是这样?
    Pengxiguaa
        4
    Pengxiguaa  
    OP
       2022-01-19 12:02:54 +08:00
    官方库对这部分常用场景应该有考虑才对...现在没有头绪,待学习别人反代 websocket 之后再来更新。
    Pengxiguaa
        5
    Pengxiguaa  
    OP
       2022-01-19 12:03:34 +08:00
    @pathletboy 好的,感谢提醒
    Pengxiguaa
        6
    Pengxiguaa  
    OP
       2022-01-19 14:19:59 +08:00
    @pathletboy

    在 windows 10 powershell 通过以下命令启动 caddy
    ```
    # caddy_windows_amd64.exe reverse-proxy --from :10086 --to 127.0.0.1:8908
    ```
    也会积累线程,奇怪了。

    有时间再测测最多能积累多少线程,会不会导致进程崩溃的问题吧。
    pathletboy
        7
    pathletboy  
       2022-01-19 14:57:24 +08:00
    @Pengxiguaa import 加一行
    _ "net/http/pprof"

    跑起来看看这个有没什么发现
    http://127.0.0.1:5050/debug/pprof/
    liaohongxing
        8
    liaohongxing  
       2022-01-21 09:22:53 +08:00
    测试大量短链接端口不应该在 windows 测试。应该在 linux 测试 ,windows 本身就对 tcp 数量有限制 。其次就是 TCP TIME_WAIT ,不过 windows 的 TCP TIME_WAIT 也不知道怎么设
    liaohongxing
        9
    liaohongxing  
       2022-01-21 09:24:12 +08:00
    你那报错我也遇到。随便用 hey 测几轮并发 ,windows 马上就报端口不够用了。
    Pengxiguaa
        10
    Pengxiguaa  
    OP
       2022-01-21 12:05:53 +08:00
    @pathletboy 功力太浅,看不太明白,只记得在所有连接断开后,goroutine 数目恢复到个位数,而 threadcreate 依然居高不下。
    Pengxiguaa
        11
    Pengxiguaa  
    OP
       2022-01-21 12:13:26 +08:00
    @liaohongxing TCP TIME_WAIT 设置看这里: https://docs.microsoft.com/en-us/biztalk/technical-guides/settings-that-can-be-modified-to-improve-network-performance

    另外我们生产服务器只有 windows server ...
    yeqown
        12
    yeqown  
       2022-02-11 18:05:09 +08:00
    @Pengxiguaa
    这样反向代理 WS 是不行的吧,你想 HTTP 握手后升级到 WS ,HTTP 客户端怎么和 WS 服务器通信呢?协议都不一样了~
    https://github.com/yeqown/fasthttp-reverse-proxy/blob/master/ws_reverseproxy.go#L71 供参考
    yeqown
        13
    yeqown  
       2022-02-11 18:07:04 +08:00
    其次,看你的错误信息,我猜测你这个代理应该连握手都没办法完成吧~(协议问题),你测试结果有正确的响应吗?
    Pengxiguaa
        14
    Pengxiguaa  
    OP
       2022-05-24 11:24:29 +08:00
    @yeqown ReverseProxy 模块中有 websocket 的实现,详情看 https://go.dev/src/net/http/httputil/reverseproxy.go:280,306
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3161 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 14:54 · PVG 22:54 · LAX 07:54 · JFK 10:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.