Swoole入门 第三个程序 异步task

一、swoole task

  • 常用的场景:异步支付处理、异步订单处理、异步日志处理、异步发送邮件/短信等。
  • Swoole 异步Task,主要实现调用异步任务的执行。实现方式是 worker 进程处理数据请求,分配给 task 进程执行。
  • task 底层使用Unix Socket管道通信,是全内存的,没有IO消耗。单进程读写性能可达100万/s,不同的进程使用不同的管道通信,可以最大化利用多核。

二、 创建异步服务(可执行)

<?php
class Server
{
    private $serv;

    public function __construct(){
        $this->serv = new swoole_server('0,0,0,0',9502);
        $this->serv ->set([
            'worker_num'    =>2, //开启2 个woker 进程
            'max_request'   =>4,//每个worker进程 max_request设置为4次
            'task_worker_num' =>4,  //开启4个task 进程
            'dispatch_mode'  =>2  //数据分包策略 - 固定模式
        ]);

        $this->serv->on('Start', [$this, 'onStart']);
        $this->serv->on('Connect', [$this, 'onConnect']);
        $this->serv->on('Receive', [$this, 'onReceive']);
        $this->serv->on('Close', [$this, 'onClose']);
        $this->serv->on('Task', [$this, 'onTask']);
        $this->serv->on('Finish', [$this, 'onFinsh']);

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

    public function onStart($serv){
        echo "#### onStart ###".PHP_EOL;
        echo "SWOOLE " . SWOOLE_VERSION . " 服务已启动 " . PHP_EOL;
        echo "master_pid: {$serv->master_pid}" . PHP_EOL;
        echo "manager_pid: {$serv->manager_pid}" . PHP_EOL;
        echo "########".PHP_EOL.PHP_EOL;
    }

    public function onConnect($serv, $fd){
        echo "#### onConnect ####" . PHP_EOL;
        echo "客户端:" . $fd . "已连接" . PHP_EOL;
        echo '#######'. PHP_EOL . PHP_EOL;
    }

    public function onReceive($serv, $fd, $form_id, $data){
        echo "### onReceive ####" . PHP_EOL;
        echo "worker_pid: { $serv->worker_pid}" .PHP_EOL;
        echo "客户端: {$fd} 发来的Email:{$data}" . PHP_EOL;
        $param = [
            'fd' =>$fd,
            'email'=> $data
        ];
        $res =  $serv->task(json_encode($param));
        if($res === false){
            echo "任务分配失败 Task " . $res . PHP_EOL;
        }else{
            echo "任务分配成功 Task " . $res . PHP_EOL;
        }

        echo "############" . PHP_EOL . PHP_EOL;
    }

    public function onTask($serv, $task_id, $form_id, $data){
        echo "##### onTask ####" . PHP_EOL;
        echo "#{$serv->worker_id} onTask: [PID = {$serv->worker_pid}] : task_id = {$task_id}" . PHP_EOL;

        //业务代码
        for($i = 1; $i <= 5; $i ++){
            sleep(2);
            echo "Task {task_id} 已完成{$i}/5的任务" . PHP_EOL;
        }

        $data_arr = json_decode($data, true);
        $serv->send($data_arr['fd'], 'Email:)' . $data_arr['email'] . ',发送成功');
        $serv->finish($data);
        echo "######". PHP_EOL . PHP_EOL;
    }
    public function onFinsh($serv, $task_id, $data){
        echo "### onFinsh ####" . PHP_EOL;
        echo "Task {$task_id} 已完成" .PHP_EOL;
        echo "######" . PHP_EOL . PHP_EOL;
    }

    public function onClose($serv, $fd){
        echo "Client Close" . PHP_EOL;
    }
}

$server = new Server();

三 创建异步客户端(执行失败)

引用官方原话:在 Swoole4+ 下所有的业务代码都是同步写法(Swoole1.x 时代才支持异步写法,现在已经移除了异步客户端,对应的需求完全可以用协程客户端实现),完全没有心智负担,符合人类思维习惯!

此处有坑 踩坑踩坑

<?php

class Client
{
    private $client;

    public function __construct(){
       //这里有个坑 swoole 4.3 后不支持这个写法 需要安装扩展ext-async
       //ext-async目前只支持最新 swoole4.4.16 如果你的版本过新 安装这个扩展很可能编译不通过
       // 本人swoole4.5.5 尝试安装失败 建议改成协程写法,暂时不会 哈哈哈 后续试试
        $this->client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);

        $this->client->on('Connect', [$this, 'onConnect']);
        $this->client->on('Recive', [$this, 'onRecive']);
        $this->client->on('Close', [$this, 'onClose']);
        $this->client->on('Error', [$this, 'onError']);
    }

    public function connect(){
        if(!$fp = $this->client->connect("127.0.0.1", 9502, 1)){
            echo "Error: {$fp->errMsg}[{$fp->errCode}]" .PHP_EOL;
            return;
        }
    }

    public function onConnect($cli){
        fwrite(STDOUT, "输入Email:");
        swoole_event_add(STDIN, function(){
            fwrite(STDOUT, "输入Email");
            $msg = trim(fgets(STDIN));
            $this ->send($msg);
        });
    }

    public function onRecive($cli, $data){
        echo PHP_EOL . "Recived: " . $data . PHP_EOL;
    }

    public function send($data){
        $this ->client->send($data);
    }

    public function onClose($cli){
        echo "Client close connection" . PHP_EOL;
    }

    public function onError(){

    }
}

$client = new Client();
$client->connect();

学习整理于https://github.com/xinliangnote/Swoole 不懂可以结合来看或评论

考虑到代码比较传统 不是swoole推崇的协程化 后续不再更新或者后续改成协程代码发出

个人博客停止维护,部分博客转载到这

  • peter
  • 2021-04-17 17:23:01
本作品采用《CC 协议》,转载必须注明作者和本文链接
滴水穿石,石破天惊----晓疯子
zhaocrazy
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!