Workling + Carrot + RabbitMQ 做Rails后台任务
Workling 插件可以让 rails 以异步方式执行某些消耗时间和cpu的代码,他的特点是能非常方便的与别的消息队列服务器结合,而且代码也非常简单。
RabbitMQ 是一个由erlang编写的Message Queue服务器,特点是效率非常高。
后台任务需求:
程序中存在很多 耗费时间的任务,例如 整理文件,清理数据库垃圾,生成备份文件,请求某个网站接口。
在我们点击 页面触发这些任务时,我们可能不需要 立即返回结果,但是点了连接之后,系统立即就去做这项工作,页面迟迟不跳转,而我们就傻傻的在原地等小圈圈转呀转,转到天也黑了 或者 转出 502 来了。
事实上我们可以在点击这些任务后,让页面直接跳转,让系统在背后去做这些事情。监控是否完成的事情我们可以放到以后完善。这样 点击了一次 生成备份文件后,我知道 啊 系统会帮我做这个的,我不等他了先访问别的连接吧。
关于消息队列:
一般后台任务结合消息队列 来做,
消息队列 顾名思义,消息的队列,特点:消息,先进先出。
用消息队列的原因, 系统如果在一瞬间 产生了 很多个耗费时间的任务,那么哪个任务先做,哪个任务后做呢?如果不排下顺序的话,后来的任务就可能插队伍前面去了,那么执行的结果也可能是错误的。
后台异步执行原理:
页面点击 链接 ,系统接收请求,产生一个后台任务的消息,该消息包含要执行的任务的方法和参数,将消息保存到RabbitMQ中。系统立即返回结果,页面跳转。
系统另外启动一个后台进程(background job),该进程循环读取RabbitMQ中收到的消息,有消息的时候就按顺序读出来,并且依次执行消息里隐含的任务,没有消息则等待。
过程:
刚开始 使用workling时 使用的异步服务器客户端的是Starling,跑起来很正常,但是 当多个app 在不同的 服务器上 通过workling与一个starling跑的时候,starling会出现错误,google了一下 大概是因为memcache的接口在多个不同电脑同时读取消息时会有问题。
于是想用workling + amqp + RabbitMQ,由于amqp需要服务器支持Event Machine ,而unicorn不支持所以放弃使用amqp,根据我的尝试,如果你使用Event driven mongrel 或 Thin 完全可以直接使用amqp。
就在放弃了amqp要打算放弃rabbitmq的时候,七哥 Seven 提示我一个插件carrot。这个插件是异步读取RabbitMQ中的消息,不需要包含在某个代码块中。用这个插件不需要服务器支持event machine。这就能让unicorn 和rabbitmq结合起来了。
于是仿造workling对其他client的支持,增加了 workling 对 carrot的支持,使用非常简单,代码在 https://github.com/yakjuly/workling。
使用方法:
1.安装rabbitmq
http://www.rabbitmq.com/install.html
2.安装carrot
gem sources -a http://gems.github.com/ (if necessary) sudo gem install carrot
3.配置文件
因为需要支持多个不同的app同时访问一个rabbitmq-server,所以对队列的命名增加了一个需求。
workling.yml
development: host: lcoalhost port: 5576 namespace: railsapp_development
4.environment.rb 中 添加以下代码
Workling::Remote.invoker = Workling::Remote::Invokers::CarrotSubscriber Workling::Remote.dispatcher = Workling::Remote::Runners::ClientRunner.new Workling::Remote.dispatcher.client = Workling::Clients::CarrotClient.new
5.启动后台监控进程
./script/workling_client start
目前不知道为什么workling_client restart会有问题,大家在使用的时候先用workling_client stop 再start。
在Rails3中,如果对后台任务需求并不特别要求及时或者效率的话,delayed_job是个不错的选择,如果一个网站 50% 的请求需要后台任务则 试试Redis + resque 吧。