本地Go Gorilla WebSocket客户端压力测试遇连接上限,求突破10万连接方案
解决10万级WebSocket客户端连接问题
你遇到的cannot assign requested address错误,本质是客户端临时端口耗尽。默认Linux系统的临时端口范围是32768-60999,总共约28232个可用端口,刚好对应你当前的连接上限。要突破10万级连接,需要从系统参数调整和客户端代码优化两方面入手:
一、调整系统网络参数
1. 扩大临时端口范围
修改系统可用的临时端口区间,让客户端能分配到更多端口:
# 临时生效 echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range # 永久生效(写入sysctl配置) echo "net.ipv4.ip_local_port_range = 1024 65535" >> /etc/sysctl.conf sysctl -p
这个调整能将可用临时端口数提升至64512个,配合端口复用可支撑更多连接。
2. 开启TIME_WAIT端口复用
客户端断开连接后,端口会进入TIME_WAIT状态(默认等待60秒),开启复用能让这些端口更快被重新使用:
# 临时生效 echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse # 永久生效 echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf sysctl -p
注意:tcp_tw_reuse仅适用于客户端发起的连接,对服务器端无影响,且不会引发兼容性问题。
3. 调高文件描述符限制
每个网络连接对应一个文件描述符,默认系统限制可能不足10万,需要调整:
# 临时生效(当前终端) ulimit -n 100000 # 永久生效(写入limits配置) echo "* soft nofile 100000" >> /etc/security/limits.conf echo "* hard nofile 100000" >> /etc/security/limits.conf
修改后需要重启终端或系统才能生效。
二、优化Go客户端代码
1. 在Dialer中启用端口复用
创建Gorilla WebSocket的Dialer时,自定义NetDialContext函数,设置SO_REUSEADDR和SO_REUSEPORT选项:
import ( "net" "golang.org/x/net/context" "github.com/gorilla/websocket" ) func main() { dialer := websocket.Dialer{ NetDialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { conn, err := net.Dial(network, addr) if err != nil { return nil, err } // 启用端口复用并关闭 linger 加速端口释放 tcpConn := conn.(*net.TCPConn) tcpConn.SetLinger(0) tcpConn.SetReuseAddr(true) tcpConn.SetReusePort(true) return tcpConn, nil }, // 可根据需求设置读写缓冲区大小,减少内存占用 ReadBufferSize: 1024, WriteBufferSize: 1024, } // 循环创建连接的逻辑... }
2. 优化资源管理
- 避免每个连接创建冗余goroutine,可批量处理连接的读写逻辑,或用
sync.Pool复用资源 - 确保连接异常断开时及时关闭并清理资源,避免内存泄漏
- 设置合理的Dial超时,防止连接创建过程阻塞
三、服务器端配套优化
要支撑10万级连接,服务器端也需要同步调整:
- 调高服务器的文件描述符限制(同客户端步骤)
- 开启服务器端的
SO_REUSEPORT选项,让多个线程/进程可监听同一端口,提升并发处理能力 - 调整Go服务器的
GOMAXPROCS,充分利用CPU资源:runtime.GOMAXPROCS(runtime.NumCPU())
通过以上调整,你应该能突破当前的连接上限,实现10万级WebSocket客户端连接的测试需求。
内容的提问来源于stack exchange,提问作者Hachour Fouad
相关产品推荐
相关产品推荐

