EasySwoole 使用


EasySwoole 使用


引言

这里写一些EasySwoole使用中碰到的知识点。

异步任务Task

安装:

composer require easyswoole/task

配置:

<?php

// 这里省略

return [
    // 这里省略 ...

    'MAIN_SERVER' => [

        // 这里省略 ...

        'TASK' => [
            'workerNum' => 4,
            'maxRunningNum' => 128,
            'timeout' => 15
        ]
    ],

    // 这里省略 ...
];

查看所有Task进程的状态:

php easyswoole task status

输出挺有意思:

┌---------┬---------┬------┬-----┬---------------------┬-------------┐
│ running │ success │ fail │ pid │     startUpTime     │ workerIndex │
├---------┼---------┼------┼-----┼---------------------┼-------------┤
│ 0       │ 10      │ 0    │ 78  │ 2023-11-22 10:40:26 │ 0           │
├---------┼---------┼------┼-----┼---------------------┼-------------┤
│ 0       │ 6       │ 0    │ 79  │ 2023-11-22 10:40:26 │ 1           │
├---------┼---------┼------┼-----┼---------------------┼-------------┤
│ 0       │ 3       │ 0    │ 80  │ 2023-11-22 10:40:26 │ 2           │
├---------┼---------┼------┼-----┼---------------------┼-------------┤
│ 0       │ 6       │ 0    │ 81  │ 2023-11-22 10:40:26 │ 3           │
└---------┴---------┴------┴-----┴---------------------┴-------------┘

具体使用有两种方式:闭包函数、任务模板。

一、异步调用选择闭包函数

调用:

\EasySwoole\EasySwoole\Task\TaskManager::getInstance()->async(function () {
    echo 'async';
}, function ($reply, $taskId, $workerIndex) {
    // $reply 返回的执行结果
    // $taskId 任务id
    echo 'async success';
});

二、异步调用选择任务模版

先定义模板:

<?php

namespace App\Task;

use EasySwoole\Task\AbstractInterface\TaskInterface;

class CustomTask implements TaskInterface
{
    protected $data;

    public function __construct($data)
    {
        // 保存投递过来的数据
        $this->data = $data;
    }

    public function run(int $taskId, int $workerIndex)
    {
        // 执行逻辑
        echo $this->data['user'];  // 运行在Task进程中,命令行查看输出
    }

    public function onException(\Throwable $throwable, int $taskId, int $workerIndex)
    {
        // 异常处理
    }
}

调用:

$task = \EasySwoole\EasySwoole\Task\TaskManager::getInstance();

// 投递异步任务
$task->async(new CustomTask(['user' => 'custom']));

注意点:

  • Task任务运行在Task进程上,与主进程共用同一个命令行客户端,可以使用输出命令很方便的进行调试。

客户端fd链接

如何获取客户端fd链接,这里说一下。

服务通过单例模式启动,我们在项目中可以随时获取该服务:

$server = \EasySwoole\EasySwoole\ServerManager::getInstance()->getSwooleServer();

服务监听和管理客户端fd链接,我们可以在该服务中获取客户端fd链接的信息。

一、获取服务中的所有fd链接并群发信息

$server = \EasySwoole\EasySwoole\ServerManager::getInstance()->getSwooleServer();

$start_fd = 0;
while(true)
{
    $conn_list = $server->getClientList($start_fd, 10);
    if ($conn_list === false or count($conn_list) === 0) {
        echo "finish\n";
        break;
    }

    $start_fd = end($conn_list);

    foreach($conn_list as $fd) {
        $server->send($fd, "broadcast");
    }
}

二、获取一个fd链接的信息

$server = \EasySwoole\EasySwoole\ServerManager::getInstance()->getSwooleServer();
$fdinfo = $server->getClientInfo($fd);  

输出信息看一下:

Array
(
    [server_port] => 9252
    [server_fd] => 3
    [socket_fd] => 63
    [socket_type] => 1
    [remote_port] => 14575
    [remote_ip] => 192.168.0.143
    [reactor_id] => 3
    [connect_time] => 1700624918
    [last_time] => 1700624924
    [last_recv_time] => 1700624924.2119
    [last_send_time] => 1700624922.3476
    [last_dispatch_time] => 1700624924.2119
    [close_errno] => 0
    [recv_queued_bytes] => 0
    [send_queued_bytes] => 0
)

三、Socket控制器 的 自定义解析器 中获取fd链接

class TestParser implements \EasySwoole\Socket\AbstractInterface\ParserInterface 
{
    public function decode($raw,$client) : ?\EasySwoole\Socket\Bean\Caller
    {
        $fd = $client->getFd();
    }

    public function encode(\EasySwoole\Socket\Bean\Response $response,$client) : ?string
    {
        $fd = $client->getFd();
    }
}

IOC 容器

Dependency Injection 依赖注入。EasySwoole 实现了简单版的 IOC 容器。

设置:

<?php
// 获取依赖注入组件 IoC 容器 对象
$di = \EasySwoole\Component\Di::getInstance();

$di->set('test', new TestClass());
$di->set('test', TestClass::class);

// set 的时候储存的是[类名, 方法名]的数组,需要自己手动调用 call_user_func() 执行(不要被错误与异常章节的 demo 误解为会自动执行)
$di->set('test', [TestClass::class,'testFunction']);

// set 的时候传递了类名,get 的时候才去 new 对象,并且将可变变量传递进构造函数,返回实例化后的对象
$di->set('test', TestClass::class, $arg_one, $arg_tow);

使用:

<?php
// 获取依赖注入组件 IoC 容器 对象
$di = \EasySwoole\Component\Di::getInstance();

// 获取 IoC 容器 中某个注入的内容
$val = $di->get('test');

// 删除 IoC 容器 中某个注入的内容
$di->delete('test');

// 清空 IoC 容器 的所有内容
$di->clear('test');

自定义进程

一、定义自定义进程类

<?php
namespace App\Process;

use EasySwoole\Component\Process\AbstractProcess;
use Swoole\Process;

class CustomProcess extends AbstractProcess
{
    protected function run($arg)
    {
        // TODO: Implement run() method.
        $processName = $this->getProcessName(); // 获取 注册进程名称
        $swooleProcess = $this->getProcess(); // 获取 注册进程的实例 \Swoole\Process
        $processPid = $this->getPid(); // 获取 当前进程 Pid
        $args = $this->getArg(); // 获取 注册进程时传递的参数

        var_dump('### 开始运行自定义进程 start ###');
        var_dump($processName, $swooleProcess, $processPid, $args);
        var_dump('### 运行自定义进程结束 end ###');
    }

    protected function onPipeReadable(Process $process)
    {
        // 该回调可选
        // 当主进程对子进程发送消息的时候 会触发
        $recvMsgFromMain = $process->read(); // 用于获取主进程给当前进程发送的消息
        var_dump('收到主进程发送的消息: ');
        var_dump($recvMsgFromMain);
    }

    protected function onException(\Throwable $throwable, ...$args)
    {
        // 该回调可选
        // 捕获 run 方法内抛出的异常
        // 这里可以通过记录异常信息来帮助更加方便地知道出现问题的代码
    }

    protected function onShutDown()
    {
        // 该回调可选
        // 进程意外退出 触发此回调
        // 大部分用于清理工作
    }

    protected function onSigTerm()
    {
        // 当进程接收到 SIGTERM 信号触发该回调
    }
}

二、注册进程

在项目根目录的 EasySwooleEvent.php 文件的 mainServerCreate 方法中进行进程注册

<?php

namespace EasySwoole\EasySwoole;

use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;

class EasySwooleEvent implements Event
{
    public static function initialize()
    {
        date_default_timezone_set('Asia/Shanghai');
    }

    public static function mainServerCreate(EventRegister $register)
    {
        $processConfig = new \EasySwoole\Component\Process\Config([
            'processName' => 'CustomProcess', // 设置 进程名称为 TickProcess
            'processGroup' => 'Custom', // 设置 进程组名称为 Tick
            'arg' => [
                'arg1' => 'this is arg1!',
            ], // 传递参数到自定义进程中
            'enableCoroutine' => true, // 设置 自定义进程自动开启协程环境
        ]);

        // 【推荐】使用 \EasySwoole\Component\Process\Manager 类注册自定义进程
        $customProcess = (new \App\Process\CustomProcess($processConfig));
        // 【可选操作】把 tickProcess 的 Swoole\Process 注入到 Di 中,方便在后续控制器等业务中给自定义进程传输信息(即实现主进程与自定义进程间通信)
        \EasySwoole\Component\Di::getInstance()->set('customSwooleProcess', $customProcess->getProcess());
        // 注册进程
        \EasySwoole\Component\Process\Manager::getInstance()->addProcess($customProcess);
    }
}

三、向自定义进程中传递消息

<?php

namespace App\HttpController;

use EasySwoole\Component\Di;
use EasySwoole\Http\AbstractInterface\Controller;

class Index extends Controller
{
    public function index()
    {
        // 获取 Di 中注入的 自定义进程
        $customProcess = Di::getInstance()->get('customSwooleProcess');
        // 向自定义进程中传输信息,会触发自定义进程的 onPipeReadable 回调
        $customProcess->write('this is test!');
    }
}

四、进程管理命令

执行 php easyswoole process -h 来查看具体操作。

显示所有进程

php easyswoole process show

如果想要以 MB 形式显示:

php easyswoole process show -d

杀死指定进程(PID)

php easyswoole process kill --pid=PID

杀死指定进程组(GROUP)

php easyswoole process kill --group=GROUP_NAME

杀死所有进程

php easyswoole process killAll

强制杀死进程

php easyswoole process kill --pid=PID -f

协程

一、创建协程

方式一、go

<?php
function task1(){
    for ($i=0;$i<=300;$i++){
        //写入文件,大概要3000微秒
        usleep(3000);
        echo "写入文件{$i}\n";
        Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
    }
}
function task2(){
    for ($i=0;$i<=500;$i++){
        //发送邮件给500名会员,大概3000微秒
        usleep(3000);
        echo "发送邮件{$i}\n";
        Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
    }
}
function task3(){
    for ($i=0;$i<=100;$i++){
        //模拟插入100条数据,大概3000微秒
        usleep(3000);
        echo "插入数据{$i}\n";
        Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
    }
}

$pid1 = go('task1');//go函数是swoole的开启协程函数,用于开启一个协程
$pid2 = go('task2');
$pid3 = go('task3');

方式二、Coroutine

<?php
\Swoole\Coroutine::create(function () {
    /* 调用协程API */

    // 用户可以在这里调用上述协程 API
});

二、WaitGroup等待所有任务完成

<?php
go(function () {
    $ret = [];

    $wait = new \EasySwoole\Component\WaitGroup();

    $wait->add();
    // 启动第 1 个协程
    go(function () use ($wait, &$ret) {
        // 模拟耗时任务 1
        \co::sleep(0.1);
        $ret[] = time();
        $wait->done();
    });

    $wait->add();
    // 启动第 2 个协程
    go(function () use ($wait, &$ret) {
        // 模拟耗时任务 2
        \co::sleep(2);
        $ret[] = time();
        $wait->done();
    });

    // 挂起当前协程,等待所有任务完成后恢复
    $wait->wait();

    // 这里 $ret 包含了 2 个任务执行结果
    var_dump($ret);
});

Timer定时器

一、循环执行

// 每隔 10 秒执行一次
\EasySwoole\Component\Timer::getInstance()->loop(10 * 1000, function () {
    echo "this timer runs at intervals of 10 seconds\n";
});

二、延时执行

// 10 秒后执行一次
\EasySwoole\Component\Timer::getInstance()->after(10 * 1000, function () {
    echo "ten seconds later\n";
});

三、清除定时器

$timerId = \EasySwoole\Component\Timer::getInstance()->loop(2 * 1000, function () {
    echo "timeout\n";
},'time_name');

var_dump($timerId); // int(1)

// 清除该定时器
$ret = \EasySwoole\Component\Timer::getInstance()->clear($timerId);
var_dump($ret); // bool(true)

// 定时器得不到执行 不输出:timeout

四、注意点一

在定时器循环执行中为了防止因为任务阻塞而引起定时器不准确,可以把任务给异步进程处理:

// 每隔 10 秒执行一次
\EasySwoole\Component\Timer::getInstance()->loop(10 * 1000, function () {
    // 把任务给异步进程处理
    \EasySwoole\EasySwoole\Task\TaskManager::getInstance()->async(function () {
        echo 'async';
    }, function ($reply, $taskId, $workerIndex) {
        // $reply 返回的执行结果
        // $taskId 任务id
        echo 'async success';
    });
});

五、注意点二

当定时器在类的方法中时,可以在定时器内直接调用类中的变量:

Class A 
{
    pretected $x;

    public function abc () 
    {
        $this->x = 1;
        $y = 2;
        
        \EasySwoole\Component\Timer::getInstance()->after(10 * 1000, function () use ($y) {
            echo $this->x . PHP_EOL;  // 类变量可以直接使用
            echo $y . PHP_EOL;  // 这个变量必须要 use 引入
        });
    }
}

// 输出结果
1
2

六、小结点

1、使用定时器的目的就一个:过一段时间后执行一个任务。这里有两个分支:执行、不执行,只要加上判断形成闭环就可以。 有一种任务不需要判断,到时直接执行就可以了。还有一种任务是如果执行会影响到其他任务的执行,从而导致系统异常, 这里需要考虑清楚,怎么判断,以及怎么取消定时任务。根据 $timerId 取消任务执行时,要注意各个任务在项目中的时间线, 别取消了其他任务的执行。

Crontab分钟级定时任务

一、定义定时任务类,新增 \App\Crontab\CustomCrontab 文件

<?php

namespace App\Crontab;

use EasySwoole\Crontab\JobInterface;

class CustomCrontab implements JobInterface
{
    public function jobName(): string
    {
        // 定时任务的名称
        return 'CustomCrontab';
    }

    public function crontabRule(): string
    {
        // 定义执行规则 根据 Crontab 来定义
        // 这里是每分钟执行 1 次
        return '*/1 * * * *';
    }

    public function run()
    {
        // 定时任务的执行逻辑

        // 相当于每分钟打印1次时间戳,这里只是参考示例。
        echo time();
    }

    public function onException(\Throwable $throwable)
    {
        // 捕获 run 方法内所抛出的异常
    }
}

二、注册定时任务,在项目根目录的 EasySwooleEvent.php 文件的 mainServerCreate 方法中进行定时任务注册

<?php

namespace EasySwoole\EasySwoole;

use App\Crontab\CustomCrontab;
use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;
use EasySwoole\EasySwoole\Crontab\Crontab;

class EasySwooleEvent implements Event
{
    public static function initialize()
    {
        date_default_timezone_set('Asia/Shanghai');
    }

    public static function mainServerCreate(EventRegister $register)
    {
        ###### 注册一个定时任务 ######
        // 配置定时任务
        $crontabConfig = new \EasySwoole\Crontab\Config();

        // 1.设置执行定时任务的 socket 服务的 socket 文件存放的位置,默认值为 当前文件所在目录
        // 这里设置为框架的 Temp 目录
        $crontabConfig->setTempDir(EASYSWOOLE_TEMP_DIR);

        // 2.设置执行定时任务的 socket 服务的名称,默认值为 'EasySwoole'
        $crontabConfig->setServerName('EasySwoole');

        // 3.设置用来执行定时任务的 worker 进程数,默认值为 3
        $crontabConfig->setWorkerNum(3);

        // 4.设置定时任务执行出现异常的异常捕获回调
        $crontabConfig->setOnException(function (\Throwable $throwable) {
            // 定时任务执行发生异常时触发(如果未在定时任务类的 onException 中进行捕获异常则会触发此异常回调)
        });

        // 创建定时任务实例
        $crontab = \EasySwoole\EasySwoole\Crontab\Crontab::getInstance($crontabConfig);

        // 注册定时任务
        $crontab->register(new CustomCrontab());
    }
}

Crontab秒级定时任务

EasySwoole 没有直接提供最小粒度为秒级的定时任务,可以通过使用 EasySwoole 的自定义进程组件 + 协程 Sleep 实现。

一、创建一个秒级定时任务类(自定义进程类)

<?php

namespace App\Crontab;

use EasySwoole\Component\Process\AbstractProcess;

class SecondCrontab extends AbstractProcess
{
    protected function run($arg)
    {
        while(1) {

            // 这里写执行逻辑
            // to do something.

            // 这里表示每秒打印一个日期时间字符串,仅供参考
            var_dump(date('Y-m-d H:i:s'));

            // 休息1秒
            \Co::sleep(1);
        }
    }
}

二、注册秒级定时任务

项目根目录的 EasySwooleEvent.php 文件的 initialize 或者 mainServerCreate 方法中进行秒级定时任务注册。

<?php

namespace EasySwoole\EasySwoole;

use App\Crontab\SecondCrontab;
use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;

class EasySwooleEvent implements Event
{
    public static function initialize()
    {
        date_default_timezone_set('Asia/Shanghai');

        ###### 注册秒级定时任务 ######
        $process = new SecondCrontab(new \EasySwoole\Component\Process\Config([
            'enableCoroutine' => true
        ]));
        \EasySwoole\Component\Process\Manager::getInstance()->addProcess($process);
    }

    public static function mainServerCreate(EventRegister $register)
    {

    }
}

批量更新数据表数据

EasySwoole中ORM没有批量更新的方法,我们需要自己写sql语句,如下:

$queryBuild = (new \EasySwoole\Mysqli\QueryBuilder())->where('id', [2, 3], 'IN')->update('mails', [
    'status' => 1,
    'updated_time' => date('Y-m-d H:i:s'),
]);
\EasySwoole\ORM\DbManager::getInstance()->query($queryBuild);

QueryBuilder 用来构建 SQL 语句,DbManager 进行执行。

join查询

有一个ORM的join示例:

$join_data = TestUserListModel::create()->alias('list')->join('table2 as t2','t2.col1 = list.col2')->all();

如何访问返回的join关联表的数据呢?

可以使用toArray($notNul = false, $strict = true)结果转换数组方法。

  • $notNul 是否过滤空,bool类型 默认false,当为true时,只返回非空字段
  • $strict 严格模式,bool类型 默认true,当为true时,只返回当前模型对应数据表的字段,其他field别名等不返回。

这里的查询可以有下面两种访问join关联表数据的方式:

// 方式1,针对返回Collection的($config->setReturnCollection(true);)
$join_data = TestUserListModel::create()->alias('list')->join('table2 as t2','t2.col1 = list.col2')->all()->toArray(false, false);

// 方式2
$join_data = TestUserListModel::create()->alias('list')->join('table2 as t2','t2.col1 = list.col2')->all();
foreach ($join_data as $one) {
    $data = $one->toArray(false, false);
}

Redis事务

EasySwoole的官方文档中对Redis事务的使用说明,参阅 https://www.easyswoole.com/Components/Redis/transaction.html ,不过内容并不详细。 具体Redis事务的文档,可以参阅 http://doc.redisfans.com/topic/transaction.html

这里举一个例子:

use EasySwoole\Component\Di;  
use Swoole\Coroutine\Redis;  

......

 // 获取Redis实例  
$redis = Di::getInstance()->getBean('redis');  

// 开启事务  
$redis->multi();  

try {  
    // 执行一系列Redis命令  
    $redis->set('key1', 'value1');  
    $redis->set('key2', 'value2');  
    $redis->incr('counter');  

    // 提交事务  
    $redis->exec();  

    // 事务执行成功  
    echo "事务执行成功!";  
} catch (\Exception $e) {  
    // 发生异常,回滚事务  
    $redis->discard();  

    // 事务执行失败  
    echo "事务执行失败:{$e->getMessage()}";  
}  

进程查看

查看项目服务状态(粘贴下面命令行输出时注意下半角全角):

php easyswoole server status

┌------------------------┬----------------------┐
│         item           │        value         │
├------------------------┼----------------------┤
│ start_time             │ 2023-12-27 14:15:07  │
├------------------------┼----------------------┤
│ connection_num         │ 1                    │
├------------------------┼----------------------┤
│ abort_count            │ 0                    │
├------------------------┼----------------------┤
│ accept_count           │ 1                    │
├------------------------┼----------------------┤
│ close_count            │ 0                    │
├------------------------┼----------------------┤
│ worker_num             │ 8                    │
├------------------------┼----------------------┤
│ task_worker_num        │ 0                    │
├------------------------┼----------------------┤
│ user_worker_num        │ 18                   │
├------------------------┼----------------------┤
│ idle_worker_num        │ 8                    │
├------------------------┼----------------------┤
│ dispatch_count         │ 67                   │
├------------------------┼----------------------┤
│ request_count          │ 67                   │
├------------------------┼----------------------┤
│ response_count         │ 68                   │
├------------------------┼----------------------┤
│ total_recv_bytes       │ 3693                 │
├------------------------┼----------------------┤
│ total_send_bytes       │ 10565                │
├------------------------┼----------------------┤
│ pipe_packet_msg_id     │ 137                  │
├------------------------┼----------------------┤
│ session_round          │ 1                    │
├------------------------┼----------------------┤
│ min_fd                 │ 3                    │
├------------------------┼----------------------┤
│ max_fd                 │ 65                   │
├------------------------┼----------------------┤
│ worker_request_count   │ 0                    │
├------------------------┼----------------------┤
│ worker_response_count  │ 0                    │
├------------------------┼----------------------┤
│ worker_dispatch_count  │ 0                    │
├------------------------┼----------------------┤
│ coroutine_num          │ 2                    │
├------------------------┼----------------------┤
│ coroutine_peek_num     │ 2                    │
├------------------------┼----------------------┤
│ runMode                │ dev                  │
└------------------------┴----------------------┘

查看所有进程(主进程worker_num为8,TASK的worker_num为4):

php easyswoole process show -d

┌------┬----------------------------┬--------------------┬------------┬----------------┬--------------------┬----------------------------------┐
│  pid │            name            │       group        │ memoryUsage│ memoryPeakUsage│     startUpTime    │               hash               │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  193 │ test.Worker.0              │ test.Worker        │ 5.83 mb    │ 8 mb           │ 2023-12-27 14:15:07│                                  │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  195 │ test.Worker.1              │ test.Worker        │ 8.62 mb    │ 10 mb          │ 2023-12-27 14:15:07│                                  │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  196 │ test.Worker.2              │ test.Worker        │ 4.49 mb    │ 6 mb           │ 2023-12-27 14:15:07│                                  │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  197 │ test.Worker.3              │ test.Worker        │ 4.49 mb    │ 6 mb           │ 2023-12-27 14:15:07│                                  │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  198 │ test.Worker.4              │ test.Worker        │ 4.49 mb    │ 6 mb           │ 2023-12-27 14:15:07│                                  │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  199 │ test.Worker.5              │ test.Worker        │ 4.49 mb    │ 6 mb           │ 2023-12-27 14:15:07│                                  │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  200 │ test.Worker.6              │ test.Worker        │ 4.49 mb    │ 6 mb           │ 2023-12-27 14:15:07│                                  │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  201 │ test.Worker.7              │ test.Worker        │ 4.49 mb    │ 6 mb           │ 2023-12-27 14:15:07│                                  │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  215 │ test.TaskWorker.0          │ test.TaskWorker    │ 6.65 mb    │ 8 mb           │ 2023-12-27 14:15:07│ 00000000056b61bf000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  216 │ test.TaskWorker.1          │ test.TaskWorker    │ 6.65 mb    │ 8 mb           │ 2023-12-27 14:15:07│ 00000000056b61ba000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  217 │ test.TaskWorker.2          │ test.TaskWorker    │ 6.73 mb    │ 8 mb           │ 2023-12-27 14:15:07│ 00000000056b61a5000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  218 │ test.TaskWorker.3          │ test.TaskWorker    │ 6.65 mb    │ 8 mb           │ 2023-12-27 14:15:07│ 00000000056b61a0000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  219 │ test.Bridge                │ test.Bridge        │ 4.51 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b61a8000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  211 │ EasySwoole.Render.Worker.0 │ EasySwoole.Render  │ 4.5 mb     │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6140000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  212 │ EasySwoole.Render.Worker.1 │ EasySwoole.Render  │ 4.5 mb     │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6143000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  213 │ EasySwoole.Render.Worker.2 │ EasySwoole.Render  │ 4.5 mb     │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b614e000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  214 │ test.Crontab               │ EasySwoole.Crontab │ 4.96 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b61b4000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  202 │ Actor.Proxy.1              │                    │ 4.5 mb     │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6109000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  203 │ Actor.Proxy.2              │                    │ 4.51 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b610c000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  204 │ Actor.Proxy.3              │                    │ 4.5 mb     │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6107000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  205 │ Actor.Worker.oneActor      │                    │ 4.51 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6172000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  206 │ Actor.Worker.oneActor      │                    │ 4.51 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6179000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  207 │ Actor.Worker.oneActor      │                    │ 4.51 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6166000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  208 │ Actor.Worker.twoActor      │                    │ 4.51 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6163000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  209 │ Actor.Worker.twoActor      │                    │ 4.51 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6168000000001f5c7a6c │
├------┼----------------------------┼--------------------┼------------┼----------------┼--------------------┼----------------------------------┤
│  210 │ Actor.Worker.twoActor      │                    │ 4.51 mb    │ 6 mb           │ 2023-12-27 14:15:07│ 00000000056b6155000000001f5c7a6c │
└------┴----------------------------┴--------------------┴------------┴----------------┴--------------------┴----------------------------------┘

查看所有注册的 Crontab:

php easyswoole crontab show

┌------------┬------------┬--------------┬--------------------┬--------------------┬--------┐
│  taskName  │  taskRule  │ taskRunTimes │  taskNextRunTime   │ taskCurrentRunTime │ isStop │
├------------┼------------┼--------------┼--------------------┼--------------------┼--------┤
│ RaceBegin  │*/1 * * * * │ 24           │2023-12-27 14:40:00 │ 2023-12-27 14:39:00│ 0      │
├------------┼------------┼--------------┼--------------------┼--------------------┼--------┤
│ DayLogClear│* 1 * * *   │ 0            │2023-12-28 01:00:00 │ 1970-01-01 08:00:00│ 0      │
├------------┼------------┼--------------┼--------------------┼--------------------┼--------┤
│ Notice     │*/1 * * * * │ 24           │2023-12-27 14:40:00 │ 2023-12-27 14:39:00│ 0      │
├------------┼------------┼--------------┼--------------------┼--------------------┼--------┤
│ RobotJoin  │*/2 * * * * │ 12           │2023-12-27 14:40:00 │ 2023-12-27 14:38:00│ 0      │
└------------┴------------┴--------------┴--------------------┴--------------------┴--------┘

查看 Task 进程状态:

php easyswoole task status

┌---------┬---------┬------┬-----┬---------------------┬-------------┐
│ running │ success │ fail │ pid │     startUpTime     │ workerIndex │
├---------┼---------┼------┼-----┼---------------------┼-------------┤
│ 0       │ 11      │ 0    │ 215 │ 2023-12-27 14:15:07 │ 0           │
├---------┼---------┼------┼-----┼---------------------┼-------------┤
│ 0       │ 16      │ 0    │ 216 │ 2023-12-27 14:15:07 │ 1           │
├---------┼---------┼------┼-----┼---------------------┼-------------┤
│ 0       │ 18      │ 0    │ 217 │ 2023-12-27 14:15:07 │ 2           │
├---------┼---------┼------┼-----┼---------------------┼-------------┤
│ 0       │ 16      │ 0    │ 218 │ 2023-12-27 14:15:07 │ 3           │
└---------┴---------┴------┴-----┴---------------------┴-------------┘

问题

报错

初次运行时会报错:

Fatal error: Namespace declaration statement has to be the very first statement or after any declare call 
in the script in /var/www/html/easyswoole_test/vendor/bin/easyswoole on line 14

需要修改项目内文件 /vendor/bin/easyswoole 的头部内容。

#!/usr/bin/env php
<?php

把上面一行屏蔽掉:

<?php
//#!/usr/bin/env php






参考资料

EasySwoole文档 https://www.easyswoole.com/Preface/intro.html

Swoole文档 https://wiki.swoole.com

EasySwoole 3.x 中文文档 https://www.mianshigee.com/tutorial/easyswoole-3.x-zh/noobcourse-introduction.md


返回