对swoole 中的 Task 任务 的介绍

首先,我们来说下,我们平时在做一些功能时候,例如发邮件,做广播的时候,都需要用到异步进程来操作,下面我举个例子吧。

例如,有10000个人,我们要给这10000个人去发邮件,这时候,按照传统的逻辑还有PHP的单线程机制,是不是只能一个一个用户地去发送,这时候问题就来了,那我如果需要的是在30秒内成功发送邮件到这10000个用户邮箱呢?是不是就会形成了一个等待时间?这时候就需要有一个异步任务,而且还是多线程的去给这10000个用户发送消息。就是我下面说到的 task。

好了,现在开始进入正题吧。

这个task 是基于 HTTP,HTTPserver,udp,tcp,websocket的,所以,我们在swoole中,这些协议都是可以用到task的。

下面我是基于websocket来给大家做演示

要开启task进程,必须要四个条件

1 设置 task_worker_num 配置 Task 进程的数量。【默认值:未配置则不启动 task】

2 worker_num 设置启动的 Worker 进程数。【默认值:CPU 核数】

3 设置 onTask 回调函数

4 设置 onFinish 回调函数

顺便我来说下他们的执行顺序

首先客户端请求 -> onMessge会接受到客户端的信息 -> 启用task -> 回调 onTask -> 回调 onFinish -> 一个进程结束

我是通过监听 http_server.php 这个文件来访问静态资源的,这里面 enable_static_handler 开启了静态资源文件,会默认去到这

个目录帮我找静态资源   /home/wwwroot/default/twj/swoole/data 

然后我们就可以通过访问url http://39.108.6.204:8811/ws_client.html 就可以去到 具体的 ws_client.html 这个文件,这个文件是用

WebSocket 协议来完成的,这里面会和服务端建立握手,从而建立长连接。

这时候建立连接后,我们服务端看到的消息如下



上面的这些打印,是在十秒后出来的,为什么会这样呢?  因为我们的task是异步的进程,所以才会延迟了十秒左右,代码如下

但是这时候,我们的客户端是即时的,因为我开启了task 异步进程

ws_client.html 静态资源文件

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<h1>我是ws测试</h1>
<script>
    var wsUrl = 'ws://39.108.6.204:8812';
    var websocket = new WebSocket(wsUrl);
    // 实例对象的 onopen属性
    websocket.onopen = function (evt) {
        websocket.send('hello=sinwa');
        console.log('coneccted-swoole-success');
    }
    // 实例化 onmessage
    websocket.onmessage = function (evt) {
        console.log('ws-server-return-data:' + evt.data);
    }
    // 关闭
    websocket.onclose = function (evt) {
        console.log('closw');
    }

    websocket.onerror = function (evt, e) {
        console.log('error:' + e.data);
    }

</script>
</body>
</html>

ws.php文件

<?php


class Ws
{

    const HOST = '0.0.0.0';
    const PORT = 8812;
    public $ws = null;

    public function __construct()
    {
        $this->ws = new Swoole\WebSocket\Server("0.0.0.0", 8812);
        $this->ws->set(
            // task_worker_num 配置 Task 进程的数量。【默认值:未配置则不启动 task】
            // worker_num 设置启动的 Worker 进程数。【默认值:CPU 核数】
            [
                'worker_num' => 2,
                'task_worker_num' => 2,// 配置此参数后将会启用 task 功能。所以 Server 务必要注册 onTask、onFinish 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();
    }

    public function onOpen($ws, $request)
    {
        var_dump($request->fd . "\n");
    }

    public function onMessage($ws, $frame)
    {
        echo 'ser-push-message:' . $frame->data . "\n";
        // todo::
        $data = [
            'task' => 1,
            'fd' => $frame->fd,

        ];
        $ws->task($data);// 投递异步耗时任务
        $ws->push($frame->fd, 'server-push:' . date('Y-M-D H:i:s') . "\n");
    }

    /***
     * @param $ws http 或者 ws的对象
     * @param $task_id 任务ID
     * @param $workerId
     * @param $data $ws->task($data);投递的任务
     */
    public function onTask($serv, $taskId, $workerId, $data)
    {
        print_r($data);
        sleep(10);
        return 'on task finish';// 返回内容告诉worker进程
    }

    /***
     * @param $serv
     * @param $taskId
     * @param $data onTask的返回值
     */
    public function onFinish($serv, $taskId, $data)
    {
        echo 'taskId:' . $taskId . "\n";
        echo 'finish-data-sucess:' . $data . "\n";
    }

    public function onClose($ws, $fd)
    {
        echo 'clientid:' . $fd . "\n";
    }
}

$obj = new Ws();

http.server.php 文件

<?php
// 需要在cli运行,不然会报错的
// httpserver 是基于server的
// 监听0.0.0.0 表示监听所有地址
$http = new swoole_http_server('0.0.0.0', 8811);

$http->set(
    [
        'enable_static_handler' => true,//开启静态文件请求处理功能,需配合 document_root 使用 默认 false
        'document_root' => '/home/wwwroot/default/twj/swoole/data',//设置静态处理器的路径。类型为数组,默认不启用
    ]
);
// 上面$htt->set(),如果它有静态资源,就不会再走后面的逻辑了


// $request 请求
// $response 响应
$http->on('request', function ($request, $response) {
//    var_dump($_GET);// 是获取不到的,要通过$request获取
    var_dump($request->get);// 只能在服务器看到,浏览器是看不到的

    // 设置cookie
    $response->cookie('singwa', '值', time() + 1800);

    // 如果要把数据放在浏览器,就要用end()这个方法,而且必须要是string
    $response->end("<h1>HTTPserver</h1>");

});
$http->start();
发布了6 篇原创文章 · 获赞 7 · 访问量 112

猜你喜欢

转载自blog.csdn.net/qq_41672878/article/details/104912745