一个worker就是一个后台运行的Python进程,用于处理那些需要长时间运行或阻塞的不想放在业务进程中去处理的任务。
启动workers
为了启动吱吱嘎嘎的work,可以简单地在你项目的根目录这样来启动:
$ rqworker high normal low *** Listening for work on high, normal, low Got send_newsletter('m@nvie.com') from defualt Job ended normaly without result *** ...
Workers将会从给定的队列中不停的循环读取任务,当所有任务都处理完毕就等待新的work到来。
每一个worker在同一时间只处理一个任务。在worker中,是没有并发的。如果你需要并发处理任务,那就需要启动多个worker。
突发模式
默认的,workers是会立即启动,处理完任务后,阻塞等待新的任务到来。也可以以突发模式启动,这样就在处理完给定的队列后立即退出。
$ rqworker --burst high normal low *** Listening for work on high, normal, low Got send_newsletter('me@nvie.com') from default Job ended normally without result No more work, burst finished. Registering death.
在需要定期处理批量任务或只是想在高峰期扩大worker处理能力的时候,该模式会比较有用。
深入worker
worker的生命周期
worker的生命周期有以下几个阶段组成:
- 启动,载入Python环境
- 注册,worker注册到系统上,让系统知晓它的存在。
- 开始监听。从给定的redis队列中取出一个任务。如果所有的队列都是空的且是以突发模式运行的,立即退出。否则,等待新的任务入队。
- 分配一个子进程。分配的这个子进程在故障安全的上下文中运行实际的任务(调用队列中的任务函数)
- 处理任务。处理实际的任务。
- 循环。重复执行步骤3。
性能说明
raworker脚本基本上就是一个获取-分叉-执行的循环。当有很多任务安装漫长时或它们都依赖于同一个模块,那每次运行任务的时候都需要付出这些昂贵的代价。这样是没问题,因为RQ不会这样造成内存泄漏,但是会变慢。
一种优化性能的处理方式就是在fork出子进程之前把需要的模块预先载入。RQ并没有提供这些设置的接口,但是你可以自己来实现。
你可以使用自己的worker脚本代替rqworker。下面是一个简单的实现:
#!/usr/bin/env python import os from rq import Queue, Connection, Worker #Preload libraries import library_that_you_want_preload # Provide queue names to listen to as arguments to this script, # similar to reworker with Connection(): qs = map(Queue, sys.argv[1:]) or [Queue()] w = Worker(qs) w.work()
Workers的名字
Workers注册到系统中都有他们自己的名字。默认的,是将主机名和当前进程id串在一起。可以通过指定参数--name来覆盖它。
停止workers
在任何时候,worker进程只要接收到信号SIGINT或SIGTERM,worker就会等待当前任务处理完成,然后停止循环,平滑的自杀(注册自己的死亡)。
如果在停止期间又收到了SIGINT或SINTERM信号,worker就会强制停止子进程(想它们发送SIGKILL信号),但是也一样会注册自己的死亡。
使用配置文件(自0.3.2版本起支持)
如果你想通过文件配置而不是通过命令行传递参数来配置rqworker,可以创建一个settings.py文件:
REDIS_HOST = 'redis.example.com' REDIS_PORT = 6380 # You c an also specify the Redis DB to use # REDIS_DB = 3 # REDIS_PASSWORD = 'very secret' # Queue to listen on QUEUES = ['high', 'normal', 'low'] # If you're using Sentry to collect you runtime exceptions, you # to configure RQ for it in a single step SENTRY_DSN = 'http://public:secret@example.com/1'
这里展示了所有支持的配置项。
注意:QUEUES和REDIS_PASSWORD自0.3.3起才支持。
可以通过参数-c指定配置文件:
$ rqworker -c settings
自定义worker的类
最新支持版本0.4.0
有时你想要自定以worker的行为。通常会有以下这些需求:
- 在运行任务之前管理数据连接。
- 使用任务运行模型,不用os.fork
- 使用不同并发模型的能力如multiprocessing或gevent
可以是用参数-w指定不同的woker类:
$ rqworker -w 'path.to.GeventWorker'