laravel 任务队列_laravel队列-让守护进程处理耗时任务

待解决的问题

最近在做一个服务器集群管理的web项目,需要处理一些极其耗时的操作,比如磁盘格式化分区。对于这个需求,最开始的想法是,为了让节点上的rpc(远程过程调用) service端尽可能简单(简单到只需要popen执行一条指令即可,有时间我再专门写一篇博客讲讲这个项目的rpc是如何实现的),我们选择了让web端直接等待处理结果,那么问题来了,如何保证用户不必等待,又能保证任务准确的执行呢?

简单的rpc结构如下图

以往在处理一些稍微耗时的操作,可以通过优化代码结构,优化数据库操作次数,起一些线程来处理一些简单的比如发邮件,生成大的压缩文件,提取视频缩量图,服务器间互访等等操作,来避免用户在web页面的等待。

但现在这个操作显然不能用之前的这些方法做,因为现在的操作哪怕只执行一次,都是非常耗时的,更何况可能需要处理的可能是上百上千台服务器。这是在线程层面很难做,要知道在响应请求的web进程中起一个线程来做的话,在响应完断开tcp连接之后,这个进程很可能被kill掉,像Apache就是这样,当然可以通过配置改变apache的行为,但显然不太靠谱。

更好的做法是在web服务器上起一个守护进程去做这个事情,那么问题就在于如何创建守护进程了,好在laravel帮我们考虑了这个事情。

Laravel的队列

laravel的队列默认是以sync(同步)的方式来处理多个任务,这显然不是我们想要的。鉴于这个项目使用的是laravel4.1版本,我选择了beanstalkd来实现异步处理多个任务。

其中beanstalkd是一种比较专业的队列服务驱动器,是一个常驻后台服务,我们可以通过它提供的接口来把任务提交给它,由它创建的守护进程来执行队列。

配置队列执行环境

1.安装beanstalkd服务

我开发的电脑为CentOS5.4,版本比较低,所以装的过程中还是遇到些麻烦

首先执行下面的指令

1 wget ftp://fr2.rpmfind.net/linux/epel/5/ppc/epel-release-5-4.noarch.rpm

2 rpm -ivh epel-release-5-4.noarch.rpm3 yummakecache4 yum search beanstalkd

但最后发现找不到这个软件,于是将yum的源换成了163的

1 cd /etc/yum.repos.d2 wget http://mirrors.163.com/.help/CentOS5-Base-163.repo

3 mv CentOS-Base.repo CentOS-Base.repo.bak

再次makecache && install 就OK了,安装完后启动beanstalkd服务

1 service beanstalkd start

另外可以搜索到beanstalkd的配置文件放在了sysconfig下

为laravel添加beanstalkd的驱动

beanstalkd的php驱动包为pda/pheanstalk

进入laravel的protected目录,composer.json在这个目录下

执行

1 composer require pda/pheanstalk 2.*

出现如下的错误

可以看出镜像地址响应 502,所以需要给composer找一个可用的镜像 http://www.phpcomposer.com/

修改~/.composer/config.json如下

然后回到protected目录,再执行前面安装驱动的命令安装,这回出现了不一样的错误

上面的php包中,第一个是为了phpstorm的对laravel更好的支持,后面一个symfony/yaml已经安装,并不需要升级,所以修改composer.json,直接将这两个项目删除掉就行了

删除完之后,再次执行安装命令安装

可以看到终于成功了,可以通过 composer show -i 查看安装了哪些包

测试

在TestController中添加一个action

1 class TestController extendsBaseController2 {3

4 public functiongetQueue(){5 //6 Log::info("添加一个对列任务");7 Queue::push('SendEmail',array('message'=>'哈哈'));8 Log::info('任务添加完毕');9 exit;10 }11

12 }

在app目录下新建tasks目录,并修改protected/composer.json和app/global.php,将这个目录加到类加载路径中

修改global.php

1 ClassLoader::addDirectories(array(2

3 app_path().'/commands',

4 app_path().'/controllers',

5 app_path().'/models',

6 app_path().'/database/seeds',

7 app_path().'/library',

8 app_path().'/tasks',

9 ));

修改composer.json

1 "classmap": [2 "app/commands",3 "app/controllers",4 "app/models",5 "app/database/migrations",6 "app/database/seeds",7 "app/tasks",8 "app/tests/TestCase.php"

9 ]

以后的耗时调度任务的代码就放在这个目录下面了

首先新建一个BaseTask.php

1 /**2 * Created by PhpStorm.3 * User: Administrator4 * Date: 2015/8/19 00195 * Time: 11:556 */

7 abstract classBaseTask8 {9 public abstract function fire($job,$data);10 }

然后新建一个SendMail.php

1 /**2 * Created by PhpStorm.3 * User: Administrator4 * Date: 2015/8/19 00195 * Time: 11:506 */

7 class SendEmail extendsBaseTask8 {9

10 public function fire($job, $data)11 {12 //TODO: Implement fire() method.

13 Log::info("对列任务执行".json_encode($data)."Time : ".time());14 sleep(30);15 Log::info("对列任务执行完毕".time());16 //将任务从队列冲删除

17 $job->delete();18 //将任务返回到队列19

20 // $job->release();

21

22 }23 }

最后就是去修改config目录下的配置文件queue.php文件了,修改为

1 'default' => 'beanstalkd',

1 'beanstalkd' => array(2 'driver' => 'beanstalkd',

3 'host' => 'localhost',

4 'queue' => 'default',

5 'ttr' => 60,

6 ),

关于ttr的解释这里有一个

表示time to run ,这个参数可以覆盖默认参数让Beanstalkd 检测是否在这个时间内完成

至此配置和写代码完成,在shell中执行,要在protected目录下,artisan文件在这个目录下

1 php artisan queue:work2 php artisan queue:listen

查看protected/app/storage/logs/laravel.log 可以看到下面的内容

508-478 刚好30秒

下面测试一个实际的问题,印象中apache服务器与客户端在请求完成断开连接后会kill掉负责处理的httpd进程,只有配置了keep-alive参数在会将进程保留到apache进程池中,所以,但用户请求一个耗时操作之后,关闭了浏览器,这个处理耗时任务的守护进程会不会也被kill掉呢?当然,其实有点多虑了,当响应完成之后tcp链接已经被断开掉了,如果进程会被kill掉,那么早就kill掉了,跟你浏览器关没关应该没多大关系,还是试试吧,实践才是硬道理

这里将SendMial中的sleep时间改长一点,改为 600秒

最后发现没有执行完,可以看到listen报出异常

很显然执行超时,看来是前面设置的ttr的问题

将ttr注释掉或者修改掉更高的值,发现还是不行,最后在仔细看看报错信息,发现

所以改变命令的执行方式

1 php artisan queue:listen --timeout=800

最后命令任务成功执行完毕

可以看到 1353-753 = 600 刚刚好

另外,看样子 这个任务对列应该是被保存起来了,当我没有启动 listen时,任务怎么都不会处理,但我一但启动listen,前面添加的任务就会立马执行

但最后还是有个问题这个是对列形式进行处理,要启动下一个对列任务,必须等上一个对列任务执行完毕,不过之前曾看到过,一个work对应一个任务队列,那么我完全可以起多个任务队列,有点多核CPU的调度哦。

更好的办法

最后,再跟一位大神讨论了一下,探讨出了另外一个更加优秀的办法,虽然会加重节点上rpc service代码的复杂度,不过也不是很麻烦。

这种方式就是回调,管理集群的web服务器可以不用等待,只需如下步骤,

通过web服务器上的rpc client向要执行耗时操作的节点上的rpc service发送一条指令,

节点上的rpc service收到指令后,不先执行指令,而是马上向web服务器,也就是rpc client返回一个任务ID。

web服务器将这个id作为一条任务记录保存到数据库。

节点上的rpc service处理指令,至于处理指令,也是在节点上在单独起一个进程 P 来处理,因为rpc service也不能让rpc client傻等着

处理进程 P 处理完了之后,将执行结果和任务ID作为参数,回调web服务器的一个web接口

web服务器接到rpc service的回调之后,通过ID查找到任务,更新任务的执行状态,更新数据

很显然,这种方式更加可靠,也大大减轻了web 服务器的负担,要知道Linux 系统的线程数是有限制的,但这要耗时任务多了,如果然服务器去等,不管啥策略都很可能吧服务器整垮。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/564444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++对象数组

对象数组是什么 数组对象就是大批量实例化对象的一种方法,例如:Student stu 实例化对象,如果有好几百个对象应该怎么办?这时候就用到了对象数组,顾名思义,就是吧所有要实例化的对象都放到一个组里面&#…

镜像安装linux选择内核版本,在CentOS和Ubuntu中安装Linux Kernel 4.13.10

Linus Torvalds 在 10 月 17 日星期五正式发布了稳定版 Linux Kernel 4.13.10,这个最新版本发布了新功能,进行了诸多修复和问题改进。下面将向大家介绍在 CentOS 和 Ubuntu 中手动安装、更新 Linux Kernel 4.13.10 的方法,当然,这…

C++成员对象和封闭类

有其他类的对象作为 成员对象的类叫封闭类。 任何生成封闭类对象的语句,都要让编译器明白,对象中的成员对象,是如何初始化的。 具体做法是通过封闭类的构造函数的初始化列表。 封闭类对象生成时,先执行所有对象成员的构造函数&a…

linux设备进入睡眠所需时间,android linux 休眠 深度睡眠 查看 方法 调试【转】

在Android移动设备中,有时按下Power键(未接电源,USB)时,因其它apk程序获取了wake_up锁未释放或程序BUG导致未释放,造成未能进入深度睡眠,从而加大了耗电量,减少了待机时间,参考如下图&#xff0…

kali 邮箱攻击_kali下邮件发送工具swaks入坑

Swaks是一个功能强大,灵活,可编写脚本,面向事务的SMTP测试工具,目前Swaks托管在私有svn存储库中。官方项目页面是牛刀小试kali下默认自带,无需安装。01 测试邮箱的连通性swaks --to xxxxxxqq.com返回250ok,…

C++引用浅析

C 中,有一种比指针更加便捷的传递聚合类型数据的方式,那就是引用(Reference)。 在 C/C 中,我们将 char、int、float 等由语言本身支持的类型称为基本类型,将数组、结构体、类(对象)等…

linux 进程 控制终端,linux系统编程之进程(五):终端、作业控制与守护进程

#include#define ERR_EXIT(m)do {perror(m);exit(EXIT_FAILURE);} while(0)int setup_daemon(int, int);/* 守护进程一直在后台运行且无控制终端 */int main(int argc, char *argv[]){// daemon(0, 0)setup_daemon(0, 0);printf("test ..."); // 无输出for(;;) ;ret…

arduino 温度调节器_Arduino用温湿度传感器控制继电器,为什么点了串口助手才能运行,拔掉usb线,直接外界9V电源却用不了...

用温湿度传感器控制继电器,为什么点了串口助手才能运行,拔掉usb线,直接外界9V电源却用不了,以下是程序,目的是在湿度达到40%的时候继电器吸合,45%后,继电器断开,求各位大神指教...用…

C++中指针与引用的区别

指针的本质 指针p也是对象,只不过p存储的数据类型是它所指的对象的地址。可以通过解引用操作符“”来访问对象的值,即p。 对象有常量(const)和非常量之分,如果指针本身是常量,即指针常量,指这…

python支持按指定字符串分割成数组_python – 如何切割numpy数组字符串的每个元素?...

这是一个矢量化的方法 –def slicer_vectorized(a,start,end):b a.view(S1).reshape(len(a),-1)[:,start:end]return np.fromstring(b.tostring(),dtypeSstr(end-start))样品运行 –In [68]: a np.array([hello, how, are, you])In [69]: slicer_vectorized(a,1,3)Out[69]:ar…

数据库的概念

数据存储方式 计算机数据(Data)的存储一般以硬盘为数据存储空间资源,从而保证计算机内的数据能够持续保存。对于数据的处理,一般会采用数据库相关的技术进行处理,从而保证数据处理的高效性。 采用数据库的管理模式不…

高中关于人工智能方面的课题_2019山东人工智能教育专项课题指南选题

人工智能教育专项课题,2019年度山东省教育规划课题已经启动,申报者有这方面的申报意向,就需要知道选题范围,以下是2019山东人工智能教育专项课题指南选题。小学人工智能教育课程体系、教学策略及教学评价的研究初中人工智能教育课…

linux qt5.9交叉编译,QT5.9移植

1.下载Qt源码Qt源码下载地址:Index of /archive/qt 其他源码和其他安装包都是有的。2.解压源码$ mkdir qt5.9$cd qt5.9将下载文件拷贝到当前目录下面。解压$ xz -d qt-everywhere-opensource-src-5.9.7.t…

python雪花算法生成id_理解分布式id生成算法SnowFlake

分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。概述SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图:1位,不用。二进制中最高位为1的都是负数,但是我们生成的id一般都使用整数&a…

linux wps 公式编辑器,WPS 2012数学公式编辑器的使用方法(详细图解)

做数学或物理课件时很多公式是件比较头痛的事。时常陷入无穷的拼接法中,用一个一个文本框组合成复杂的公式。其实WPS 2012e为我们提供了一个功能强大的公式编辑器Equation Editor,可以帮助我们解决这些问题。1、插入公式将光标放置于欲插入公式的位置&am…

linux utmp结构体,Linux C编程如何使用联机帮助来解决编程问题?

1.背景多次学习C语言一直无法踏入C语言的大门,每次都是在学习C语言中的那些系统调用库函数等望而却只,linux下的系统调用需要我们去记忆一些没有规律的结构体和一些大写的宏定义并且还有一个函数多种形式的例如print fprintf sprintf等等,看起…

ios 画线平滑_iOS 画贝塞尔曲线 连续曲线 平滑曲线 曲线图表

利用贝塞尔曲线画一段连续曲线bezierDemo2.pngbezierDemo1.pngimage.png如果我们根据几个点画一条连续的曲线, 我们使用的方法是- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;这个方法是由一个结束点…

python中怎么判断字母大小写_python判断字符串是字母 数字 大小写(转载)

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼今天遇到的字符串处理的问题,记录一下方便使用str1 input(请输入一个字符:)#初始化字符、数字、空格、特殊字符的计数lowercase 0uppercase 0number 0space 0other 0for strs in str1:#如果在字符串中…

深度linux安装好上不了网,Deepin Linux 无法上网

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼我又用回2008了LINUX图形界面还是太慢 我的感觉太敏锐 虽然LINUX的图形界面的延迟 从你鼠标发出信号 到XSERVER的视觉呈现也就几百毫秒 但还是感觉比WINDOWS NT的效率差了几百倍 .用的越久感觉越明显.WINDOWS图形界面下的操控不管你…

php 伪静态 获取当前页面路径_织梦移动适配PHP获取当前页面URL地址方法

在做织梦网站开发时,会遇到获取当前URL并做PHP判断。比如地区站群PC端的移动适配功能,下面提供PHP通用移动端适配方法。PC首页路径:www.xx.com移动端首页路径:m.xx.com地区PC首页路径:beijing.xx.com地区移动端首页路径…