Laravel 4.2 中队列服务(queue)使用感受


Posted in PHP onOctober 30, 2014

这半个月,我参与重写了一个微信公众号后端系统,首次使用了laravel 4.2,以及laravel引以为傲的队列服务(queue)。

由于整个系统涉及到多端交互,又有大量语音传输、处理的业务,我们在一些地方发现响应时间过长。之前的系统基于node.js和mongoDB,由于node天生就是异步,有守护进程,所以并没有出现过这个问题,而这次重写必然要引入异步流程了。Queue进入了我们的视线。

根据这一页几乎还全是英文的”中文文档“ ,laravel恰好在4.2版本中刚刚引入了redis作为队列存储,这是一个非常好的消息。OK,背景介绍到这里,下面扯扯干货。

laravel中的队列服务跟其他队列服务也没有什么不同,都是最符合人类思维的最简单最普遍的流程:有一个地方存放队列信息,一个PHP进程在运行时将任务写入,另外一个PHP守护进程轮询队列信息,将达到执行要求的任务执行并删除。由于PHP是url驱动的同步语言,本身是阻塞的,所以laravel提供一个守护进程工具来查询并执行队列信息也就不足为奇了。

Laravel的queue配置文件是 /app/config/queue.php,在 Default Queue Driver 这一项中,可以选择"sync", "beanstalkd", "sqs", "iron", "redis" 五种驱动器。

1. sync是本地调试用的同步驱动器

2. beanstalkd 是一个专业队列服务驱动器:http://kr.github.io/beanstalkd/

3. sqs和iron是国外第三方队列服务

4. 最后一项redis给了我们一个使用redis的理由,这样我们顺便把缓存服务和session服务全部迁移到redis上了。

0. 顺便说一句,session驱动器千万别用mysql,处理时间1S不是梦,哎,看谁呢,说的就是你,1S哥!

队列服务需要专门新建任务类,作为独立类,他们不需要继承类,因为队列里的任务在执行的时候,是由PHP守护进程来独立调用的,当然如果你要use一下别的类再调用,也不会出错。之前我把很多额外服务独立到了一个单独的文件夹 /app/services 里,比如输入信息验证 validator,特殊安全验证模块等,这次queue类们就位于其中。

queue的使用非常简单,下面就是一个简单的示例:

use Queue;

Queue::push('CurlJsonQueue', [

 'url' => $url,

 'json' => $json

]);

这就是一个标准的queue压入流程了。当然,在这里我把CurlJsonQueue类放到了services根目录下,这个目录已经被我注册到composer.json的"autoload"的"classmap"中,是位于顶层命名空间中的,可以直接调用,如果需要调用非顶层命名空间,是可以写 App\OOXX 的。我们的系统需要大量和微信服务器交互,所以就独立出来了这个类。

<?php
class CurlJsonQueue extends BaseController{
 public function fire($job, $data)

 {

  $url = $data['url'];

  $json = $data['json'];
  parent::base_post_curl($url, $json);
  $job->delete();

 }

}

这个类默认的方法是 fire() ,参数也是固定的两个 $job 和 $data,由于我在BaseController中封装了post的curl模块,所以就调用了一下。另外这里还有一个小坑,当时写base_post_curl() 的时候用的protected,导致use BaseController无效,必须继承。

通过执行上面的代码,queue中就被放入了一个新的任务,laravel通过下面的命令开启守护进程:

php artisan queue:listen

然后守护进程就开始处理队列了。此代码中的PHP命令和artisan文件的路径请自行调整。

大家可能注意到了,我们要使用的这个队列系统用到了redis和PHP命令行,如果在测试环境,加个开机启动甚至是手动启动都可以,但是在生产环境就需要更稳固的工具来守护这两个程序,我们用的是supervisor,关于supervisor的安装配置大家可以参考这篇文章: http://blog.segmentfault.com/qianfeng/1190000000532561 注意,文章里有小坑请自行去踩。。。

OK,全部配置好之后,跑起来redis和PHP命令行,整个系统就开始愉快地运行啦~

使用感受:

队列服务超好用,之前一次和app的交互流程需要6-7S,异步以后降低到2S以内,基本就是传输时间和PHP代码运行时间了,耗时的特殊操作已经异步了。不过队列服务默认1S开一个进程检查一次redis中有没有可以运行的服务,在阿里云服务器上,大约能占到单核的10%,消耗略大,而且队列处理时间相对较长,因为没有了之前同步时候的文件加载福利。不过如果有多个任务,PHP进程是会连续执行的,不会1S执行一个的啦。

下面说说坑:

1. 由于queue核心类使用了一个特殊函数,导致没有明确类型的变量会以单元素数组的形式存进json,再存进redis。解决办法就是在每一个要放进去的数据前面加上 ''. 。上面的$url和$json由于都已经在前面用引号进行了类型申明,故没做这一步操作。

2. 如果要传递url给队列,系统queue类会在每一个 / 前面加上两个 \\ 。这对于一些特殊操作可能会造成致命影响。(开玩笑,有上面那个致命么!)

PHP 相关文章推荐
一篇入门的php Class 文章
Apr 04 PHP
PHP编程中字符串处理的5个技巧小结
Nov 13 PHP
IIS6+PHP5+MySQL5+Zend Optimizer+phpMyAdmin安装配置图文教程 2009年
Jun 08 PHP
无法在发生错误时创建会话,请检查 PHP 或网站服务器日志,并正确配置 PHP 安装最快的解决办法
Aug 01 PHP
php小技巧 把数组的键和值交换形成了新的数组,查找值取得键
Jun 02 PHP
PHP版 汉字转码的实现详解
Jun 09 PHP
ThinkPHP 3.2 版本升级了哪些内容
Mar 05 PHP
PHP通过串口实现发送短信
Jul 08 PHP
crontab无法执行php的解决方法
Jan 25 PHP
PHP实现生成数据字典功能示例
May 24 PHP
实例解析php的数据类型
Oct 24 PHP
使用Entrust扩展包在laravel 中实现RBAC的功能
Mar 16 PHP
初识Laravel
Oct 30 #PHP
用 Composer构建自己的 PHP 框架之使用 ORM
Oct 30 #PHP
用 Composer构建自己的 PHP 框架之设计 MVC
Oct 30 #PHP
用 Composer构建自己的 PHP 框架之构建路由
Oct 30 #PHP
ThinkPHP做文字水印时提示call an undefined function exif_imagetype()解决方法
Oct 30 #PHP
用 Composer构建自己的 PHP 框架之基础准备
Oct 30 #PHP
thinkphp视图模型查询提示ERR: 1146:Table 'db.pr_order_view' doesn't exist的解决方法
Oct 30 #PHP
You might like
php将数据库中所有内容生成静态html文档的代码
2010/04/12 PHP
PHP程序级守护进程的实现与优化的使用概述
2013/05/02 PHP
WordPress特定文章对搜索引擎隐藏或只允许搜索引擎查看
2015/12/31 PHP
PHP生成word文档的三种实现方式
2016/11/14 PHP
解决PHP程序运行时:Fatal error: Maximum execution time of 30 seconds exceeded in的错误提示
2016/11/25 PHP
php-7.3.6 编译安装过程
2020/02/11 PHP
来自chinaz的ajax获取评论代码
2008/05/03 Javascript
Div Select挡住的解决办法
2008/08/07 Javascript
JavaScript中去掉数组中的重复值的实现方法
2011/08/03 Javascript
基于JavaScript实现继承机制之构造函数+原型链混合方式的使用详解
2013/05/07 Javascript
jQuery判断元素是否存在的可靠方法
2014/05/06 Javascript
jquery实现全选、反选、获得所有选中的checkbox
2020/09/13 Javascript
Bootstrap打造一个左侧折叠菜单的系统模板(一)
2016/05/17 Javascript
基于jQuery下拉选择框插件支持单选多选功能代码
2016/06/07 Javascript
angularjs下拉框空白的解决办法
2017/06/20 Javascript
解决vue无法设置滚动位置的问题
2018/10/07 Javascript
JavaScript简单实现的仿微博留言功能示例
2019/01/17 Javascript
Node.js如何对SQLite的async/await封装详解
2019/02/14 Javascript
vue 实现小程序或商品秒杀倒计时
2019/04/14 Javascript
jquery.pager.js分页实现详解
2019/07/29 jQuery
vue图片加载失败时用默认图片替换的方法
2019/08/29 Javascript
javascript 对象 与 prototype 原型用法实例分析
2019/11/11 Javascript
vue 组件间的通信之子组件向父组件传值的方式
2020/07/29 Javascript
vue 使用 sortable 实现 el-table 拖拽排序功能
2020/12/26 Vue.js
python和pyqt实现360的CLable控件
2014/02/21 Python
python中base64加密解密方法实例分析
2015/05/16 Python
Python的Django框架中URLconf相关的一些技巧整理
2015/07/18 Python
Pycharm 设置自定义背景颜色的图文教程
2018/05/23 Python
深入浅析Python的类
2018/06/22 Python
python mac下安装虚拟环境的图文教程
2019/04/12 Python
Python count函数使用方法实例解析
2020/03/23 Python
pip install命令安装扩展库整理
2021/03/02 Python
全球速卖通俄罗斯站:AliExpress俄罗斯
2019/06/17 全球购物
幼儿园开学寄语
2014/04/03 职场文书
咖啡厅商业计划书
2014/09/15 职场文书
我的收音机情缘
2022/04/05 无线电