最近在使用Ratchet (一个PHP websocket框架)改造一个PHP网站的时候,出现了错误:
"It is set to 1024, but you have descriptors numbered at least as high as 1266.
--enable-fd-setsize=2048 is recommended, but you may want to set it
to equal the maximum number of open files supported by your system"
经过几番周折,发现原因是PHP源代码将FD_SIZE设置为1024了,一旦超过1024个websocket连接,就会报这个错。网上的解决方案,基本上是修改PHP源代码,重新编译PHP. 但是个人认为修改PHP源代码的做法存在风险,故我提出了新的思路,并在项目中成功运用(欢迎拍砖)。
基本原理是在后台多开几个websocket服务进程,每个进程用不同的端口号。而前台js随机连接后台开放的websocket服务进程端口号。这样每个websocket服务进程有1024的可用连接数,根据网站的峰值连接数计算可得所需开的websocket服务进程数量,当然需要留些余量。这样不需要重新编译PHP源代码,也能够轻松突破PHP websocket 1024个连接数限制了。
后台的实现
写一个push-server.php作为websocket服务, push-server的实现可以参照Ratchet的例子, 但是需要稍微改造下,即可以输入port作为命令行参数。
$port = $argv[1]; if ($port == ""){ $port = 40003; // 默认端口,如果启动push-server.php时不写参数,则使用40003端口 } // .....省略其他代码 ..... // 将$port作为监听端口传入 $webSock->listen($port, '0.0.0.0');
根据需要,可以启动多个websocket进程,如:
php push-server 40003
php push-server 40004
php push-server 40005
这样后台就可以容许 1024 * 3 = 3072个websocket连接了。
前台的实现
随机获取连接服务的代码如下:
<span function</span><span getWSServer() { </span><span var</span> serverPorts = ['40003', '40004', '40005'<span ]; </span><span var</span> server = 'ws://youhost'<span ; </span><span var</span> randomPortIndex = Math.floor(Math.random() *<span serverPorts.length); server </span>+= ':' +<span serverPorts[randomPortIndex]; </span><span return</span><span server; };</span>
当然你也可以根据自己需要,指定什么时候连接某个websocket服务,不再赘述。