用workerman做的http服务器,如果用作长轮询的话如何能不造成阻塞呢?
这个是一个长轮训demo
use Workerman\Worker; require_once './Workerman/Autoloader.php'; // 初始化一个worker容器,监听1234端口 $worker = new Worker('http://0.0.0.0:1234'); $worker->count = 1; // 初始化一个数组,用来保存所有的长轮训连接 $poll_connections = array(); /* * 当有客户端发来消息时 * 长轮训拉取数据url格式为 http://xxxx:1234/?type=get&uid=xxx * 向某uid发送数据格url格式 http://xxxx:1234/?type=send&to_uid=xxx&content=xxx */ $worker->onMessage = function($connection, $data) { global $poll_connections; if(empty($_GET)) { return $connection->close('type empty'); } // 这个请求是长轮训活取数据请求 if($_GET === 'get') { // 这里简单的用uid验证用户身份,没传uid视为非法请求 if(!isset($_GET)) { return $connection->close('empty uid'); } // 临时给当前的连接对象添加一个属性保存uid $connection->uid = $_GET; // 保存客户端的连接对象,当需要向这个uid推送数据时需要使用这个对象 $poll_connections = $connection; // 重点是这里,不send任何数据,则会和浏览器一直保持连接 return; } // 这个请求是向某个uid长轮训推送数据 elseif($_GET === 'send') { // 检查参数是否都传了 if(!isset($_GET) || !isset($_GET)) { return $connection->close('to_uid or content empty'); } // 查找to_uid 对应的连接对象,以便向to_uid的浏览器发送数据 if(!isset($poll_connections)) { // to_uid 不在线,发送不在线提示 return $connection->close("uid:{$_GET} offline"); } // 注意这里,向to_uid的浏览器发送了数据 $poll_connections->close($_GET); // 给发送者返回成功提示 $connection->close("send success!"); return; } // type传的不对,非法请求 else { return $connection->close('unknown type :' . $_GET); } }; // 当有客户端连接断开时,删除uid到连接对象的映射 $worker->onClose = function($connection) { global $poll_connections; if(isset($connection->uid)) { unset($poll_connections); } }; // 运行所有的worker(其实当前只定义了一个) Worker::runAll();
在线测试 长轮询接受url http://workerman.net:1234/?type=get&uid=123 http://workerman.net:1234/?type=get&uid=456 http://workerman.net:1234/?type=get&uid=789 ...
发送消息url http://workerman.net:1234/?type=send&to_uid=123&content=hello http://workerman.net:1234/?type=send&to_uid=456&content=hello ...
技巧是不向浏览器send数据,浏览器就会一直等待数据,然后服务端业务该干嘛干嘛,服务端不会阻塞,等需要发送数据时,在向浏览器send。
这样一个worker进程就能维持大量的连接(上万或者数十万),服务端是非阻塞的,性能很高,服务器也不会有任何负载
这个是一个长轮训demo
在线测试
长轮询接受url
http://workerman.net:1234/?type=get&uid=123
http://workerman.net:1234/?type=get&uid=456
http://workerman.net:1234/?type=get&uid=789
...
发送消息url
http://workerman.net:1234/?type=send&to_uid=123&content=hello
http://workerman.net:1234/?type=send&to_uid=456&content=hello
...
技巧是不向浏览器send数据,浏览器就会一直等待数据,然后服务端业务该干嘛干嘛,服务端不会阻塞,等需要发送数据时,在向浏览器send。
这样一个worker进程就能维持大量的连接(上万或者数十万),服务端是非阻塞的,性能很高,服务器也不会有任何负载