Celery從入門(mén)到放棄

1.定義:

? ? Celery是一個(gè)異步的任務(wù)隊(duì)列(也叫做分布式任務(wù)隊(duì)列)


2.工作結(jié)構(gòu)

? ? Celery分為3個(gè)部分

? ? (1)worker部分負(fù)責(zé)任務(wù)的處理,即工作進(jìn)程(我的理解工作進(jìn)程就是你寫(xiě)的python代碼,當(dāng)然還包括python調(diào)用系統(tǒng)工具功能)

? ? (2)broker部分負(fù)責(zé)任務(wù)消息的分發(fā)以及任務(wù)結(jié)果的存儲(chǔ),這部分任務(wù)主要由中間數(shù)據(jù)存儲(chǔ)系統(tǒng)完成,比如消息隊(duì)列服務(wù)器RabbitMQ、redis、

Amazon SQS、MongoDB、IronMQ等或者關(guān)系型數(shù)據(jù)庫(kù),使用關(guān)系型數(shù)據(jù)庫(kù)依賴(lài)sqlalchemy或者django的ORM

? ? (3)Celery主類(lèi),進(jìn)行任務(wù)最開(kāi)始的指派與執(zhí)行控制,他可以是單獨(dú)的python腳本,也可以和其他程序結(jié)合,應(yīng)用到django或者flask等web框架里面以及你能想到的任何應(yīng)用


3.話(huà)不多說(shuō),用起來(lái)

? ? (1)安裝Celery(要安裝celery3版本,4版本改動(dòng)較大沒(méi)測(cè)試)

#pip install celery==3.1.17

? ? (2)broker部分此處使用安裝好的redis服務(wù)6380端口的db0作為消息隊(duì)列,普通redis服務(wù)的安裝此處不做介紹

? (3)Celery的使用一(單獨(dú)腳本調(diào)用,簡(jiǎn)單方便)

? ? ? ? #注:不考慮任務(wù)的結(jié)果存儲(chǔ)情況

? ? ? ? ?<1>/tmp/tasks.py(實(shí)際腳本中不要寫(xiě)中文注釋?zhuān)?/p>

#!/usr/bin/env python

# -*- coding=utf-8 -*-

from celery import Celery

from celery import platforms

#用于開(kāi)啟root也可以啟動(dòng)celery服務(wù),默認(rèn)是不允許root啟動(dòng)celery的

platforms.C_FORCE_ROOT = True

#創(chuàng)建一個(gè)celery實(shí)例,傳遞進(jìn)去的第一個(gè)參數(shù)tasks必須是本文件的文件名tasks,指定broker為本機(jī)redis6380服務(wù)

celery = Celery('tasks', broker='redis://localhost:6380/0')

#使用celery實(shí)例的task裝飾器裝飾add函數(shù),此處的add函數(shù)可以當(dāng)作后期的耗時(shí)任務(wù)對(duì)待

@celery.task

def add(x,y):

? ? return x + y

? ? ? ?<2>啟動(dòng)celery服務(wù)

#cd /tmp

#celery -A tasks worker --loglevel=info

? ? ? ?<3>驗(yàn)證執(zhí)行任務(wù)

? ? ? ?#導(dǎo)入模塊,執(zhí)行add函數(shù),此處使用add.delay(3,4)而不是add(3,4),因?yàn)楸籧elery封裝了,要異步執(zhí)行需要額外使用add.delay(3,4)

? ?? ? #需要注意,如果把返回值賦值給一個(gè)變量,那么原來(lái)的應(yīng)用程序也會(huì)被阻塞,需要等待異步任務(wù)返回的結(jié)果。因此,實(shí)際使用中,不需要把結(jié)果賦值。

#cd /tmp

#python

>>>from tasks import add

>>>add.delay(3,4)

? ? ? ?#celery服務(wù)的窗口會(huì)刷出任務(wù)的信息,以及是否處理成功,以及結(jié)果

? ? ? ?#將來(lái)只要在別的程序中引入tasks中的add函數(shù),就是異步的了,是不是有點(diǎn)屌。。。。。

? ? ? ?<4>擴(kuò)展知識(shí),指定隊(duì)列名

? ? ? ?傳入redis中的指定隊(duì)列testq怎么玩?(其他broker引擎也支持)

? ? ? ?啟動(dòng)celery服務(wù)的時(shí)候添加額外參數(shù)-Q '隊(duì)列名'

#cd /tmp

#celery -A tasks.tasks worker --loglevel=info -Q 'testq'

? ? ? ?跑任務(wù)的時(shí)候指定testq隊(duì)列名

#cd /tmp

#python

>>>from tasks import add

>>>add.delay(3,4,queue='testq')

? ? ? ?<5>擴(kuò)展知識(shí),指定開(kāi)啟的worker進(jìn)程數(shù)(底層是調(diào)用的Python的multiprocessing模塊中的Pool進(jìn)程池思想來(lái)做)

? ? ? ?-c 5 開(kāi)啟5個(gè)worker進(jìn)程來(lái)同時(shí)搶任務(wù),跑任務(wù)

#cd /tmp

#celery -A tasks.tasks worker --loglevel=info -c 5

? ? ? ?<6>擴(kuò)展知識(shí),管理broker里面的數(shù)據(jù),查看任務(wù)狀態(tài),以及任務(wù)的詳細(xì)信息

? ? ? ?安裝一個(gè)叫flower的webui,提供任務(wù)查詢(xún),worker生命管理,以及路由管理等(底層是通過(guò)tornado框架封裝的)

#pip install flower

#任意目錄下執(zhí)行都可以

#celery flower --port=5555 --broker=redis://localhost:6380/0

? ? ? ?#里面可以看到任務(wù)參數(shù),結(jié)果,接受任務(wù)時(shí)間,任務(wù)開(kāi)始時(shí)間,任務(wù)狀態(tài),Started是任務(wù)進(jìn)行中,Success是任務(wù)跑完執(zhí)行成功

? ? (4)Celery的使用二(項(xiàng)目方式,也叫做Python包方式,結(jié)構(gòu)清晰,低耦合;相比純腳本方式略復(fù)雜,用不用由你)

? ? 創(chuàng)建一個(gè)叫做proj的Python包(創(chuàng)建Python包的操作此處不做詳細(xì)說(shuō)明,tree /tmp/proj)


? ? ? ?<1>proj/celery.py

? ? ? #from __future__ import absolute_import據(jù)說(shuō)添加此行可以低降低出錯(cuò)的概率哦(阿門(mén)保佑;其實(shí)就是兼容Python版本的一個(gè)東東)

? ? ? #創(chuàng)建一個(gè)celery的實(shí)例,名字叫做app,傳遞進(jìn)去的第一個(gè)參數(shù)是Python包的名字,include加載任務(wù)文件,config_from_object指定celery的配置文件(好吧,看起來(lái)比單純使用腳本方式麻煩點(diǎn),請(qǐng)繼續(xù)往下看)

#!/usr/bin/env python

# -*- coding=utf-8 -*-

from __future__ import absolute_import

from celery import Celery

app = Celery('proj', include=['proj.tasks'])

app.config_from_object('proj.config')

if __name__ == '__main__':

? ? app.start()

? ? ? ?<2>proj/config.py

? ? ? ?#配置文件里指定broker

#!/usr/bin/env python

# -*- coding:utf-8 -*-

from __future__ import absolute_import

BROKER_URL = 'redis://127.0.0.1:6380/0'

? ? ? ?<3>proj/tasks.py

? ? ? ?#導(dǎo)入celery實(shí)例,實(shí)例綁定任務(wù)

#!/usr/bin/env python

# -*- coding:utf-8 -*-

from __future__ import absolute_import

from proj.celery import app

@app.task

def add(x, y):

? ? return x + y

? ? ? ?<4>開(kāi)啟celery服務(wù)(特定目錄指定包名字啟動(dòng))

#cd /tmp/

#celery -A proj worker -l info

? ? ? ?<5>擴(kuò)展功能,指定隊(duì)列名,調(diào)整worker進(jìn)程數(shù),頁(yè)面管理celery同上,不再做說(shuō)明

?(5)Celery的使用三(django-celery模式;#反正我喜歡用這種

? ? ? ?django調(diào)用celery跑異步任務(wù),常見(jiàn)場(chǎng)景有注冊(cè)成功,發(fā)送郵件可以異步來(lái)防止網(wǎng)絡(luò)IO阻塞,以及耗時(shí)間的任務(wù),例如需要去跑9000臺(tái)IP的某些配置參數(shù)任務(wù),或者下發(fā)任務(wù)執(zhí)行,可能需要10幾分鐘才能跑完,就可以WEB應(yīng)用中使用這種異步方式

? ? ? ?<1>安裝django-celery軟件包

? ? ? ?#一定要注意celery的版本和django-celery的小版本要保持一致,否則會(huì)有各種雜七雜八的小問(wèn)題(都是淚.......)

#pip install celery==3.1.17

#pip install django-celery==3.1.17

? ? ? ?<2>創(chuàng)建celery必須的數(shù)據(jù)庫(kù)表結(jié)構(gòu)

#cd Python_20161203

#python manage.py migrate

? ? ? ?<3>django項(xiàng)目的settings.py文件中追加如下內(nèi)容;app呢是django項(xiàng)目里面的應(yīng)用名字

? ? ? ?settings.py

import djcelery

djcelery.setup_loader()

BROKER_URL = 'redis://127.0.0.1:6380/0'

CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6380/1'

CELERY_TASK_SERIALIZER = 'json'

CELERY_RESULT_SERIALIZER = 'json'

CELERY_ACCEPT_CONTENT = ['json']

CELERY_IMPORTS = ('app.tasks', )

CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'

CELERYD_CONCURRENCY = 20

參數(shù)說(shuō)明(可以根據(jù)自己的需求添加自己的參數(shù)):

CELERY_RESULT_BACKEND = "redis://127.0.0.1:6380/1'" #結(jié)果存儲(chǔ)

CELERY_TASK_RESULT_EXPIRES = 1200 # celery任務(wù)執(zhí)行結(jié)果的超時(shí)時(shí)間,我的任務(wù)都不需要返回結(jié)果,只需要正確執(zhí)行就行

CELERYD_CONCURRENCY = 20 # celery worker的并發(fā)數(shù) 也是命令行-c指定的數(shù)目,事實(shí)上實(shí)踐發(fā)現(xiàn)并不是worker也多越好,保證任務(wù)不堆積,加上一定新增任務(wù)的預(yù)留就可以

CELERYD_PREFETCH_MULTIPLIER = 4 # celery worker 每次去redis取任務(wù)的數(shù)量,我這里預(yù)取了4個(gè)慢慢執(zhí)行,因?yàn)槿蝿?wù)有長(zhǎng)有短沒(méi)有預(yù)取太多

CELERYD_MAX_TASKS_PER_CHILD = 200 # 每個(gè)worker執(zhí)行了多少任務(wù)就會(huì)死掉,我建議數(shù)量可以大一些,比如200

CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' # 這是使用了django-celery默認(rèn)的數(shù)據(jù)庫(kù)調(diào)度模型,任務(wù)執(zhí)行周期都被存在你指定的orm數(shù)據(jù)庫(kù)中


? ? ? ?<4>app/tasks.py(在django的app應(yīng)用目錄下創(chuàng)建tasks.py任務(wù)文件,里面調(diào)用復(fù)雜的任務(wù)函數(shù))

#!/usr/bin/env python

# -*- coding=utf-8 -*-

###############################

from __future__ import absolute_import

from celery import task

import time

#task裝飾器封裝了celery函數(shù),為耗時(shí)的操作

@task

def add(x,y):

? ? for i in range(30):

? ? ? ?print i

? ? ? ?time.sleep(1)

? ? return x + y

? ? ? ?<5>添加驗(yàn)證功能,查看實(shí)際效果

? ? ? ?app/urls.py

urlpatterns = [

url(r'^celery_test/,views.celery_test),

]

? ? ? ?app/views.py

def celery_test(request):

? ? from tasks import add

? ? add.delay(4,8)

? ? return HttpResponse('Celery testing666')

? ? ? ?<6>開(kāi)啟djanog服務(wù)和celery服務(wù)(雖然耦合了,但是還是需要額外開(kāi)啟)

#python manage.py runserver 0.0.0.0:8000

#另一個(gè)窗口開(kāi)啟celery服務(wù)

#python manage.py celery worker --loglevel=info


? ? ? ?<7>發(fā)送http的GET請(qǐng)求,調(diào)用celery去執(zhí)行異步任務(wù)(大功告成)

curl http://127.0.0.1:8000/index/celery_test/

? ? ? ? celery那端的屏幕輸出如下:

[2016-12-01 16:16:00,940: INFO/MainProcess] Received task: app.tasks.add[06a8d603-a7d3-4732-b8f3-ad010d531200]

[2016-12-01 16:16:00,941: WARNING/Worker-1] 0

[2016-12-01 16:16:01,943: WARNING/Worker-1] 1

[2016-12-01 16:16:02,945: WARNING/Worker-1] 2

[2016-12-01 16:16:03,947: WARNING/Worker-1] 3

[2016-12-01 16:16:04,948: WARNING/Worker-1] 4

[2016-12-01 16:16:05,950: WARNING/Worker-1] 5

[2016-12-01 16:16:06,952: WARNING/Worker-1] 6

[2016-12-01 16:16:07,954: WARNING/Worker-1] 7

[2016-12-01 16:16:08,955: WARNING/Worker-1] 8

[2016-12-01 16:16:09,957: WARNING/Worker-1] 9

[2016-12-01 16:16:10,958: WARNING/Worker-1] 10

[2016-12-01 16:16:11,959: WARNING/Worker-1] 11

[2016-12-01 16:16:12,961: WARNING/Worker-1] 12

[2016-12-01 16:16:13,962: WARNING/Worker-1] 13

[2016-12-01 16:16:14,964: WARNING/Worker-1] 14

[2016-12-01 16:16:15,964: WARNING/Worker-1] 15

[2016-12-01 16:16:16,966: WARNING/Worker-1] 16

[2016-12-01 16:16:17,968: WARNING/Worker-1] 17

[2016-12-01 16:16:18,969: WARNING/Worker-1] 18

[2016-12-01 16:16:19,971: WARNING/Worker-1] 19

[2016-12-01 16:16:20,973: WARNING/Worker-1] 20

[2016-12-01 16:16:21,974: WARNING/Worker-1] 21

[2016-12-01 16:16:22,976: WARNING/Worker-1] 22

[2016-12-01 16:16:23,978: WARNING/Worker-1] 23

[2016-12-01 16:16:24,979: WARNING/Worker-1] 24

[2016-12-01 16:16:25,981: WARNING/Worker-1] 25

[2016-12-01 16:16:26,982: WARNING/Worker-1] 26

[2016-12-01 16:16:27,984: WARNING/Worker-1] 27

[2016-12-01 16:16:28,986: WARNING/Worker-1] 28

[2016-12-01 16:16:29,987: WARNING/Worker-1] 29

[2016-12-01 16:16:30,990: INFO/MainProcess] Task app.tasks.add[06a8d603-a7d3-4732-b8f3-ad010d531200] succeeded in 30.049149203s: 12

? ? (6)Celery的使用四(celery模式;#反正我不喜歡用,那索性不寫(xiě)了,想學(xué)習(xí)的點(diǎn)擊下面的鏈接去自助學(xué)習(xí)吧,加油少年

不安裝django-celery版本使用方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,415評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,104評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,884評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,647評(píng)論 6 408
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,130評(píng)論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,366評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,887評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,737評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,939評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,174評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,586評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,827評(píng)論 1 283
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,608評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,914評(píng)論 2 372

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