PHP的Laravel框架中使用消息队列queue及异步队列的方法


Posted in PHP onMarch 21, 2016

queue配置

首先说明一下我之前的项目中如何使用queue的。

我们现在的项目都是用的symfony,老一点的项目用的symfony1.4,新一点的项目用的都是symfony2。symfony用起来整体感觉还是很爽的,尤其symfony2,整体上来讲使用了很多java里面框架的设计思想。但是他不支持queue。在symfony,我们使用queue也经历了几个过程。最开始使用张堰同学的httpsqs。这个简单使用,但是存在单点。毕竟我们的项目还是正式对外服务的,所以我们研究了Apache旗下的开源项目ActiveMQ,研究研究发现还有Apache旗下还有更新的MQ,那就是Apollo。最后我们决定使用的Apollo。

queue在我们的项目中主要的应用场景就是异步处理一些比较耗时的功能,比如同步第三方数据、数据有变动了同步通知到我们的第三方数据使用者等等。我们大致的思路是这样的,在各个controller里面如果需要异步处理的,就把一个json对象encode一下,塞到Apollo里面。再写一个work的Command,在这个Command中解析json对象,根据里面的action和参数决定来调用不同的方法处理。根据业务需要同时在不同的机器上运行Command作为守护进程一直跑着,也算实现异步多任务处理应用的方案。就这么一直使用着,直到发现了laravel。打算研究一下。如果可能替代一下也不是不可能。呵呵。

由于才开始学习,当然直接上laravel5。routes、controller、view都基本上和symfony差别不到,上手倒是不困难。最后研究一下queue。

1、安装laravle,使用composer,倒是很简单。

composer global require "laravel/installer=~1.1"
vi ~/.bash_profile

把~/.composer/vendor/bin 加入到环境变量中。

source ~/.bash_profile

就可以直接在命令行中使用laravel了。试一下。

laravel -V

能够看到下面的,就代表成功了。

Laravel Installer version 1.2.1

2、创建项目。

laravel new guagua

3、配置redis和queue。

4、创建controller,

php artisan make:controller DefaultController

在controller的action中push100个queue的任务。

for($i = 0; $i < 100; $i ++) {
  Queue::push(new SendEmail("ssss".$i));
}

5、创建queue的Command

php artisan make:command SendEmail --queued

修改app/Commands/SendEmail.php,添加一个私有变量。

protected $msg;

同时修改构造函数。

public function __construct($msg)
{
  $this->msg = $msg;
}

再修改的handle方法

public function handle() {
  sleep(4);
  echo $this->msg."\t".date("Y-m-d H:i:s")."\n";
  $this->delete();
}

6、修改routes

Route::get('/', [
  'as' => 'index',
  'uses' => 'DefaultController@index'
]);

7、监听queue

php artisan queue:listen

为了验证多任务处理,我们同时开三个窗口运行同样的命令。

8、用laravel内建的server启动服务

php artisan serve --port 8080

打开浏览器,访问http://localhost:8080/页面。当然也可以用nginx,apache之类的。但是需要各种配置,还是内建的使用方便。

在控制台就能看到各个queue执行的情况了,如下图。可以看到100个任务被三个work平分了。

PHP的Laravel框架中使用消息队列queue及异步队列的方法

到此,基本达到了我想要的效果。验证了laravel可以简单实现queue,并且可以多任务处理。

make command生成的代码中use App\Commands\Command ,但是运行时提示没有这个文件。 解决办法,修改为 use Illuminate\Console\Command; 不知道为什么会出现这个低级问题,难道是我mac系统问题,还是我的人品问题。
在controller的action中push队列的时候,没有异步执行,还是在action的脚本中执行的。 发现是配置问题,原来不仅仅要修改config中的queue.php,还要修改.evn中相关配置。 虽然问题解决了,但是还是觉得蛋疼,不能理解。还需要在学习学习laravel。

异步队列使用方法

1.配置

关于队列的定义,这里就不作介绍了。我们要使用异步队列就有两个关键:

(1)存储队列的地方
(2)执行任务的服务
打开 config/queue.php ,这是Laravel5关于队列的配置文件。首先我们可以通过 default 参数指定默认队列驱动,默认配置是 sync , 这是同步队列,我们要做异步队列首先就要改变这里。假设我们用 database 作为驱动,队列任务将会存放在数据库中,而我们后面会另外启动一个后台服务来处理队列任务,这就是异步方式了。

'default' => 'database'

修改完配置后,我们需要创建一个表来存放队列任务,Laravel5已经在自带artisan命令中内置了一个指令用来生成数据迁移,只需要两条命令即可,当然你得实现配置好数据库连接。

php artisan queue:table
php artisan migrate

这样就自动在数据库中创建了 jobs 表。

2.启动队列监听服务

通过下面这条指令启动队列监听服务,它会自动处理 jobs 表中的队列任务:

php artisan queue:listen

在linux中,如果想让它在后台执行,可以这样:

nohup php artisan queue:listen &

3.添加队列任务

关于队列任务的添加,手册里说的比较详细,这里就简单举个例子吧。

首先,通过artisan创建一个队列命令:

php artisan make:command SendEmail --queued

这样会生成 app/Commands/SendEmail.php 这个类文件,这个类会被标识为队列命令,你可以在 handle 方法中写自己的业务逻辑。

在控制器中,可以简单通过 Bus::dispatch 分发任务:

Bus::dispatch(new \App\Commands\SendEmail());

你会发现任务不会立即执行,而是被放到 jobs 表中,由队列监听服务处理。

更详细的用法建议参考 command bus 和 queue 相关的手册章节。

PHP 相关文章推荐
php格式化工具Beautify PHP小小BUG
Apr 24 PHP
PHP实例分享判断客户端是否使用代理服务器及其匿名级别
Jun 04 PHP
ThinkPHP的cookie和session冲突造成Cookie不能使用的解决方法
Jul 01 PHP
简单谈谈php中ob_flush和flush的区别
Nov 27 PHP
PHP获得数组交集与差集的方法
Jun 10 PHP
PHP+Mysql+jQuery查询和列表框选择操作实例讲解
Oct 22 PHP
PHP实现补齐关闭的HTML标签
Mar 22 PHP
php运行报错Call to undefined function curl_init()的最新解决方法
Nov 20 PHP
php实现头像上传预览功能
Apr 27 PHP
PHP cURL获取微信公众号access_token的实例
Apr 28 PHP
Laravel框架模板继承操作示例
Jun 11 PHP
PHP利用递归函数实现无限级分类的方法
Mar 22 PHP
Zend Framework框架之Zend_Mail实现发送Email邮件验证功能及解决标题乱码的方法
Mar 21 #PHP
Zend Framework教程之Zend_Form组件实现表单提交并显示错误提示的方法
Mar 21 #PHP
Zend Framework实现多文件上传功能实例
Mar 21 #PHP
Zend Framework入门之环境配置及第一个Hello World示例(附demo源码下载)
Mar 21 #PHP
Zend Framework教程之连接数据库并执行增删查的方法(附demo源码下载)
Mar 21 #PHP
Zend Framework框架教程之Zend_Db_Table_Rowset用法实例分析
Mar 21 #PHP
Zend Framework教程之Zend_Db_Table_Row用法实例分析
Mar 21 #PHP
You might like
PHP 配置open_basedir 让各虚拟站点独立运行
2009/11/12 PHP
用PHP实现弹出消息提示框的两种方法
2013/12/17 PHP
PHP查找数值数组中不重复最大和最小的10个数的方法
2015/04/20 PHP
php验证码生成代码
2015/11/11 PHP
php实现网页端验证码功能
2017/07/11 PHP
Javascript 获取链接(url)参数的方法
2009/02/15 Javascript
JavaScript执行效率与性能提升方案
2012/12/21 Javascript
php与js的区别是什么
2013/08/05 Javascript
JavaScript中按位“异或”运算符使用介绍
2014/03/14 Javascript
深入理解JavaScript中的箭头函数
2015/07/28 Javascript
深入浅析AngularJS和DataModel
2016/02/16 Javascript
Jquery uploadify 多余的Get请求(404错误)的解决方法
2017/01/26 Javascript
js实现下拉框效果(select)
2017/03/28 Javascript
详解react如何在组件中获取路由参数
2017/06/15 Javascript
利用Javascript实现一套自定义事件机制
2017/12/14 Javascript
解决Vue的项目使用Element ui 走马灯无法实现的问题
2020/08/03 Javascript
跟老齐学Python之Import 模块
2014/10/13 Python
使用python实现省市三级菜单效果
2016/01/20 Python
python reverse反转部分数组的实例
2018/12/13 Python
python集合是否可变总结
2019/06/20 Python
python函数的万能参数传参详解
2019/07/26 Python
python 实现查询Neo4j多节点的多层关系
2019/12/23 Python
Pycharm debug调试时带参数过程解析
2020/02/03 Python
TensorFlow梯度求解tf.gradients实例
2020/02/04 Python
Python调用shell cmd方法代码示例解析
2020/06/18 Python
利用CSS3实现炫酷的飞机起飞动画
2016/09/17 HTML / CSS
HTML5 CSS3新的WEB标准和浏览器支持
2009/07/16 HTML / CSS
使用placeholder属性设置input文本框的提示信息
2020/02/19 HTML / CSS
英国排名第一的冲浪店:Ann’s Cottage
2020/06/21 全球购物
小学捐书活动总结
2014/07/05 职场文书
酒店七夕情人节活动策划方案
2014/08/24 职场文书
公司财务会计主管应聘求职信
2014/09/26 职场文书
pyqt5打包成exe可执行文件的方法
2021/05/14 Python
Python移位密码、仿射变换解密实例代码
2021/06/27 Python
古见同学有交流障碍症 第二季宣传CM公开播出
2022/04/11 日漫
Python测试框架pytest高阶用法全面详解
2022/06/01 Python