celery task 实例化过程 跟调用机制。

在 jumpserver 中 通过  很多异步执行的task,从task 入口 了解下celery 的机制过程。

首先callable 对象 都可以被当作 实例化成task,主要 是由装饰器 实现得,一种是 @app.taks 实现得 ,从这开始 作为一个入口,来看看 task 的实例化过程以及调用过程。自己写了个小demo debug 了解 task 实例化过程中 一步一步 具体的执行流程 ,最后一步是这样的,出现了 调用这个方法,返回了task。

 def _task_from_fun(self, fun, **options):
        if not self.finalized and not self.autofinalize:
            raise RuntimeError('Contract breach: app not finalized')
        base = options.pop('base', None) or self.Task
        bind = options.pop('bind', False)

        T = type(fun.__name__, (base, ), dict({
            'app': self,
            'accept_magic_kwargs': False,
            'run': fun if bind else staticmethod(fun),
            '_decorated': True,
            '__doc__': fun.__doc__,
            '__module__': fun.__module__,
            '__wrapped__': fun}, **options))()
        task = self._tasks[T.name]  # return global instance.
        return task

这个 task 对象是由元类 创造出来得,关于 元类type 怎么创造 对象,这个需要以后仔细说一说。

当一个 函数被 装饰成 task 时,这个 task 就是一个全局得对象。

from celery import Celery

app = Celery('tasks', broker='amqp://[email protected]:15672//')

@app.task
def add(x, y):
    result = x + y
    return result

调用的时候 应该这么写

from tasks import add
add.delay(1,2)

这个调用过程应该是怎样的?调用 的过程会把函数 用到的参数传进去,然后会调用 apply_async 方法。apply_async 主要是以消息形式 将 task 发送出去,而 发送消息 的客户端 主要是借助 python 消息库kombu 。而 kombu 主要作用是 实现了 一个客户端 跟 rabbitmq 或者redis  也就是broker 交互。具体源码如下,主要通过 kombu 的ensure 方法 是 建立了publish 对象 来实现发送消息。

 def ensure(self, obj, fun, errback=None, max_retries=None,
               interval_start=1, interval_step=1, interval_max=1,
               on_revive=None):
        """Ensure operation completes, regardless of any channel/connection
        errors occurring.

        Will retry by establishing the connection, and reapplying
        the function.

        :param fun: Method to apply.

        :keyword errback: Optional callback called each time the connection
          can't be established. Arguments provided are the exception
          raised and the interval that will be slept ``(exc, interval)``.

        :keyword max_retries: Maximum number of times to retry.
          If this limit is exceeded the connection error will be re-raised.

        :keyword interval_start: The number of seconds we start sleeping for.
        :keyword interval_step: How many seconds added to the interval
          for each retry.
        :keyword interval_max: Maximum number of seconds to sleep between
          each retry.

        **Example**

        This is an example ensuring a publish operation::

            >>> from kombu import Connection, Producer
            >>> conn = Connection('amqp://')
            >>> producer = Producer(conn)

            >>> def errback(exc, interval):
            ...     logger.error('Error: %r', exc, exc_info=1)
            ...     logger.info('Retry in %s seconds.', interval)

            >>> publish = conn.ensure(producer, producer.publish,
            ...                       errback=errback, max_retries=3)
            >>> publish({'hello': 'world'}, routing_key='dest')

        """

kombu 真是一个非常好的库,暴露出的接口非常简单,内部实现很好。

以上大概理解了 生产端的 代码逻辑,下面看消费端的代码实现。

当消费端 也就是 worker 开始消费 消息命令如下。这是个坑,以后再补。

 

 

 

 

 

 

 

你可能感兴趣的:(python,Devops)