laravel是一个高度依赖包管理器与命令行界面的php框架。不使用composer
和php artisan
两个工具几乎寸步难行。……不过这也并不意味着laravel就是虚拟主机没戏,必须VPS/云主机起跳的“小网站杀手”。
其实在cPanel虚拟主机上,部署laravel并不是那么难的事情,因为仁慈的cPanel面板,一般都开放有操作Linux原生cron jobs的设置页面。
只要有了cron这个口子,就可以获得执行命令行任务的机会,每分钟1次——这已经足够了。
但是实际使用中发现,laravel的其他功能都没毛病,就是异步队列根本不能用。考察laravel提供的原生异步队列驱动器,没有一个适合在虚拟主机环境中使用:
- 同步(sync):只是残废的调试工具
- Beanstalkd:虚拟主机不会有
- Redis:虚拟主机不会有
- IronMQ:要美元
- Amazon SQS:要美元
我考虑了很多方案(包括一些很土炮的馊主意),最终还是遵守了laravel的哲学[注A]
,写了一个原生的MySQL队列驱动器。
原理
就是数据库一张表。加入任务时写入,执行任务时检索,需要删除时打标记(软删除)。
即使使用Queue::later()
推迟任务,任务信息也会立刻写入表格,而不设计“主动推迟一定时间再写入”的复杂。表格中记录有任务的执行时刻,没到时间的任务会在检索时被自然忽略。
性能确实低下(受制于MySQL),绝对禁止用于大数量、高密度任务的场合。但是部署极其简易,所以很适合小网站、偶发性、时效性不强的异步任务。
特点
100%完整实现,Laravel文档规定的用法全部支持。具体而言:
- 支持原生的
queue:listen
,queue:work
等 artisan 队列操作 - 不在 artisan 上画蛇添足去定义额外的命令
- 支持记录重试次数,正确对接laravel的失败任务回收系统
- 支持任意多个队列,支持自定义默认队列名称
- 只占用1个数据表,支持自定义表名,允许数据库有表前缀
- 不使用Eloquent ORM
安装
composer.json
增加以下依赖包,并做 composer update
[注B]
:
"shamiao/l4mysqlqueue": "~1.0"
编辑 config/app.php
增加 provider
条目:
'Shamiao\L4mysqlqueue\L4mysqlqueueServiceProvider'
编辑 config/queue.php
设置队列驱动器:
'default' => 'mysql', // 这个是连接名,随意。惯例是写成和驱动器同名的'mysql'
'mysql' => array( // 这个和'default'右边那个一致就好
'driver' => 'mysql', // 驱动器名,这里就必须写成'mysql'了!
'queue' => 'default', // 如有需要,可以指定默认队列名,推荐直接删去不写
'table' => 'queue',' // 如有需要,可以指定表格名,推荐直接删去不写
),
最后把本软件包(package)附带的迁移操作(migrations)并入数据库[注C]
:
php artisan migrate --package="shamiao/l4mysqlqueue"
使用
没什么好说的。这个驱动器对用户而言是透明的,所以Laravel文档的Queue页面怎么说就可以怎么做。
是完整实现,所以文档中提到的功能全都没有禁忌。
如果在虚拟主机环境下,运行一个必须持续跑着的 queue:listen
或 queue:work --daemon
不方便,也可以像这样利用cron来变通的执行[注D]
:
* * * * * ( cd /home/username/your/laravel/dir; php artisan queue:work --tries=3 )
当然代价就是每分钟只能执行一个任务了。
注意
- 删除任务时只打标记做软性删除,所以数据表
queue
必然只膨胀不减小。请记得自拟计划,在负载不高时把status = 'deleted'
的任务真正的DELETE掉。 - 很多实现还会调整,如有任何变化请以GitHub说明为准。
链接
From GitHub and Composer with love:
本项目代码均为独立,开发过程受到过两个不完善实现 barryvdh/laravel-async-queue 和 octoberrain/cron 的启发。
注释
- A:①要艺术,不要把代码写的很“脏”。 ②接口遍地都是,有需要,就扩展。
- B: 虚拟主机肯定不会提供composer。你需要自己下载
composer.phar
,放到主文件夹下边,然后执行php /home/username/composer.phar update
。- C: 根据主机环境不同,可能部分主机要用
php5
代替php
,也可能有部分主机没有PATH变量,必须手动打/usr/bin/php
完整路径。- D:不妨写成
.sh
脚本文件并设置权限755,这样在cron job里只需要指定脚本完整路径即可,日后修改也方便。