前段时间在开发一个量化交易系统,这是一个类似股票交易软件的系统:股票价格变化后要实时在终端(APP)的行情价格页面实时更新,如果用户是在持仓页面,还要计算持仓盈亏及预付款比例,因为有一个强制平仓机制(当预付款比较低于30%时系统要自动触发强制平仓),因为行情波动非常快(有些产品一秒钟内价格会变化五六次),所以当某个产品的价格变化时,要触发一系统的行情推送(通过长连接)及盈亏计算操作。
因为价格变动非常快,如果使用同步操作的话,很容易造成阻塞,所以用异步消息队列是比较好的选择,在网上查了一番,决定用resque来实现,试用了一下,发现网上所谓的resque教程大都是将它的demo代码讲解了一遍,坑很多,所以把我试用过程中遇到的问题统一做个记录,一个是方便同样正在尝试使用resque的朋友,二是作为自己的备忘录,好,下面正式开始。
网上很多教程的指引还是安装源chrisboulton/php-resque
版本的,实际上现在最新的版本应该是resque/php-resque
源的, 用composer安装的方法是,在composer.json
文件中的require节点下添加”resque/php-resque:^1.2
”,
然后执行composer install
即可。
resque是基于redis的,所以没有redis是运行不起来的,可能开发者初期没有考虑到redis有设置了密码的情况,所以我刚开始看网上的资料是有介绍怎样解决这个问题的,但我把代码签出来后发现Resque::setBackend
的方法是支持传入auth参数的,于是以为这个问题已经在目前的版本里解决了,实际上还是不行,如果你的redis里设置了密码,建议修改插件目录下的resque/php-resque/lib/Resque.php
这个文件,大概在68行将创建redis连接的代码用以下代码代替可以解决连接redis失败的问题。
$redis = new Redis();
$redis->connect(self::$redisServer);
$redis->auth(self::$auth);
$redis->select(self::$redisDatabase);
self::$redis = $redis;
修改完后将redis的密码通过setBackend方法的第三个参数传入就可以了,示例:
Resque::setBackend('127.0.0.1', 1, \Config::$redis['option']['auth']);
如果你看了其它网友的经验分享,你会知道resque有三个角色:Queue、Worker、Job
,Queue负责接收消息队列,Worker负责任务调度,Job负责执行业务逻辑,用现实生活举例就是像一个高铁站一样,Queue是售票厅、Worker是控制室、Job则是车队,以下我也分三部分说下这个注意事项:
Resque::setBackend('127.0.0.1', 1, \Config::$redis['option']['auth']);
for($i = 1; $i < 10; $i++){
Resque::enqueue('pushMarketPrice', '\site_pc\action\Job', ['newPrice' => 1367.85, 'rate' => 7.09]);
}
class Worker{
/**
* @router cli work
*/
public function run(){
require "../vendor/resque/php-resque/bin/resque";
}
}
其中,require后面的路径请修改为相对你项目执行文件入口的路径。
$this->args
就能拿到传入的参数数组,非常方便。class Job{
public function perform(){
Tools::logToDb('resque', $this->args);
}
}
$this->args
就是你此前在Queue中传入的自定义参数数组了。
怎样判断resque的状态(是否在正常运行中)呢?还有如果已经在运行,怎样重启?可以通过查看进程的命令来达到这个目的,登录系统后执行: ps -aux | grep resque
如果resque正在运行中,你看到的界面应该是这样的:
其中,上图椭圆形圈中的是进程ID,如果希望停止运行,可以使用kill -9 [进程id]
来杀死进程,红方框则是进程状态,正在等待队列中的任务。一有任务就会执行,至此,这个插件已经在正常运行了。