laravel 队列消息
laravel 的队列消息非常简单的开发,原来如下:
- laravel 存储队列可以是数据库(database), 缓存(redis), 同步(sysc),等等,我们无需考虑队列的出队入队的存储,而只是需要关注,当 laravel 从队列取出一条处理工作的时,需要告诉它怎么做,也就是在代码层面上实现 /APP/Jobs/XXX.php 中的 hangdle() 方法
以 WechatTemplate.php 为例子
class WechatTemplate extends Job implements SelfHandling, ShouldQueue
{
use InteractsWithQueue, SerializesModels;
// Execute the job.
public function handle()
{
$wechat = $this->user;
if(!is_null($wechat)){
$config = config('wechat_template.'.$this->config);
try{
EasyWechat::notice()->send([
'touser' => $wechat->id,
'template_id' => $config['template_id']
]);
}catch(Exception $e){
Log::info('WechatTemplate@handle', ['message' => $e->getMessage(), 'code' => $e->getCode()]);
throw $e;
}
}
}
}
这里的 handle() 方法告诉 laravel 在从队列中取出任务的时候需要做些什么,比如这里就是告诉它发微信模板消息
- 以 database 来存储队列为例,laravel 需要两张表去装 未处理的任务队列, 还有失败的任务队列
//未处理的任务队列
php artisan queue:table
//失败的任务队列
php artisan queue:failed-table
这两条命令会产生两张表 jobs 和 failed_jobs,表中字段为:
CREATE TABLE `jobs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`queue` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`payload` longtext COLLATE utf8_unicode_ci NOT NULL,
`attempts` tinyint(3) unsigned NOT NULL,
`reserved` tinyint(3) unsigned NOT NULL,
`reserved_at` int(10) unsigned DEFAULT NULL,
`available_at` int(10) unsigned NOT NULL,
`created_at` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `jobs_queue_reserved_reserved_at_index` (`queue`,`reserved`,`reserved_at`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
queue - 队列的名字,可以在 config/queue.php 中的 connections 内进行设置
payload - 被序列化的一个整的类,拿这里的例子来说就是 WechatTemplate.php 这个类,当任务队列取出后就反序列化这个类,执行其中的 handle() 方法
- 做好前两步后,需要 php 时刻去监听这个队列是否有没有完成的任务,所以需要在项目命令下开启一个 php 进程去监听这个队列,如果一有任务进来就执行:
php artisan queue:listen --tries=3
//在生产环境中可以用 supervisor 去开启一个守护进程,如果 php 执行失败 supervisor 会自动重启一个新进程杀死旧的进程,或者 nuhup & 方式让进程进驻后台执行
nuhup php artisan queue:listen --tries=3 &
ps -ef | grep php
检查关于 php 进程时候会发现其实 php 开启了两个进程来实现任务队列,一个是 listen,一个是 work
0 6201 6200 0 4:50下午 ttys002 0:01.91 php artisan queue:listen --tries=3
0 10200 6201 0 5:36下午 ttys002 0:00.09 /usr/local/Cellar/php70/7.0.13_6/bin/php artisan queue:work --queue=default --delay=0 --memory=128 --sleep=3 --tries=3 --env=local
总结
虽然 laravel 开发消息队列非常简单,但是在生产环境中,还是需要对消息队列模块进行压力测试,如果高并发的情况下会怎么样,出错率是多少,而且最好使用高速存储 redis 去存储 队列任务。