Consumer創建
Consumer與Worker類似,都需要使用Blueprint進行創建,我們來簡單瀏覽一下Consumer的init函數
class Consumer(object):
"""Consumer blueprint."""
def __init__(self, on_task_request,
init_callback=noop, hostname=None,
pool=None, app=None,
timer=None, controller=None, hub=None, amqheartbeat=None,
worker_options=None, disable_rate_limits=False,
initial_prefetch_count=2, prefetch_multiplier=1, **kwargs):
self.app = app
self.controller = controller
self.init_callback = init_callback
self.hostname = hostname or gethostname()
self.pid = os.getpid()
self.pool = pool
self.timer = timer
self.strategies = self.Strategies()
self.conninfo = self.app.connection_for_read()
self.connection_errors = self.conninfo.connection_errors
self.channel_errors = self.conninfo.channel_errors
self._restart_state = restart_state(maxR=5, maxT=1)
self._does_info = logger.isEnabledFor(logging.INFO)
self._limit_order = 0
self.on_task_request = on_task_request
self.on_task_message = set()
self.amqheartbeat_rate = self.app.conf.broker_heartbeat_checkrate
self.disable_rate_limits = disable_rate_limits
self.initial_prefetch_count = initial_prefetch_count
self.prefetch_multiplier = prefetch_multiplier
# this contains a tokenbucket for each task type by name, used for
# rate limits, or None if rate limits are disabled for that task.
self.task_buckets = defaultdict(lambda: None)
self.reset_rate_limits()
self.hub = hub
if self.hub or getattr(self.pool, 'is_green', False):
self.amqheartbeat = amqheartbeat
if self.amqheartbeat is None:
self.amqheartbeat = self.app.conf.broker_heartbeat
else:
self.amqheartbeat = 0
if not hasattr(self, 'loop'):
self.loop = loops.asynloop if hub else loops.synloop
if _detect_environment() == 'gevent':
# there's a gevent bug that causes timeouts to not be reset,
# so if the connection timeout is exceeded once, it can NEVER
# connect again.
self.app.conf.broker_connection_timeout = None
self._pending_operations = []
self.steps = [] # 進行一些初始化工作
self.blueprint = self.Blueprint(
steps=self.app.steps['consumer'],
on_close=self.on_close,
) # 創建blueprint
self.blueprint.apply(self, **dict(worker_options or {}, **kwargs)) # 使用blueprint進行初始化
這個函數主要進行了三項工作:
- 初始化屬性
- 創建blueprint
- 使用blueprint進行初始化
接下來我們把目光轉向Consumer類創建時Blueprint需要執行的步驟
class Blueprint(bootsteps.Blueprint):
"""Consumer blueprint."""
name = 'Consumer'
default_steps = [
'celery.worker.consumer.connection:Connection',
'celery.worker.consumer.mingle:Mingle',
'celery.worker.consumer.events:Events',
'celery.worker.consumer.gossip:Gossip',
'celery.worker.consumer.heart:Heart',
'celery.worker.consumer.control:Control',
'celery.worker.consumer.tasks:Tasks',
'celery.worker.consumer.consumer:Evloop',
'celery.worker.consumer.agent:Agent',
]
可以看到,形式上與Worker啟動時的Blueprint類似。我們首先梳理一下各個步驟的依賴關系
image.png
與Worker一樣,Consumer也會執行Blueprint實例的apply函數,初始化各個Step,創建順序為
Connection
Events
Heart
Mingle
Tasks
Control
Gossip
Agent
event loop
image.png
通過Blueprint創建完各個組件后,Consumer的創建流程完成,開始下一步的啟動操作。
組件創建流程
與之前Worker類一樣,我們來分析Consumer類創建的過程中,各個組件的創建流程