如何用RabbitMQ和Swoole实现一个异步任务系统


Posted in PHP onMay 29, 2021

系统介绍

如何用RabbitMQ和Swoole实现一个异步任务系统

从图中可以看到,我们这个系统是一个基于事件的异步任务系统。就是说当一个事件产生时,生产者将事件抛给调度器,调度器负责查询事件下有哪些任务,然后将这些任务丢到相应的队列中,最后由消费者消费任务队列中的任务。

在整个系统中主要分为三大部分

1.事件生产者,即产生消息事件的一方。

2.任务调度器(Scheduler),负责注册事件并调度任务。

3.消费者(Worker),负责消费任务队列中的任务。

事件生产者

事件生产者很简单,在业务系统中直接调用即可,代码如下。

<?php
 
require_once DIR.'/../autoload.php';
 
use Asynclib\Ebats\Event;
 
try{
 
    $event = new Event('order_paied');  //定义事件
 
    $event->setOptions(['order_id' => 'FB138020392193312']); //事件产生的参数
 
    $event->publish();
 
}catch (Exception $exc){
 
    echo $exc->getMessage();
 
}

任务调度器

调度器主要做两件事,一是注册事件,另一个是调度任务。

注册事件代码如下:

//注册事件
 
EventManager::register('order_create', 'closeOrder', 'demo', 10);//关闭未付款订单(延迟任务)
 
EventManager::register('order_paied', 'virtualShipping', 'demo'); //虚拟商品自动发货

这样就注册了两个事件,事件下各有一个任务。

具体调度部分代码很简单,就不多赘述,有兴趣的可以去看代码。

消费者

重头戏来了,一个异步任务系统最重要的就是消费端了,现在让我们来看下Worker的流程图。

如何用RabbitMQ和Swoole实现一个异步任务系统

可以看到,在这里我们采用了两个交换器和两个队列,一个负责处理正常的任务即ntask,另一个负责处理需要延迟执行的任务即dtask。简单描述下一个任务的生命周期。

正常任务

1、task产生,进入正常任务的交换器Exchange[ebats_core_ntask]

2、交换器根据topic将任务分发到对应的队列中

3、子进程ntask阻塞等待成功获取到task,并执行该任务

4、执行失败,需要重试时抛出RetryException,不需要重试时抛出TaskException

5、子进程ntask捕获到重试异常将任务抛给延迟任务的交换器Exchange[ebats_core_dtask]

6、将任务执行信息回调给上层开发者以便保存查看

延迟任务

1、子进程dtask阻塞等待成功获取到task,并执行该任务
2、执行失败,需要重试时抛出RetryException,不需要重试时抛出TaskException
3、子进程dtask捕获到重试异常将任务抛给延迟任务的交换器Exchange[ebats_core_dtask]
4、将任务执行信息回调给上层开发者以便保存查看

消费者代码如下:

require_once DIR.'/../autoload.php';
 
require_once DIR.'/task/TaskDemoModel.php';
 
use Asynclib\Ebats\Worker;
 
  
 
//执行结果回调函数
 
$callback = function ($topic, $taskid, $taskname, $params, $timeuse, $message){
 
  
 
};
 
$worker = new Worker($callback);  //支持多进程消费默认为1
 
$worker->setQueue('demo');  //队列名和事件的topic一一对应
 
$worker->run();

自定义调度器

一般来说这是一个基于事件的任务系统,那么能不能直接产生任务呢。答案是肯定的。

只需要创建一个自定义调度器,由您自行实现调度逻辑,最终生成一个任务即可。代码如下:

<?php
 
require_once DIR.'/../autoload.php';
 
use Asynclib\Ebats\Task;
 
use Asynclib\Core\Consumer;
 
use Asynclib\Amq\ExchangeTypes;
 
use Asynclib\Exception\ExceptionInterface;
 
  
 
/**
 
 * 本示例演示了如何创建一个自定义调度器,开发者可以根据自身需求开发自己的任务调度器
 
 */
 
try{
 
    $worker = new Consumer();
 
    $worker->setExchange('order_fanout', ExchangeTypes::TOPIC);
 
    $worker->setQueue('shzf_order_paied', ['*.*.WAIT_SELLER_SEND_GOODS']);
 
    $worker->run(function($key, $msg){
 
        $order_data = json_encode($msg);
 
        echo " [$key] $order_data \n";
 
        Task::create('demo', 'orderAsync', $msg);//创建任务,之后消息将作为参数由任务接管处理
 
    });
 
}catch (ExceptionInterface $exc){
 
    echo $exc->getMessage();
 
}

这样,当接收到消息时就会产生一个orderAsync的任务,您只需要启动一个用来消费这个Topic的Worker即可。

也许你会觉得这里直接写业务逻辑的代码就可以了,实际上也确实可以。当你可以忍受一个进程慢慢消费的时候是可以这样做的。但大多数情况下我们还是希望它能够尽快的消费掉,所以建议这里只负责创建任务,具体任务的业务逻辑由worker去执行。

以上就是如何用RabbitMQ和Swoole实现一个异步任务系统的详细内容,更多关于用RabbitMQ和Swoole实现一个异步任务系统的资料请关注三水点靠木其它相关文章!

PHP 相关文章推荐
PHP个人网站架设连环讲(三)
Oct 09 PHP
调试一段PHP程序时遇到的三个问题
Jan 17 PHP
使用PHP静态变量当缓存的方法
Nov 13 PHP
PHP循环遍历数组的3种方法list()、each()和while总结
Nov 19 PHP
LINUX下PHP程序实现WORD文件转化为PDF文件的方法
May 13 PHP
php中array_unshift()修改数组key注意事项分析
May 16 PHP
PHP实现移除数组中为空或为某值元素的方法
Jan 07 PHP
详解php实现页面静态化原理
Jun 21 PHP
PHP面向对象五大原则之开放-封闭原则(OCP)详解
Apr 04 PHP
PHP命令Command模式用法实例分析
Aug 08 PHP
Laravel框架实现的批量删除功能示例
Jan 16 PHP
微信公众号之主动给用户发送消息功能
Jun 22 PHP
浅谈Laravel中使用Slack进行异常通知
May 29 #PHP
详解Go与PHP的语法对比
May 29 #PHP
详解php中流行的rpc框架
如何在Mac上通过docker配置PHP开发环境
浅谈如何提高PHP代码质量之端到端集成测试
May 28 #PHP
浅谈如何提高PHP代码质量之单元测试
May 28 #PHP
浅谈如何提高PHP代码的质量
May 28 #PHP
You might like
PHP 透明水印生成代码
2012/08/27 PHP
php使用百度天气接口示例
2014/04/22 PHP
PHP7 其他修改
2021/03/09 PHP
原生javascript获取元素样式属性值的方法
2010/12/25 Javascript
这些年、我收集的JQuery代码小结
2012/08/01 Javascript
异步动态加载js与css文件的js代码
2013/09/15 Javascript
js实现数组去重、判断数组以及对象中的内容是否相同
2013/11/29 Javascript
jQuery 设置 CSS 属性示例介绍
2014/01/16 Javascript
JS实现一个列表中包含上移下移删除等功能
2014/09/24 Javascript
详解JavaScript的AngularJS框架中的表达式与指令
2016/03/05 Javascript
jQuery插件zTree实现单独选中根节点中第一个节点示例
2017/03/08 Javascript
jQuery实现可兼容IE6的滚动监听功能
2017/09/20 jQuery
微信小程序实现城市列表选择
2018/06/05 Javascript
详解Angular中通过$location获取地址栏的参数
2018/08/02 Javascript
微信小程序 云开发模糊查询实现解析
2019/09/02 Javascript
在layui tab控件中载入外部html页面的方法
2019/09/04 Javascript
vue从零实现一个消息通知组件的方法详解
2020/03/16 Javascript
[02:57]DOTA2亚洲邀请赛小组赛第四日 赛事回顾
2015/02/02 DOTA
python连接mysql数据库示例(做增删改操作)
2013/12/31 Python
python删除特定文件的方法
2015/07/30 Python
浅析Python 读取图像文件的性能对比
2019/03/07 Python
Python Django view 两种return的实现方式
2020/03/16 Python
python中wheel的用法整理
2020/06/15 Python
python怎么自定义捕获错误
2020/06/29 Python
Pycharm配置autopep8实现流程解析
2020/11/28 Python
python中time包实例详解
2021/02/02 Python
Space NK美国站:英国高端美妆护肤商城
2017/05/22 全球购物
时装界的“朋克之母”:Vivienne Westwood
2017/07/06 全球购物
日语专业毕业生自荐信
2013/11/11 职场文书
六查六看六改心得体会
2014/10/14 职场文书
学校党的群众路线教育实践活动总结材料
2014/10/30 职场文书
幼儿园教师岗位职责
2015/04/02 职场文书
小区保洁员岗位职责
2015/04/10 职场文书
丧事酒宴答谢词
2015/09/30 职场文书
sql时间段切分实现每隔x分钟出一份高速门架车流量
2022/02/28 SQL Server
使用python绘制横竖条形图
2022/04/21 Python