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 array_pop()数组函数将数组最后一个单元弹出(出栈)
Jul 12 PHP
CI(CodeIgniter)框架介绍
Jun 09 PHP
30个php操作redis常用方法代码例子
Jul 05 PHP
非常实用的PHP常用函数汇总
Dec 17 PHP
Yii2 rbac权限控制操作步骤实例教程
Apr 29 PHP
PHP 接入支付宝即时到账功能
Sep 18 PHP
CodeIgniter开发实现支付宝接口调用的方法示例
Nov 14 PHP
浅谈Coreseek、Sphinx-for-chinaese、Sphinx+Scws的区别
Dec 15 PHP
php语言注释,单行注释和多行注释
Jan 21 PHP
Smarty模板变量与调节器实例详解
Jul 20 PHP
Laravel 不同生产环境服务器的判断实践
Oct 15 PHP
phpstudy后门rce批量利用脚本的实现
Dec 12 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
javascript,php获取函数参数对象的代码
2011/02/03 PHP
php构造函数实例讲解
2013/11/13 PHP
Symfony2获取web目录绝对路径、相对路径、网址的方法
2016/11/14 PHP
CI框架使用composer安装的依赖包步骤与方法分析
2016/11/21 PHP
浅谈Yii乐观锁的使用及原理
2017/07/25 PHP
Laravel核心解读之异常处理的实践过程
2019/02/24 PHP
JS按位非(~)运算符与~~运算符的理解分析
2011/07/31 Javascript
javascript获取和判断浏览器窗口、屏幕、网页的高度、宽度等
2014/05/08 Javascript
js判断当页面无法回退时关闭网页否则就history.go(-1)
2014/08/07 Javascript
Webpack 实现 AngularJS 的延迟加载
2016/03/02 Javascript
Bootstrap3制作搜索框样式的方法
2016/07/11 Javascript
BootstrapValidator超详细教程(推荐)
2016/12/07 Javascript
浅谈js script标签中的预解析
2016/12/30 Javascript
jQuery插件zTree实现获取当前选中节点在同级节点中序号的方法
2017/03/08 Javascript
解决jquery appaend元素中id绑定事件失效的问题
2017/09/12 jQuery
jQuery中each方法的使用详解
2018/03/18 jQuery
Vue 动态路由的实现及 Springsecurity 按钮级别的权限控制
2019/09/05 Javascript
[01:06:32]DOTA2上海特级锦标赛D组资格赛#1 EG VS VP第一局
2016/02/28 DOTA
[01:02:30]Mineski vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第三场 8.22
2019/09/05 DOTA
在Python中使用成员运算符的示例
2015/05/13 Python
Python基于pygame实现的font游戏字体(附源码)
2015/11/11 Python
Python数据结构之双向链表的定义与使用方法示例
2018/01/16 Python
Python对切片命名的实现方法
2018/10/16 Python
Python叠加两幅栅格图像的实现方法
2019/07/05 Python
Django {{ MEDIA_URL }}无法显示图片的解决方式
2020/04/07 Python
Python‘==‘ 及 ‘is‘相关原理解析
2020/09/05 Python
CSS3移动端vw+rem不依赖JS实现响应式布局的方法
2019/01/23 HTML / CSS
阿联酋航空官方网站:Emirates
2017/10/17 全球购物
意大利咖啡、浓缩咖啡和浓缩咖啡机:illy caffe
2019/03/20 全球购物
给定一个时间点,希望得到其他时间点
2013/11/07 面试题
自动化专业职业生涯规划书范文
2014/01/16 职场文书
商务日语专业自荐信
2014/04/17 职场文书
《鸿门宴》教学反思
2014/04/22 职场文书
会议主持人开场白台词
2015/05/28 职场文书
嘉年华活动新闻稿
2015/07/17 职场文书
js判断两个数组相等的5种方法
2022/05/06 Javascript