news 2026/9/24 23:06:17

使用 Supervisor 守护 RQ Worker:生产环境进程管理与配置实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 Supervisor 守护 RQ Worker:生产环境进程管理与配置实战

使用 Supervisor 守护 RQ Worker:生产环境进程管理与配置实战

【免费下载链接】rqSimple job queues for Python项目地址: https://gitcode.com/gh_mirrors/rq/rq

Supervisor 是生产环境中管理 RQ Worker 这类长驻进程的经典工具,它能自动重启崩溃的进程,并用统一的面板集中查看构成产品的所有进程状态。本文以 RQ 仓库中的官方指南 docs/patterns/supervisor.md 为主体,结合rq worker命令的源码实现,讲解 supervisor 配置文件的每个关键字段、RQ 对终止信号的特殊要求,以及 virtualenv 与 Conda 环境下的完整部署方案。读完本文,你将能够为 RQ Worker 写出一份可直接上生产、可自动拉起、可优雅停机的 supervisor 配置。

为什么用 Supervisor 管理 RQ Worker

RQ Worker 是一个典型的"永远在跑"的进程:它从 Redis 队列中不断取出任务并执行,队列为空时就阻塞等待新任务。这样的进程一旦被误杀、崩溃或服务器重启,就需要有人把它重新拉起来——这正是 Supervisor 的用武之地:

  • 自动重启:进程意外退出时自动拉起,保证任务消费能力不中断;
  • 统一管理:通过supervisorctl或 Web 面板查看/控制所有受管进程,产品由多个服务组成时尤其方便;
  • 与 RQ 天然契合:RQ 官方在 docs/docs/workers.md 中明确建议,生产环境应使用 Supervisor 或 systemd 这类进程管理器来运行 Worker。

RQ 与 Supervisor 的结合非常简单,核心就是一个[program:xxx]配置块。下面从最常用的配置说起。

基础配置:把 RQ Worker 交给 Supervisor

把下面这份配置写入 Supervisor 的配置目录(如/etc/supervisor/conf.d/rqworker.conf),这是官方文档给出的推荐设置:

[program:myworker] ; Point the command to the specific rq command you want to run. ; If you use virtualenv, be sure to point it to ; /path/to/virtualenv/bin/rq ; Also, you probably want to include a settings module to configure this ; worker. For more info on that, see docs/docs/workers.md command=/path/to/rq worker -c mysettings high default low ; process_num is required if you specify >1 numprocs process_name=%(program_name)s-%(process_num)s ; If you want to run more than one worker instance, increase this numprocs=1 ; This is the directory from which RQ is ran. Be sure to point this to the ; directory where your source code is importable from directory=/path/to ; RQ requires the TERM signal to perform a warm shutdown. If RQ does not die ; within 10 seconds, supervisor will forcefully kill it stopsignal=TERM ; These are up to you autostart=true autorestart=true

这份配置虽短,但每一行都对应着 RQ 运行机制的一个关键点,逐一拆解如下。

command:启动命令的三种写法

command是 Supervisor 要执行的进程启动命令,写法取决于你的 Python 环境:

场景写法说明
系统级 Pythoncommand=/path/to/rq worker -c mysettings high default low直接用 RQ 的可执行脚本
virtualenvcommand=/path/to/virtualenv/bin/rq worker ...务必指向虚拟环境内的rq可执行文件,而不是系统全局的
Conda envcommand=/opt/conda/envs/myenv/bin/rq worker ...指向 Conda 环境目录下的rq,详见下文 Conda 小节

命令中的high default low是队列名列表,Worker 按给定顺序监听这些队列,优先级从左到右递减:先消费完high队列的任务,再处理default,最后是low

-c mysettings让 Worker 从mysettings模块读取配置(即mysettings.py)。从源码看,rq/cli/helpers.py 的read_config_file会导入该模块并读取其中所有大写命名的变量作为设置,因此你可以在配置模块中声明REDIS_URLQUEUESNAMEDICT_CONFIG等项(完整支持项见 docs/docs/workers.md 的 "Using a Config File" 一节)。注意 Supervisor 默认不会把当前目录加入PYTHONPATH,所以同时要用下面的directory指对工作目录。

process_name 与 numprocs:多 Worker 实例

process_name=%(program_name)s-%(process_num)s numprocs=1
  • numprocs指定启动多少个进程实例。想横向扩展消费能力时,把它调大即可(例如numprocs=4表示同时跑 4 个 Worker)。
  • 一旦numprocs > 1process_name必须设置,否则 Supervisor 无法区分同名进程。%(program_name)s对应[program:myworker]的名字myworker%(process_num)s是实例序号,最终进程名为myworker-0myworker-1……

关于并发模型,需要澄清一点:单个 RQ Worker 内部是串行处理任务的(每个 Worker 同一时刻只执行一个 Job,任务在子进程"work horse"中运行)。要提高并发吞吐,正确姿势就是多开 Worker 进程——用numprocs放大,或使用 RQ 1.14.0 起的rq worker-pool命令(见 rq/cli/workers.py 的worker_pool实现)。两种方式在 Supervisor 下都可行。

directory:工作目录决定了 import 是否成功

directory=/path/to

Worker 从这个目录启动,Python 才能把你的业务代码(任务函数所在模块)导入进来。务必指向你的源码可被 import 的目录,一般就是项目的根目录。这也是配合-c mysettings使用的前提之一——如果mysettings.py在项目根目录,而directory指错了地方,Worker 会直接因导入失败而退出。

stopsignal=TERM:RQ 优雅停机的前提

stopsignal=TERM

这是整个配置里与 RQ 行为耦合最深的一行,也是最容易踩坑的地方。

RQ 的 Worker 在启动时会安装SIGINTSIGTERM的信号处理器(见 rq/worker/base.py 的_install_signal_handlers)。收到一次SIGTERM时,Worker 执行的是暖关闭(warm shutdown):停止接收新任务,但会等当前正在执行的任务跑完,然后优雅地注销自身(源码见 rq/worker/base.py 的request_stop)。这一行为在测试中也有明确验证,例如 tests/test_worker.py 中的test_working_worker_warm_shutdown:向正在执行任务的 Worker 发送一次 SIGTERM,任务仍能正常完成,之后 Worker 才退出。

如果在暖关闭过程中再次收到SIGINTSIGTERM,Worker 会转入冷关闭(cold shutdown):立即向子进程发送SIGKILL强杀当前任务,然后退出(见 rq/worker/base.py 的request_force_stop)。对应测试为test_working_worker_cold_shutdown:忙时发两次 SIGTERM,Worker 立即抛SystemExit,正在运行的任务被中断。

因此 Supervisor 这边必须stopsignal=TERM(而不是默认的TERM之外的信号),才能触发 RQ 的暖关闭。配合 Supervisor 默认的 10 秒stopwaitsecs:如果 Worker 在 10 秒内没有正常退出(比如当前任务执行了很久),Supervisor 会强制SIGKILL掉它——这相当于人工触发了一次冷关闭,属于兜底手段。如果生产任务单个执行时间较长,可以适当调大stopwaitsecs,给暖关闭留足时间。

autostart 与 autorestart

autostart=true autorestart=true
  • autostart=true:Supervisor 自身启动(如开机/supervisord启动)时自动拉起该程序;
  • autorestart=true:进程异常退出时自动重启。

这两项是"守护"二字的落点,按需设置即可。

Conda 环境:为非 Python 依赖提供运行环境

当 RQ 任务需要非 Python 的依赖(例如 C 库、系统工具)时,可以借助 Conda 虚拟环境来承载这些依赖。官方文档给出的思路与 virtualenv 完全一致,只是路径换成 Conda 环境:

[program:myworker] ; Point the command to the specific rq command you want to run. ; For conda virtual environments, install RQ into your env. ; Also, you probably want to include a settings module to configure this ; worker. For more info on that, see docs/docs/workers.md environment=PATH='/opt/conda/envs/myenv/bin' command=/opt/conda/envs/myenv/bin/rq worker -c mysettings high default low ; process_num is required if you specify >1 numprocs process_name=%(program_name)s-%(process_num)s ; If you want to run more than one worker instance, increase this numprocs=1 ; This is the directory from which RQ is ran. Be sure to point this to the ; directory where your source code is importable from directory=/path/to ; RQ requires the TERM signal to perform a warm shutdown. If RQ does not die ; within 10 seconds, supervisor will forcefully kill it stopsignal=TERM ; These are up to you autostart=true autorestart=true

与基础版相比,区别只在两处:

  1. environment=PATH='/opt/conda/envs/myenv/bin':把 Conda 环境的bin目录注入PATH。这样 Worker 在 fork 出的子进程里执行任务时,能找到该环境内的可执行程序(比如任务调用的某个命令行工具)。如果任务还需要该环境里的动态库,可以进一步追加LD_LIBRARY_PATH之类的键值对,多个变量用逗号分隔。
  2. command指向环境内的rq:前提是先把 RQ 安装进这个 Conda 环境(如conda install -n myenv rqpip install rq)。注意这里和 virtualenv 一样,指向的是环境内部的rq可执行文件。

其余字段(process_namenumprocsdirectorystopsignal=TERMautostartautorestart)的含义与基础版完全相同。

配套的 RQ 配置文件

Supervisor 里的-c mysettings需要一个真正的mysettings.py。官方推荐的配置项如下,可直接作为模板:

REDIS_URL = 'redis://localhost:6379/1' # You can also specify the Redis DB to use # REDIS_HOST = 'redis.example.com' # REDIS_PORT = 6380 # REDIS_DB = 3 # REDIS_PASSWORD = 'very secret' # Queues to listen on QUEUES = ['high', 'default', 'low'] # If you want custom worker name # NAME = 'worker-1024' # If you want to use a dictConfig for more complex/consistent logging DICT_CONFIG = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s' }, }, 'handlers': { 'default': { 'level': 'INFO', 'formatter': 'standard', 'class': 'logging.StreamHandler', 'stream': 'ext://sys.stderr', # Default is stderr }, }, 'loggers': { 'root': { # root logger 'handlers': ['default'], 'level': 'INFO', 'propagate': False }, } }

要点说明:

  • REDIS_URL优先;也可以改用REDIS_HOST/REDIS_PORT/REDIS_DB/REDIS_PASSWORD组合。若设置了QUEUES,命令行上的队列名可以省略——源码 rq/cli/workers.py 中queues = queues or settings.get('QUEUES', ['default']),命令行参数优先于配置文件。
  • NAME可指定自定义的 Worker 名,方便在rq info与监控面板中识别。
  • DICT_CONFIG使用 Pythonlogging.config.dictConfig做复杂日志配置;RQ 也尊重应用先配置好的日志处理器,避免重复配置。
  • 从 rq/cli/helpers.py 的get_redis_from_config可以看出,配置文件还支持REDIS_SSLREDIS_SSL_CA_CERTS等 SSL 选项以及SENTINEL字典(Redis Sentinel 场景),有需要的可查阅源码后按需添加。

配置完成后:如何验证与运维

  1. 重载配置并启动:supervisorctl reread然后supervisorctl update(或直接supervisorctl start myworker)。
  2. 查看状态:supervisorctl status,应看到myworker处于RUNNING
  3. 观察日志:supervisorctl tail -f myworker,正常会看到类似*** Listening for work on high, default, low的输出。
  4. 验证优雅停机:supervisorctl stop myworker,此时 Worker 若正在执行任务,会等任务完成后才退出(暖关闭);对正在跑的任务可以先手动确认其确实执行完毕。源码层面的依据可查看 tests/test_worker.py 中的WorkerShutdownTestCase,它覆盖了空闲暖关闭、忙时暖关闭与忙时冷关闭三条路径。
  5. 验证自动重启:supervisorctl signal KILL myworker(模拟崩溃),Supervisor 应依据autorestart=true自动拉起新进程。

补充:另一个选择 systemd

如果你的发行版内置 systemd(多数现代 Linux 发行版),也可以参考 RQ 官方的另一种模式 docs/patterns/systemd.md:通过rqworker@.service模板单元文件配合systemctl start rqworker@1.service启动多实例,ExecStop=/bin/kill -s TERM $MAINPID同样遵循"SIGTERM 触发暖关闭"的原则。两种进程管理器任选其一即可,不要在同一个 Worker 上重复叠加。

小结

把 RQ Worker 交给 Supervisor 管理,本质上就是回答四个问题:用什么命令启动(指向正确环境的rq,队列按优先级排列,-c指定配置模块)、在哪个目录启动directory指向源码可导入的目录)、想要几个实例numprocs配合process_name)、停机时发什么信号stopsignal=TERM触发暖关闭)。掌握这几条,再结合 Conda 环境注入与 RQ 配置文件,即可得到一套可靠、可观测、可优雅上下线的生产级 Worker 守护方案。

相关参考:

  • 官方模式指南:docs/patterns/supervisor.md、docs/patterns/systemd.md
  • Worker 使用详解:docs/docs/workers.md
  • CLI 命令实现:rq/cli/workers.py、rq/cli/helpers.py
  • 信号处理与关闭逻辑:rq/worker/base.py
  • 关闭行为测试:tests/test_worker.py

【免费下载链接】rqSimple job queues for Python项目地址: https://gitcode.com/gh_mirrors/rq/rq

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 23:05:17

工业现场算力下沉:PLC与边缘计算控制器的三笔账

“PLC用得好好的,为什么还要上边缘计算控制器?”这句话,我在工业现场被问过不下几十次。问的人通常不是抬杠,而是担心又折腾一个用不上的新概念。我一般不会急着讲CPU、实时操作系统、协议转换这些技术词,而是先跟他算…

作者头像 李华
网站建设 2026/9/24 23:05:00

Modbus Studio:一站式Modbus协议调试与报文分析工具实战指南

搞工控和上位机开发的朋友,对 Modbus 这个词一定不陌生。它是工业现场最普及的通讯协议,PLC、变频器、智能仪表、传感器,只要带 RS485 口的设备,十有八九都支持 Modbus RTU,新一点的设备还会提供 Modbus TCP。可协议普…

作者头像 李华
网站建设 2026/9/24 23:04:32

Orca:并行调度多AI编程Agent的实战指南

如果你最近同时维护两个老项目,又要在三天内把一堆小需求排进迭代,一定会懂我下面说的这种体验:GitHub Copilot 在 IDE 里补全得挺欢,但一让它跨文件改逻辑就开始“眼花”;Codeium 免费额度用得挺舒服,可长…

作者头像 李华
网站建设 2026/9/24 23:02:50

开发Android手机安全管家:权限审计与RSA+AES数据加密实战

1. 研究思路:为什么需要一套“手机安全管家”智能手机早已不只是通讯工具了。微信里躺着工作群消息,相册里存着身份证照片,备忘录里记着银行卡号,甚至很多人的支付类App还开着免密小额支付。换句话说,手机就是数字身份…

作者头像 李华
网站建设 2026/9/24 23:01:46

GitHub趋势榜观察:AI工作流、效率小工具与新手避坑实用指南

先说个有意思的观察:周日晚上整理 GitHub 日榜趋势速报,跟工作日完全是两种画风。周中的榜单会被各类工作流框架、AI Agent 工程、云原生运维工具占满,到了周末,能明显看到一批游戏工具、桌面小工具、可视化小项目往上蹿。2026-09…

作者头像 李华