框架 thinkPHP5.0.24 + workerman + GatewayWorker + gatewayclient
使用AsyncTcpConnection类连接欧易交易所 执行的业务逻辑是每收到一条信息就推送给所有客户端 如图
一共有两个任务 (因为接口不一样 所以启动了两个workerman)
GatewayWorker里面没有什么业务代码 只是提供连接 都是通过 gatewayclient推送 下方有截图
启动时是没有问题 过两三个小时就会报错以下错误
stream_socket_client(): Unable to connect to tcp://127.0.0.1:2900 (通常每个套接字地址(协议/网络地址/端口)只允许使用一次。) in E:\php\amm\vendor\workerman\gatewayclient\Gateway.php:1254
windows php8启动脚本
猜测是本地端口消耗光了,用linux系统按照手册优化好linux内核应该就好了
我也这样觉得 但是6万多个端口都用完是不是不太合理
复现步骤我也不清楚 像是随机出现 有时候运行半个小时就会直接报错 有时候五六个小时才会报错
我也遇到和你差不多的情况,我的分析是workerman的原因.
从报错理解上来看,应该是端口耗光了.
我是做压测的时候遇到的,
此时重启workerman该问题还存在,说明它并没有请求结束就关闭通信,
再等个几秒钟,就会自己就好了.我猜测有定时器再检测,导致关闭不及时,所以耗光了端口
这个是网络编程基础知识。
作为客户端(例如gatewayClient)每发起一个TCP连接会占用本地一个临时端口,连接关闭后这个端口不会被操作系统立刻释放,端口进入timewait状态,大概持续60-240s,用来保证连接安全的关闭。如果频繁的发起连接建立和关闭,这个timewait状态的端口数会迅速增加,最终占满所有端口。还有这个端口数不是想象中的6万,一般是1-3万,操作系统保留了一些,通过内核配置可以修改增加数量。
你用ab压测nginx也一样,压测个1-3万个请求就报这个错了。重启nginx也不行,要等一会儿timewait的状态的端口被操作系统释放掉才行。