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 相关文章推荐
实用函数4
Nov 08 PHP
Smarty的配置与高级缓存技术分享
Jun 05 PHP
基于session_unset与session_destroy的区别详解
Jun 03 PHP
Laravel 4 初级教程之视图、命名空间、路由
Oct 30 PHP
php从完整文件路径中分离文件目录和文件名的方法
Mar 13 PHP
php类自动加载器实现方法
Jul 28 PHP
Yii框架中jquery表单验证插件用法示例
Oct 18 PHP
php_pdo 预处理语句详解
Nov 21 PHP
php的常量和变量实例详解
Jun 27 PHP
PHP 进度条函数的简单实例
Sep 19 PHP
php调用云片网接口发送短信的实现方法
Oct 25 PHP
PHP 图片合成、仿微信群头像的方法示例
Oct 25 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的FTP学习(一)[转自奥索]
2006/10/09 PHP
php面向对象全攻略 (九)访问类型
2009/09/30 PHP
探讨如何在php168_cms中提取验证码
2013/06/08 PHP
PHP页面中文乱码分析
2013/10/29 PHP
javascript+php实现根据用户时区显示当地时间的方法
2015/03/11 PHP
PHP设计模式之迭代器模式
2016/06/17 PHP
简单解决微信文章图片防盗链问题
2016/12/17 PHP
Yii框架参数配置文件params用法实例分析
2019/09/11 PHP
javascript学习笔记(十) js对象 继承
2012/06/19 Javascript
javascript jq 弹出层实例
2013/08/25 Javascript
Google Dart编程语法和基本类型学习教程
2013/11/27 Javascript
javascript获取函数名称、函数参数、对象属性名称的代码实例
2014/04/12 Javascript
jquery实现在光标位置插入内容的方法
2015/02/05 Javascript
jquery显示loading图片直到网页加载完成的方法
2015/06/25 Javascript
url传递的参数值中包含&amp;时,url自动截断问题的解决方法
2016/08/02 Javascript
Nuxt.js实战详解
2018/01/18 Javascript
Electron-vue开发的客户端支付收款工具的实现
2019/05/24 Javascript
详解Jest结合Vue-test-utils使用的初步实践
2019/06/27 Javascript
vue实现输入框的模糊查询的示例代码(节流函数的应用场景)
2019/09/01 Javascript
Python进程间通信用法实例
2015/06/04 Python
Python实现句子翻译功能
2017/11/14 Python
Python下载网络文本数据到本地内存的四种实现方法示例
2018/02/05 Python
Python numpy 提取矩阵的某一行或某一列的实例
2018/04/03 Python
Falsk 与 Django 过滤器的使用与区别详解
2019/06/04 Python
Django模型序列化返回自然主键值示例代码
2019/06/12 Python
Python flask框架post接口调用示例
2019/07/03 Python
python打印直角三角形与等腰三角形实例代码
2019/10/20 Python
python分别打包出32位和64位应用程序
2020/02/18 Python
Django-rest-framework中过滤器的定制实例
2020/04/01 Python
python pillow库的基础使用教程
2021/01/13 Python
html通过canvas转成base64的方法
2019/07/18 HTML / CSS
乌克兰电子和家用电器商店:Foxtrot
2019/07/23 全球购物
UNIX命令速查表
2012/03/10 面试题
领导干部贪图享乐整改措施
2014/09/21 职场文书
python爬虫请求库httpx和parsel解析库的使用测评
2021/05/10 Python
MySQL数据库 安全管理
2022/05/06 MySQL