如何用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中的日期及时间
Nov 23 PHP
php SQL防注入代码集合
Apr 25 PHP
jQuery 源码分析笔记
May 25 PHP
linux iconv方法的使用
Oct 01 PHP
ThinkPHP自动转义存储富文本编辑器内容导致读取出错的解决方法
Aug 08 PHP
php多个文件及图片上传实例详解
Nov 10 PHP
利用PHP抓取百度阅读的方法示例
Dec 18 PHP
PHP 获取指定地区的天气实例代码
Feb 08 PHP
php curl批处理实现可控并发异步操作示例
May 09 PHP
PHP PDOStatement::bindColumn讲解
Jan 30 PHP
THINKPHP5.1 Config的配置与获取详解
Jun 08 PHP
基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询操作
Aug 17 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
Thinkphp搜索时首页分页和搜索页保持条件分页的方法
2014/12/05 PHP
PHP用mb_string函数库处理与windows相关中文字符及Win环境下开启PHP Mb_String方法
2015/11/11 PHP
WordPress中用于检索模版的相关PHP函数使用解析
2015/12/15 PHP
JQuery实现用户名无刷新验证的小例子
2013/03/22 Javascript
jQuery javaScript捕获回车事件(示例代码)
2013/11/07 Javascript
jquery trigger伪造a标签的click事件取代window.open方法
2014/06/23 Javascript
关于编写性能高效的javascript事件的技术
2014/11/28 Javascript
js实现绿白相间竖向网页百叶窗动画切换效果
2015/03/02 Javascript
jQuery+jsp下拉框联动获取本地数据的方法(附源码)
2015/12/03 Javascript
快速掌握WordPress中加载JavaScript脚本的方法
2015/12/17 Javascript
JavaScript实现仿淘宝商品购买数量的增减效果
2016/01/22 Javascript
JQuery 两种方法解决刚创建的元素遍历不到的问题
2016/04/13 Javascript
JavaScript中自带的 reduce()方法使用示例详解
2016/08/10 Javascript
jQuery实现带延时功能的水平多级菜单效果【附demo源码下载】
2016/09/21 Javascript
基于jQuery的$.getScript方法去加载javaScript文档解析
2017/11/08 jQuery
30分钟快速实现小程序语音识别功能
2018/11/27 Javascript
js的各种数据类型判断的介绍
2019/01/19 Javascript
vant中的toast层级改变操作
2020/11/04 Javascript
Python的词法分析与语法分析
2013/05/18 Python
Python中操作符重载用法分析
2016/04/29 Python
python基于phantomjs实现导入图片
2016/05/13 Python
Flask的图形化管理界面搭建框架Flask-Admin的使用教程
2016/06/13 Python
python3实现163邮箱SMTP发送邮件
2018/05/22 Python
python cv2.resize函数high和width注意事项说明
2020/07/05 Python
python+openCV对视频进行截取的实现
2020/11/27 Python
基于DOM+CSS3实现OrgChart组织结构图插件
2016/03/02 HTML / CSS
html5 touch事件实现触屏页面上下滑动(二)
2016/03/10 HTML / CSS
银行介绍信范文
2014/01/10 职场文书
小区门卫管理制度
2014/01/29 职场文书
大学生求职信范文
2014/05/24 职场文书
工伤事故赔偿协议书范文
2014/09/24 职场文书
2015年世界无烟日活动总结
2015/02/10 职场文书
2015个人半年总结范文
2015/03/09 职场文书
幼儿园重阳节活动总结
2015/05/05 职场文书
2015年教务主任工作总结
2015/07/22 职场文书
mysql幻读详解实例以及解决办法
2022/06/16 MySQL