Resque是GitHub团队开源的一个Ruby后台任务框架,底层依赖Redis做队列存储,因为结构简单、稳定可靠,至今仍有不少Rails项目在用它处理异步任务。不过在Ubuntu上从零配置Resque,中间会踩到不少坑,比如Redis没有设置密码导致连不上、Worker启动后任务堆积不消费、进程挂掉没人拉起等。这篇文章把完整的配置流程拆开讲一遍,从环境准备到生产环境的进程守护,一步步给出可执行的命令和配置。

一、安装并配置Redis环境
Resque的队列数据全部存在Redis里,所以第一步是把Redis装好。Ubuntu自带的软件源里就有Redis,直接用apt安装即可:
sudo apt update sudo apt install redis-server -y
装完之后Redis会自动以systemd服务的形式启动,可以用systemctl status redis-server确认状态。默认配置文件在/etc/redis/redis.conf,生产环境建议至少改两处:一是设置requirepass给Redis加密码,避免队列数据裸奔;二是如果Resque和Redis在同一台机器上,保持bind 127.0.0.1即可,不要监听公网地址。
改完配置记得重启服务:sudo systemctl restart redis-server。然后用redis-cli验证一下连接是否正常:
redis-cli -a 你的密码 ping # 返回 PONG 说明正常
这里有个常见的坑:如果设置了密码但项目里没配置,Resque在入队时会抛出NOAUTH错误,排查起来容易让人误以为是Gem安装问题。所以密码改完之后,一定要记得同步更新应用的Resque连接配置。
二、在项目中集成Resque并编写Job
环境准备好后,在项目的Gemfile里加入Resque依赖:
gem 'resque'
然后执行bundle install。接着需要告诉Resque怎么连Redis,一般是在项目根目录建一个config/initializers/resque.rb文件:
Resque.redis = Redis.new(host: '127.0.0.1', port: 6379, password: '你的密码', thread_safe: true)
接下来定义Job类。Resque的Job就是一个带有self.perform类方法的普通Ruby类,同时要用@queue声明它属于哪个队列:
class SendEmailJob
@queue = :email
def self.perform(user_id, template)
user = User.find(user_id)
Mailer.send_template(user, template).deliver_now
rescue => e
logger.error "发送邮件失败: #{e.message}"
raise e
end
end入队的方式非常简单,调用Resque.enqueue即可:Resque.enqueue(SendEmailJob, user.id, 'welcome')。任务会以JSON形式序列化后写进Redis的email队列,等Worker来消费。要注意perform的参数必须是能被JSON序列化的类型,传对象进去会报错,一般都传id,在Job内部再查库还原对象。
另外建议在config/resque.rake里加载任务目录,方便统一管理:
require 'resque/tasks' task 'resque:setup' do ENV['QUEUE'] = '*' require './config/environment' end
三、启动Worker并配置进程守护
启动Worker最直接的方式是用rake任务:QUEUE=email rake environment resque:work。其中QUEUE环境变量指定要消费的队列,写成*表示消费所有队列,也可以用逗号分隔多个队列并设置优先级,比如QUEUE=email,export表示优先处理email队列。加上VERBOSE=1可以输出详细日志,排查问题的时候很有用。
但直接在终端跑Worker显然不适合生产环境,终端一关进程就没了。Ubuntu上推荐用systemd做守护。创建一个服务文件/etc/systemd/system/resque-worker.service:
[Unit] Description=Resque Worker After=redis-server.service [Service] Type=simple User=deploy WorkingDirectory=/home/deploy/myapp Environment=QUEUE=email ExecStart=/bin/bash -lc 'cd /home/deploy/myapp && bundle exec rake environment resque:work' Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
保存后执行sudo systemctl daemon-reload和sudo systemctl enable --now resque-worker,Worker就会开机自启,进程异常退出后5秒内自动拉起。如果想提高消费能力,可以配置多个Worker实例,一种做法是写多个service文件,另一种是用COUNT=3参数让rake一次性fork出3个Worker进程:COUNT=3 QUEUE=* rake environment resque:work。
最后再说两个日常运维要点。一是任务失败会进入failure列表,可以用resque-web这个Web界面查看,在Gemfile里加gem 'resque-web'并挂载路由就能可视化查看队列长度和失败任务。二是记得给Redis配置合适的内存策略,Resque的队列数据都堆在内存里,如果队列积压严重,Redis内存打满后任务数据可能被淘汰,生产环境要把maxmemory-policy设置成noeviction,宁可写入报错也不要悄悄丢任务。把这几步都做完,Resque在Ubuntu上基本就能稳定跑了。