继上篇 2018年swoole实战1-初识swoole
项目中,总有一些场景会触发耗时比较长的行为。如:用户更新了文章,触发推送消息给此用户的所有粉丝,如果一个用户有10000个粉丝,用同步阻塞的方式来实现,肯定会被吐槽死,这种场景必须用非阻塞的方式实现,让用户无感知。
swoole的task任务投递功能可实现异步非阻塞的功能
以下通过三体人与ETO组织的对话场景来模块此功能:
废话不多说,亮代码吧...
服务端
新建 server.php
ws = new swoole_websocket_server(self::HOST, self::PORT);
$this->ws->set(
[
'worker_num' => 2,
'task_worker_num' => 2,
]
);
$this->ws->on('open', [$this, 'onOpen']);
$this->ws->on('message', [$this, 'onMessage']);
$this->ws->on('task', [$this, 'onTask']);
$this->ws->on('finish', [$this, 'onFinish']);
$this->ws->on('close', [$this, 'onClose']);
$this->ws->start();
}
/**
* 监听连接事件
* @param $ws
* @param $request
*/
public function onOpen($ws, $request) {
echo "收到地球人的连接请求,客户端id:{$request->fd}\n";
}
/**
* 监听数据发送事件
* @param $ws
* @param $frame
*/
public function onMessage($ws, $frame) {
echo "地球人发送的数据:{$frame->data}\n";
echo "元首:让他们去清理掉面壁者吧...\n";
// 投递任务
$data = [
'task' => '全力加速水滴...\n',
'fd' => $frame->fd,
];
$time = date('Y-m-d H:i:s', time());
$ws->push($frame->fd, "清理所有的面壁者, 重点是要不引起任何人注意,无声无息地干掉罗辑!" . $time);
$ws->task($data); // 投递任务
$time = date('Y-m-d H:i:s', time());
$ws->push($frame->fd, "接下来会有水滴协助你们,水滴已经在加速前进了,等水滴到达,我们就无所畏惧了... " . $time);
}
/**
* 执行投递的任务
* @param $server
* @param $taskId
* @param $workerId
* @param $data
* @return array
*/
public function onTask($server, $taskId, $workerId, $data) {
echo $data['task'];
sleep(5);
$time = date('Y-m-d H:i:s', time());
return [
'fd' => $data['fd'],
'message' => '水滴加速完成 ' . $time,
];
}
/**
* 任务完成后的回调
* @date 2018-07-27
* @param $server
* @param $taskId
* @param $data
*/
public function onFinish($server, $taskId, $data) { // $data 是 onTask 返回的内容
$server->push($data['fd'], $data['message']); // 通知客户端,任务已经完成
}
public function onClose($ws, $fd) {
}
}
$obj = new WebSocket();
客户端
新建 client.html
webSocket客户端
swoole异步非阻塞投递任务
启动服务
☁ ws php server.php
[2018-07-27 11:50:13 @59805.0] TRACE Create swoole_server host=0.0.0.0, port=8812, mode=3, type=1
代码解析
如果觉得本文对你有所帮助,点个赞,或者赏杯咖啡钱,你的认可对我很重要