使用Celery踩過的坑

為什么要使用celery

Celery是一個使用Python開發(fā)的分布式任務(wù)調(diào)度模塊,因此對于大量使用Python構(gòu)建的系統(tǒng),可以說是無縫銜接误辑,使用起來很方便旋炒。Celery專注于實時處理任務(wù),同時也支持任務(wù)的定時調(diào)度脆淹。因此適合實時異步任務(wù)定時任務(wù)等調(diào)度場景智润。Celery需要依靠RabbitMQ等作為消息代理,同時也支持Redis甚至是Mysql未辆,Mongo等窟绷,當然,官方默認推薦的是RabbitMQ咐柜。

broker的選擇

雖然官方支持的broker有很多兼蜈,包括RabbitMQ攘残,Redis甚至是數(shù)據(jù)庫,但是不推薦使用數(shù)據(jù)庫为狸,因為數(shù)據(jù)庫需要不斷訪問磁盤歼郭,當你的任務(wù)量大了之后會造成很嚴重的性能問題,同時你的應(yīng)用很可能也在使用同一個數(shù)據(jù)庫辐棒,這樣可能導(dǎo)致你的應(yīng)用被拖垮病曾。如果業(yè)務(wù)環(huán)境比較簡單可以選擇Redis,如果比較復(fù)雜選擇RabbitMQ漾根,因為RabbitMQ是官方推薦的泰涂,但是比Redis操作起來又相對復(fù)雜些。我的選擇是broker用RabbitMQ辐怕,backend用Redis

celery不能用root用戶啟動問題 C_FORCE_ROOT environment

如果使用root用戶啟動celery會遇到下面的問題

Running a worker with superuser privileges when the
worker accepts messages serialized with pickle is a very bad idea!
If you really want to continue then you have to set the C_FORCE_ROOT
environment variable (but please think about this before you do).

解決辦法:

from celery import Celery, platforms

platforms.C_FORCE_ROOT = True  #加上這一行

任務(wù)重復(fù)執(zhí)行

celery執(zhí)行定時任務(wù)的時候遇到了重復(fù)執(zhí)行的問題逼蒙,當時是用redis做broker和backend。
官方文檔中有相關(guān)描述寄疏。

If a task is not acknowledged within the Visibility Timeout the task will
be redelivered to another worker and executed.

This causes problems with ETA/countdown/retry tasks where the time to execute exceeds the visibility timeout; in fact if that happens it will be executed again, and again in a loop.

So you have to increase the visibility timeout to match the time of the longest ETA you are planning to use.

Note that Celery will redeliver messages at worker shutdown, so having a long visibility timeout will only delay the redelivery of ‘lost’ tasks in the event of a power failure or forcefully terminated workers.

Periodic tasks will not be affected by the visibility timeout, as this is a concept separate from ETA/countdown.

You can increase this timeout by configuring a transport option with the same name:

BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': 43200}

The value must be an int describing the number of seconds.

就是說當我們設(shè)置一個ETA時間比visibility_timeout長的任務(wù)時是牢,每過一次 visibility_timeout 時間,celery就會認為這個任務(wù)沒被worker執(zhí)行成功陕截,重新分配給其它worker再執(zhí)行驳棱。
解決辦法就是把 visibility_timeout參數(shù)調(diào)大,比我們ETA的時間差要大农曲。celery本身的定位就主要是實時的異步隊列社搅,對于這種長時間定時執(zhí)行,支持不太好朋蔫。
但是第二天依然重復(fù)執(zhí)行了罚渐。。驯妄。

最后我的解決方法是在每次定時任務(wù)執(zhí)行完就在redis中寫入一個唯一的key對應(yīng)一個時間戳荷并,當下次任務(wù)執(zhí)行前去獲取redis中的這個key對應(yīng)的value值,和當前的時間做比較青扔,當滿足我們的定時頻率要求時才執(zhí)行源织,這樣保證了同一個任務(wù)在規(guī)定的時間內(nèi)只會執(zhí)行一次。

使用不同的queue

當你有很多任務(wù)需要執(zhí)行的時候微猖,不要偷懶只使用默認的queue谈息,這樣會相互影響,并且拖慢任務(wù)執(zhí)行的凛剥,導(dǎo)致重要的任務(wù)不能被快速的執(zhí)行侠仇。雞蛋不能放在同一個籃子里的道理大家都懂。
有一種簡單的方式設(shè)置queue

Automatic routing

The simplest way to do routing is to use the CELERY_CREATE_MISSING_QUEUES setting (on by default).

With this setting on, a named queue that is not already defined in CELERY_QUEUES will be created automatically. This makes it easy to perform simple routing tasks.

Say you have two servers, x, and y that handles regular tasks, and one server z, that only handles feed related tasks. You can use this configuration:

CELERY_ROUTES = {'feed.tasks.import_feed': {'queue': 'feeds'}}

With this route enabled import feed tasks will be routed to the “feeds” queue, while all other tasks will be routed to the default queue (named “celery” for historical reasons).

Now you can start server z to only process the feeds queue like this:

user@z:/$ celery -A proj worker -Q feeds

You can specify as many queues as you want, so you can make this server process the default queue as well:

user@z:/$ celery -A proj worker -Q feeds,celery

直接使用

CELERY_ROUTES = {'feed.tasks.import_feed': {'queue': 'feeds'}}
user@z:/$ celery -A proj worker -Q feeds,celery

指定routes,就會自動生成對應(yīng)的queue,然后使用-Q指定queue啟動celery就可以逻炊,默認的queue名字是celery互亮。可以看官方文檔對默認queue的名字進行修改余素。

啟動多個workers執(zhí)行不同的任務(wù)

在同一臺機器上豹休,對于優(yōu)先級不同的任務(wù)最好啟動不同的worker去執(zhí)行,比如把實時任務(wù)和定時任務(wù)分開桨吊,把執(zhí)行頻率高的任務(wù)和執(zhí)行頻率低的任務(wù)分開威根,這樣有利于保證高優(yōu)先級的任務(wù)可以得到更多的系統(tǒng)資源,同時高頻率的實時任務(wù)日志比較多也會影響實時任務(wù)的日志查看视乐,分開就可以記錄到不同的日志文件洛搀,方便查看。

$ celery -A proj worker --loglevel=INFO --concurrency=10 -n worker1.%h
$ celery -A proj worker --loglevel=INFO --concurrency=10 -n worker2.%h
$ celery -A proj worker --loglevel=INFO --concurrency=10 -n worker3.%h

可以像這樣啟動不同的worker炊林,%h可以指定hostname姥卢,詳細說明可以查看官方文檔
高優(yōu)先級的任務(wù)可以分配更多的concurrency卷要,但是并不是worker并法數(shù)越多越好渣聚,保證任務(wù)不堆積就好。

是否需要關(guān)注任務(wù)執(zhí)行狀態(tài)

這個要視具體的業(yè)務(wù)場景來看僧叉,如果對結(jié)果不關(guān)心奕枝,或者任務(wù)的執(zhí)行本身會對數(shù)據(jù)產(chǎn)生影響,通過對數(shù)據(jù)的判斷可以知道執(zhí)行的結(jié)果那就不需要返回celery任務(wù)的退出狀態(tài)瓶堕,可以設(shè)置

CELERY_IGNORE_RESULT = True

或者

@app.task(ignore_result=True)
def mytask(…):
    something()

但是隘道,如果業(yè)務(wù)需要根據(jù)任務(wù)執(zhí)行的狀態(tài)進行響應(yīng)的處理就不要這樣設(shè)置。

內(nèi)存泄漏

長時間運行Celery有可能發(fā)生內(nèi)存泄露郎笆,可以像下面這樣設(shè)置

CELERYD_MAX_TASKS_PER_CHILD = 40 # 每個worker執(zhí)行了多少任務(wù)就會死掉
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谭梗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子宛蚓,更是在濱河造成了極大的恐慌激捏,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凄吏,死亡現(xiàn)場離奇詭異远舅,居然都是意外死亡,警方通過查閱死者的電腦和手機痕钢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門图柏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人任连,你說我怎么就攤上這事蚤吹。” “怎么了随抠?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵裁着,是天一觀的道長余佃。 經(jīng)常有香客問我,道長跨算,這世上最難降的妖魔是什么爆土? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮诸蚕,結(jié)果婚禮上步势,老公的妹妹穿的比我還像新娘。我一直安慰自己背犯,他們只是感情好坏瘩,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著漠魏,像睡著了一般倔矾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柱锹,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天哪自,我揣著相機與錄音,去河邊找鬼禁熏。 笑死壤巷,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的瞧毙。 我是一名探鬼主播胧华,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宙彪!你這毒婦竟也來了矩动?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤释漆,失蹤者是張志新(化名)和其女友劉穎悲没,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灵汪,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡檀训,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了享言。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峻凫。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖览露,靈堂內(nèi)的尸體忽然破棺而出荧琼,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布命锄,位于F島的核電站堰乔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏脐恩。R本人自食惡果不足惜镐侯,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驶冒。 院中可真熱鬧苟翻,春花似錦、人聲如沸骗污。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽需忿。三九已至诅炉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間屋厘,已是汗流浹背涕烧。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留擅这,地道東北人澈魄。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓景鼠,卻偏偏與公主長得像仲翎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铛漓,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容