Swoole优雅的实现给在线用户推送websocket广播消息(

2020-03-22  本文已影响0人  骑蚂蚁上高速_jun

前期本人写过一篇关于 Swoole两种方案实现总后台给所有在线用户 群发通知
的文章, 现在研究了一种更好的实现案例。推荐生产环境使用该种方案
直接上案例:

use Swoole\Websocket\Server;
use Swoole\Coroutine as Co;
use Swoole\Runtime;

$server= new Server("0.0.0.0",20001);
/**
 * 重点: 开启环境协程化,使所有的客户端协程话
 */
Runtime::enableCoroutine(SWOOLE_HOOK_ALL | SWOOLE_HOOK_CURL);
$server->set([
    "worker_num"=>2,
    "enable_coroutine"=>true,// 必须开启协程异步化
]);

$server->on("workerStart",function(Server $server,int $workerId){
    $pid=$server->master_pid;
  /**
  * 在子协程中 实现的 redis 订阅端,是异步化的。 并不会影响客户端的连接
  */
    if($workerId ==0){
        Co::create(function()use($server){
            $redis = new Redis();
            $redis->connect("127.0.0.1");
            $redis->setOption(Redis::OPT_READ_TIMEOUT,-1);
            $redis->subscribe(['test'],function(Redis $instance,string $channelName,string $message)use($server){
                /**
                 * 1. 遍历所有的连接,
                 * 2 . 判断所有的 ws客户端连接
                 * 3. 给客户端发送消息
                 */
                foreach ($server->connections as $fd){
                    if($server->isEstablished($fd)){
                        $server->push($fd,"send message to client success!");
                    }
                }
            });
        });
    }
   // 这句话打印的次数与配置中worker_num 是一致的,表示上述redis订阅端并不会影响 worker进程接收请求
    echo "进程{$workerId} 启动\n";
});

$server->on("request",function(\Swoole\Http\Request $request,\Swoole\Http\Response $response){
    $response->status(201);
    $response->header("content-type","text/html;charset=utf-8");
    $response->end("哈哈".getmypid());
});
/**
 * 接收客户端消息触发
 */
$server->on("message",function(Server $server, \Swoole\Websocket\Frame $frame){
    $fd = $frame->fd;
    $data = $frame->data;
    echo "接收到客户端{$fd} 消息: {$data} \n";
});


$server->start();
上一篇下一篇

猜你喜欢

热点阅读