我用 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 新手,大家有遇到过这个问题吗?
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 |
2
Pengxiguaa OP @pathletboy 感谢回复
目前我已将系统 TCP 释放时间( TcpTimedWaitDelay )调整为了 30 秒,并重新进行了测试。 几轮 websocket 连接-断开 之后,通过资源监视器看到反代程序积累了 465 个线程,此时 websoket 客户端处于断开的状态(进程已退出),8908 websocket 服务端正常运行,等待了 10 分钟线程数并未减少。紧接着关闭 8908 服务(退出进程),等待 10 分钟,线程数依然保持不变。 |
3
pathletboy 2022-01-19 11:59:13 +08:00
@Pengxiguaa 有条件的话可以测试下 caddy 反代是不是这样?
|
4
Pengxiguaa OP 官方库对这部分常用场景应该有考虑才对...现在没有头绪,待学习别人反代 websocket 之后再来更新。
|
5
Pengxiguaa OP @pathletboy 好的,感谢提醒
|
6
Pengxiguaa OP @pathletboy
在 windows 10 powershell 通过以下命令启动 caddy ``` # caddy_windows_amd64.exe reverse-proxy --from :10086 --to 127.0.0.1:8908 ``` 也会积累线程,奇怪了。 有时间再测测最多能积累多少线程,会不会导致进程崩溃的问题吧。 |
7
pathletboy 2022-01-19 14:57:24 +08:00
|
8
liaohongxing 2022-01-21 09:22:53 +08:00
测试大量短链接端口不应该在 windows 测试。应该在 linux 测试 ,windows 本身就对 tcp 数量有限制 。其次就是 TCP TIME_WAIT ,不过 windows 的 TCP TIME_WAIT 也不知道怎么设
|
9
liaohongxing 2022-01-21 09:24:12 +08:00
你那报错我也遇到。随便用 hey 测几轮并发 ,windows 马上就报端口不够用了。
|
10
Pengxiguaa OP @pathletboy 功力太浅,看不太明白,只记得在所有连接断开后,goroutine 数目恢复到个位数,而 threadcreate 依然居高不下。
|
11
Pengxiguaa OP @liaohongxing TCP TIME_WAIT 设置看这里: https://docs.microsoft.com/en-us/biztalk/technical-guides/settings-that-can-be-modified-to-improve-network-performance
另外我们生产服务器只有 windows server ... |
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 供参考 |
13
yeqown 2022-02-11 18:07:04 +08:00
其次,看你的错误信息,我猜测你这个代理应该连握手都没办法完成吧~(协议问题),你测试结果有正确的响应吗?
|
14
Pengxiguaa OP @yeqown ReverseProxy 模块中有 websocket 的实现,详情看 https://go.dev/src/net/http/httputil/reverseproxy.go:280,306 。
|