getwayworker timer_Laravel + Workerman 实现多进程定时器任务
发布日期:2021-06-24 16:33:24 浏览次数:2 分类:技术文章

本文共 4385 字,大约阅读时间需要 14 分钟。

前言

由于本人个人原因不太喜欢使用Linux的Crontab或者使用Supervisor去执行php的一些异步进程。

但是有了workerman的加持,我们可以使用workerman的一些方法特性去实现纯php版的异步功能。

因为workerman这个框架自身也是纯PHP实现的高性能异步PHP socket即时通讯框架,php加持php岂不美哉?

(PS:workerman死忠粉)

准备工作

Laravel版本:6.0

Workerman版本:4.0

workerman的运行环境需要安装pcntl和posix扩展。

我这里使用的是laravel的集成docker环境 laradock是可以直接使用的

Workerman环境具体可以访问:http://doc.workerman.net/install/install.h...

Laradock环境https://laradock.io/

具体实现

一、安装workerman

composer require workerman/workerman

二、编写Artisan控制台命令方便调用workerman

php artisan make:command WorkermanTimerCommand

可以看到在laravel的app\Console\Commands目录下生产了一个WorkermanTimerCommand.php文件。

三、接着我们开始编写workerman的控制台命令支持

namespace App\Console\Commands;

use App\Listens\WorkermanTimers;

use Illuminate\Console\Command;

use Workerman\Worker;

class WorkermanTimerCommand extends Command

{

/**

* 控制台命令的名称和参数.

*

* @var string

*/

protected $signature = 'workerman {action} {--d}';

/**

* 控制台命令描述.

*

* @var string

*/

protected $description = 'workerman的多进程定时任务';

/**

* Create a new command instance.

*

* @return void

*/

public function __construct()

{

parent::__construct();

}

/**

* Execute the console command.

*

* @return mixed

*/

public function handle()

{

global $argv;

$action = $this->argument('action');

$argv[0] = 'wk';

$argv[1] = $action;

$argv[2] = $this->option('d') ? '-d' : '';

$this->startServer();

}

/**

* 启动workerman服务

*/

public function startServer()

{

$worker = new Worker();

// 服务名称.

$worker->name = 'laravel timer';

// 启动多少个进程数量,这里大家灵活配置,可以参考workerman的文档.

$worker->count = 4;

// 当workerman的进程启动时的回调方法.

$worker->onWorkerStart = [WorkermanTimers::class, 'onWorkerStart'];

// 当workerman的进程关闭时的回调方法.

$worker->onClose = [WorkermanTimers::class, 'onClose'];

Worker::runAll();

}

}

可以看到在上面的startServer方法里,我们为onWorkerStart和onClose分别注册回调到了WorkermanTimers类里面的onWorkerStart和onWorkerStart方法。

这里的意思是当workerman里面的进程启动的时候,会调用WorkermanTimers类里面对应的方法!

那我们来看看这个WorkermanTimers类究竟需要干一些什么!

四、编写定时器任务分发类(WorkermanTimers)

我们现在app目录下新建一个Listens目录,并创建WorkermanTimers类

WorkermanTimers类具体代码:

namespace App\Listens;

use Workerman\Lib\Timer;

class WorkermanTimers

{

/**

* 服务进程启动时

* @param $businessWorker

*/

public static function onWorkerStart($businessWorker)

{

// 拿到当前进程的id编号.

$workid = $businessWorker->id;

// 获取所有定时器任务配置.

$timedTask = config('timers');

if (is_array($timedTask)) {

// 循环检测任务绑定.

foreach ($timedTask as $key => $value) {

// 绑定任务进程.

if ($value['worker_id'] == $workid) {

Timer::add($value['time'], $value['func']);

}

}

}

}

/**

* 服务进程结束时

* @param $client_id

*/

public static function onClose($client_id)

{

}

}

解释:

以上onWorkerStart方法就是workerman每个进程刚启动的时候会回调过来当前进程的属性$businessWorker

我们在WorkermanTimerCommand里面定义的进程数count=4,就是4个进程。也就是说onWorkerStart方法会被调用四次,因为多进程里每个进程相互隔离,所以每次我们拿到的$businessWorker->id都会不一样。

worker进程的id编号,范围为0到$worker->count-1,所以每次$businessWorker->id编号应该是0,1,2,3

所以我们循环定义的timers配置,判断每个配置绑定的进程编号如果和当前的进程编号一致,我们就为当前进程增加一个定时器!

可能各位看官有疑问了,timers的配置在哪呢?

我们接着往下走

五、在config/目录下新增一个timers.php

具体配置如下:

return [

// 定时任务名称.

'say' => [

'worker_id' => 1, // 需要绑定的进程id.

'time' => 5, // 时间间隔 秒为单位.

'func' => 'Facades\App\Services\TestService::testSay', // 定时执行的方法.

],

/* 'eat' => [

'worker_id' => 2, // 需要绑定的进程id.

'time' => 10, // 时间间隔 秒为单位.

'func' => 'Facades\App\Services\TestService::testEat', // 定时执行的方法.

]*/

];

timers.php返回的是一个多维数据结构的配置,

数组一级元素代表这个定时任务的名称(为了区分和理解),

数组二级元素worker_id代表我们需要绑定到哪个进程

数组二级元素time表示时间间隔,多少秒执行一次

数组二级元素func 代表要执行哪个方法

在结合上面的WorkermanTimers类去看,就可以理解为:

任务:say绑定在进程编号为1的worker上面,每5秒就会执行一次\App\Services\TestService类里面的testSay方法

在laravel里面,命名空间前面加上Facades\就可以静态调用该类的方法,这部分的概念大家可以去看看laravel文档

六、编写定时任务类

我们在app目录下新建一个Services文件夹,并且新增一个TestService类

TestService类具体代码:

namespace App\Services;

class TestService

{

public function testSay()

{

var_dump("Hello Laravel and Workerman");

}

}

七、测试

输入命令php artison workerman start 启动workerman

看看有没有任务执行:

14ed803de3c1a475e2bd7425c769b2fe.png

命令:

启动:

php artisan workerman start

启动常驻内存:

php artisan workerman start --d

其他命令:

php artisan workerman reload //重新加载配置

php artisan workerman reload //重启workerman

php artisan workerman stop //停止workerman

总结

流程:

1.当workerman的每个进程启动后,会回调给WorkermanTimers类的onWorkerStart方法

2.onWorkerStart会加载所有定时任务的配置,然后去循环绑定任务类

3.添加workerman定时间并绑定任务类方法!

4.每个进程绑定一个定时任务,当然也可以一个进程绑定多个定时器任务,具体取决于你怎么在timers.php里面配置

参考文档

其他

workerman是一款底层设计非常优秀的框架,纯php实现高性能常驻内存特性。

workerman能做的事情也远远不止于此,还有很多例如:IM、游戏、物联网等等功能等你去探索!

当优雅的Laravel 遇上 性能强悍得 Workerman 会发生点什么呢?

如果大家有兴趣的话后面我可以在写一些Laravel结合Workerman开发及时通信的例子,比如聊天室、弹幕什么的!

本作品采用《CC 协议》,转载必须注明作者和本文链接

转载地址:https://blog.csdn.net/weixin_33865450/article/details/114170891 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:java rich client_开发你的Rich Client:IBM对Laszlo开源富客户端平台提供支持
下一篇:java jvm内存地址_Java JVM内存那些事儿

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月29日 05时09分32秒