Swoole入门 - 异步 Task

2019-06-03  本文已影响0人  铁匠简记

在Server程序中如果需要执行很耗时的操作,比如一个聊天服务器发送广播,Web服务器中发送邮件、短信。如果直接去执行这些函数就会阻塞当前进程,导致服务器响应变慢。
Swoole提供了异步任务处理的功能,可以投递一个异步任务到TaskWorker进程池中执行,不影响当前请求的处理速度。

实现

基于第一个WS服务器,只需要增加onTask和onFinish 2个事件回调函数即可,onFinish事件接收onTask事件执行完毕后的返回值。另外需要设置task进程数量,可以根据任务的耗时和任务量配置适量的task进程。

场景

当收到来自客户端的消息,执行一个耗时10秒的代码逻辑(如发送邮件),再去返回客户端消息,这个时候客户端就需要等待至少10秒,用户体验是非常差的。
onTask事件的编写,我们可以查看官方文档


<?php
class WS {
    public $server;
    public function __construct() {
        $this->server = new Swoole\WebSocket\Server('0.0.0.0', 8812);
        $this->server->set([
                'worker_num' => 2,
                'task_worker_num' => 2
        ]);
        $this->server->on('open', [$this, 'onOpen']);
        $this->server->on('message', [$this, 'onMessage']);
        $this->server->on('task', [$this, 'onTask']);
        $this->server->on('finish', [$this, 'onFinish']);
        $this->server->on('close', [$this, 'onClose']);

        $this->server->start();
    }

    public function onOpen($server,$request)
    {
        echo "server: handshake success with fd{$request->fd}\n";
        // todo 10s
        $data = [
                'task' => 1,
                'fd'   => $request->fd
        ];
        $server->task($data);
        $server->push($request->fd,'server-push:'.date('Y-m-d H:i:s'));
    }

    public function onMessage($server,$frame)
    {
        echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
        $server->push($frame->fd, "this is server");
    }

    public function onTask($server, $taskId, $workerId, $data)
    {
        print_r($data);
        // 耗时场景 10s
        sleep(10);
        return 'on task 10s finish';   // 告诉worker
    }

    public function onFinish($server, $taskId, $data)
    {
        echo "taskId:{$taskId}\n";
        echo "finish-data-success:{$data}\n"
    }

    public function onClose($server,$fd)
    {
        echo "client {$fd} closed\n";
    }
}
$obj = new WS();

测试

开启http服务,ws服务。

开启HTTP服务
开启WebSocket服务
浏览器访问http://127.0.0.1:8811/ws_client.html。通过HTTP服务启动ws客户端连接WebSocket服务,进入浏览器控制台可以看到,onFinish中的逻辑是在最后执行的,而在onOpen事件中,在投递task任务之后的逻辑并没有等Task的逻辑执行完再执行,这是因为Swoole的Task是异步处理的。
用ws.html调起ws客户端 10s逻辑执行中
10s逻辑执行完

HTTP服务,TCP都是可以基于这种形式做Task任务投放的。

上一篇下一篇

猜你喜欢

热点阅读