分佈式任務隊列 Celery —— 應用基礎

目錄

前文列表

分佈式任務隊列 Celery
分佈式任務隊列 Celery —— 詳解工作流

前言

緊接前文,繼續看 Celery 應用基礎,下列樣例依舊從前文 proj 中進行修改。

Celery 的週期(定時)任務

Celery 週期任務功能由 Beat 任務調度器模塊支撐,Beat 是一個服務進程,負責週期性啓動 beat_schedule 中定義的任務。
e.g.

# filename: app_factory.py
from __future__ import absolute_import
from celery import Celery
from kombu import Queue, Exchange


def make_app():
    app = Celery('proj')
    app.config_from_object('proj.celeryconfig')

    default_exchange = Exchange('default', type='direct')
    web_exchange = Exchange('task', type='direct')
    app.conf.task_default_queue = 'default'
    app.conf.task_default_exchange = 'default'
    app.conf.task_default_routing_key = 'default'

    app.conf.task_queues = (
        Queue('default', default_exchange, routing_key='default'),
        Queue('high_queue', web_exchange, routing_key='hign_task'),
        Queue('low_queue', web_exchange, routing_key='low_task'),
    )

    # 設定 Beat 時區,默認爲 UTC 時區
    app.conf.timezone = 'Asia/Shanghai’
    # 在 beat_schedule 中聲明週期任務
    app.conf.beat_schedule = {
        # 週期任務 Friendly Name
        'periodic_task_add': {
            # 任務全路徑
            'task': 'proj.task.tasks.add’,
            # 週期時間
            'schedule': 3.0,
            # 指定任務所需的參數
            'args': (2, 2)
        },
    }
    return app

使用 -B 選擇,表示啓動 Celery Worker 服務進程的同時啓動 Beat 模塊。

這裏寫圖片描述

NOTE 1:Beat 會把週期任務的時間表存儲在 celerybeat-schedule 文件,在執行指令的當前目錄生成。當 timezone 發生改變時,Beat 會根據 celerybeat-schedule 的內容自動調整計時方式。

NOTE 2:Beat 也支持 crontab 計時方式,十分簡單易用。
e.g.

# filename: app_factory.py
from celery.schedules import crontab

…
    app.conf.beat_schedule = {
        'periodic_task_add': {
            'task': 'proj.task.tasks.add’,
            # 每隔一分鐘週期執行
            'schedule': crontab(minute='*/1'),
            'args': (2, 2)
        },
    }

Celery 的同步調用

Task.get 方法處理用於獲取任務的執行結果之外,還能夠用於實現 Celery 同步調用,以滿足更多的應用場景。
e.g.

# filename: tasks.py

import time

from proj.celery import app


@app.task
def add(x, y, debug=False):
    # Test sync invoke.
    time.sleep(10)
    for i in xrange(10):
        print("Warting: %s s" % i)
    if debug:
        print("x: %s; y: %s" % (x, y))
    return x + y

同步調用任務 add

>>> from proj.task.tasks import add
>>> add.delay(2, 2).get()
4

這裏寫圖片描述

因爲直接調用了 get 方法,所以進程會被阻塞知道任務 add 返回結果爲止。

Celery 結果儲存

如果你對任務執行的結果非常關注,那麼你可以使用數據庫(e.g. Redis)來充當 Backend,從而將執行結果持久化。
e.g.

# 執行一個任務,並取得任務 id
>>> from proj.task.tasks import add
>>> result = add.delay(2, 2)
>>> result.status
u’SUCCESS'
>>> result.get()
4
>>> result.id
'65cee5e0-5f4f-4d2b-b52f-6904e7f2b6ab’

進入 Redis 數據庫,查看該任務對應的記錄。

root@aju-test-env:~# redis-cli
127.0.0.1:6379>

# 查看 Redis 所有的 keys
127.0.0.1:6379> keys *
 1) "celery-task-meta-da3f6f3d-f977-4b39-a795-eaa89aca03ec"
 2) "celery-task-meta-38437d5c-ebd8-442c-8605-435a48853085”
...
35) "celery-task-meta-65cee5e0-5f4f-4d2b-b52f-6904e7f2b6ab"
...

# 通過任務 id,可以定位出任務在 Redis 中的 value
127.0.0.1:6379> GET 'celery-task-meta-65cee5e0-5f4f-4d2b-b52f-6904e7f2b6ab'
"{\"status\": \"SUCCESS\", \"traceback\": null, \"result\": 4, \"task_id\": \"65cee5e0-5f4f-4d2b-b52f-6904e7f2b6ab\", \"children\": []}"

Celery 的監控

Celery Flower 是 Celery 官方推薦的監控工具,藉助於 Celery Events 接口,Flower 能夠實時監控 Celery 的 Worker、Tasks、Broker、併發池等重要對象。

  • 安裝 Flower
$ pip install flower
  • 開啓 Celery Events
celery worker -A proj -E -l info

這裏寫圖片描述

  • 開啓 RabbitMQ Management Plugin
$ rabbitmq-plugins enable rabbitmq_management
$ service rabbitmq-server restart
  • 啓動 Flower,並指定 broker URL
>nbsp;celery flower -l info --broker_api=http://guest:guest@<rabbitmq_server_ip>:15672/api/

這裏寫圖片描述

  • 訪問 Flower Web,瀏覽器打開 http://<flower_server_ip>:5555/dashboard

這裏寫圖片描述

Celery 的調試

Celery 藉助 telnet 可以支持遠程 pdb 調試,非常方便。

# filename: tasks.py
from proj.celery import app
from celery.contrib import rdb


@app.task
def add(x, y):
    # 設置斷點
    rdb.set_trace()
    return x + y

使用 celery.contrib 的 rdb 來設置斷點,然後重啓 Celery Worker 服務。

這裏寫圖片描述

可以看見日誌中提示了 telnet 遠程連接的地址,所以打開另外一個終端,執行 telnet 指令即可完成連接,進入到非常熟悉的 pdb shell。

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章