乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      使用Cerely調(diào)度任務(wù)

       River_LaLaLa 2016-08-21


      開(kāi)始使用Celery調(diào)度任務(wù)

      如果引入調(diào)度,周期性執(zhí)行或者不阻塞請(qǐng)求線程,很多Django應(yīng)用可以得到更好的使用。

      在Django應(yīng)用里,有很多方式可以用來(lái)調(diào)度任務(wù),但是使用Celery有許多優(yōu)勢(shì)。它有很好的支持,伸縮性好,并且能和Django一起工作。它應(yīng)用廣泛,有很多資源可以幫助學(xué)習(xí)和使用它。一旦學(xué)會(huì)了,對(duì)其他項(xiàng)目也有好處。

      Celery 3.0.x

      本文檔適用于Celery 3.0.x。之前或之后的版本可能有差別。

      Celery簡(jiǎn)介

      Celery被用來(lái)稍后執(zhí)行某些代碼,或用調(diào)度器調(diào)度這些代碼

      這有什么用呢?下面有一些例子。

      第一個(gè)例子,假設(shè)用戶發(fā)來(lái)一個(gè)頁(yè)面請(qǐng)求,然后等待請(qǐng)求完成,瀏覽器加載新頁(yè)面。對(duì)于他們的請(qǐng)求,你需要運(yùn)行一些代碼,而這些代碼的運(yùn)行時(shí)間可能比用戶想要等待網(wǎng)頁(yè)的時(shí)間要長(zhǎng),但是你并不真得需要在響應(yīng)頁(yè)面請(qǐng)求前執(zhí)行那些代碼。這時(shí),你如果使用Celery稍后執(zhí)行這些耗時(shí)的代碼,就立即響應(yīng)頁(yè)面請(qǐng)求。

      當(dāng)你需要連接遠(yuǎn)程服務(wù)器來(lái)處理請(qǐng)求時(shí)會(huì)經(jīng)常遇到這種情況。你的應(yīng)用不能控制遠(yuǎn)程服務(wù)器響應(yīng)的時(shí)間,甚至遠(yuǎn)程服務(wù)器可能是關(guān)閉的。

      另一種常見(jiàn)情形是需要周期性執(zhí)行某些代碼。比如,你可能每小時(shí)查詢最新的天氣預(yù)報(bào)并且儲(chǔ)存數(shù)據(jù)。你可以寫(xiě)個(gè)任務(wù)來(lái)執(zhí)行這項(xiàng)工作,然后設(shè)置Celery每個(gè)小時(shí)執(zhí)行一次。這個(gè)任務(wù)運(yùn)行并把數(shù)據(jù)存入數(shù)據(jù)庫(kù),然后Web應(yīng)用就可以獲得最新的天氣預(yù)報(bào)。

      一個(gè)任務(wù)(task)只是一個(gè)Python函數(shù)。你可以把調(diào)度一個(gè)任務(wù)理解為延時(shí)調(diào)用哪個(gè)函數(shù)。比如,你可以需要 Celery 5分鐘后使用參數(shù)(1, 3, 3)調(diào)用你的函數(shù)task1,或者你可以使函數(shù)batchjob每晚0時(shí)執(zhí)行。

      我們將會(huì)設(shè)置Celery來(lái)使你的任務(wù)在和其余應(yīng)用代碼盡可能相似的環(huán)境中執(zhí)行,以使它們使用同樣的數(shù)據(jù)庫(kù)和Django設(shè)置。有一些差異需要記住,稍后將會(huì)講到。

      當(dāng)一個(gè)任務(wù)準(zhǔn)備執(zhí)行時(shí),Celery將它放到一個(gè)隊(duì)列上,這個(gè)隊(duì)列上有其它的將要執(zhí)行的任務(wù)。你可以有很多隊(duì)列,但是這里為了簡(jiǎn)單我們假設(shè)只有一個(gè)隊(duì)列。

      可以這樣說(shuō),將一個(gè)任務(wù)添加到隊(duì)列上僅僅只是把它加入到一個(gè)待辦列表。為了執(zhí)行任務(wù),一些其它的程序--任務(wù)執(zhí)行單元(worker)--將監(jiān)視隊(duì)列上是否有任務(wù)。當(dāng)它發(fā)現(xiàn)隊(duì)列上有任務(wù)時(shí),它會(huì)取出并執(zhí)行第一個(gè)任務(wù),然后接著監(jiān)視隊(duì)列等待其它任務(wù)。你可以有很多任務(wù)執(zhí)行單元,可能在許多不同的服務(wù)器上,但是我們今天假設(shè)只有一個(gè)任務(wù)執(zhí)行單元。

      稍后我們會(huì)講更多關(guān)于隊(duì)列,任務(wù)執(zhí)行單元和其他尚未提及的重要的程序,上面這些現(xiàn)在已經(jīng)夠用了,讓我們做一些工作。

      本地安裝Cerely

      安裝本地Django使用的Celery很簡(jiǎn)單--只需安裝django-celery


      為Celery配置Django

      首先,我們配置Celery在runserver上使用。對(duì)于Celery中間件(broker,稍后介紹),將使用Django database broker implementation?,F(xiàn)在,你只需知道Celery需要一個(gè)中間件,在開(kāi)發(fā)過(guò)程中可以使用Django自帶的(但是在生產(chǎn)環(huán)境中你必須使用一些更健壯的性能更好的)

      在Django settings.py文件中:

      1.添加這些代碼:


      前兩行是必需的,第三行設(shè)置Celery使用Django中間件。

      注意:絕對(duì)不要在生產(chǎn)環(huán)境中使用Django中間件。在本教程中我們使用它只是為了節(jié)省時(shí)間。在生產(chǎn)環(huán)境中,你可以使用RabbitMQ或者Redis。

      2.在INSTALLED_APPS中添加djcelery和kombu.transport.django:


      djcelery是必需的。kombu.transport.django是基于Django的中間件,主要用在開(kāi)發(fā)環(huán)境中。

      3.創(chuàng)建Celery數(shù)據(jù)庫(kù),如果使用South作模式遷移:


      否則:


      編寫(xiě)一個(gè)任務(wù)

      如前所述,一個(gè)任務(wù)可以僅僅只是一個(gè)Python函數(shù)。但是,Celery必須了解它。當(dāng)Celery和Django一起工作時(shí),這很容易。只需要在你的應(yīng)用中添加一個(gè)tasks.py文件,把你的任務(wù)放在那個(gè)文件中,并且裝飾它們。這里有一個(gè)簡(jiǎn)單的tasks.py:


      當(dāng)djcelery.setup_loader()從你的配置文件啟動(dòng)的時(shí)候,Celery將會(huì)檢查INSTALLED_APPS查找tasks.py模塊,找到那些被標(biāo)記為任務(wù)的函數(shù),并將它們注冊(cè)為任務(wù)。

      將一個(gè)函數(shù)標(biāo)記為任務(wù)并不影響它正常工作。你仍可以如此調(diào)用它:z = add(1, 2)并且它會(huì)和以前一樣工作。將它標(biāo)記為任務(wù)可以讓你用其它方式調(diào)用。

      調(diào)度任務(wù)

      接著上面的簡(jiǎn)單例子。我們想立即運(yùn)行任務(wù),并且不想它阻塞當(dāng)前線程。只需通過(guò)在任務(wù)的名字后面添加 .delay 即可實(shí)現(xiàn):


      Celery將會(huì)把任務(wù)添加到它的隊(duì)列 (“worker, please call myapp.tasks.add(2, 2)) 然后理解返回。只要一個(gè)空閑的任務(wù)執(zhí)行單元在隊(duì)列的首部看到它,任務(wù)執(zhí)行單元就會(huì)把它從隊(duì)列上移除,然后執(zhí)行它:


      一個(gè)關(guān)于導(dǎo)入名稱(chēng)的警告

      這很重要,你的任務(wù)總是導(dǎo)入并且引用相同的包名稱(chēng)。比如,依賴(lài)于你的Python路徑如何設(shè)置,可能這樣指向它myproject.myapp.tasks.add或者myapp.tasks.add?;蛘邚膍yapp.views,你可能這樣導(dǎo)入它 .tasks.add。但是Celery無(wú)法知道這些都是同一個(gè)任務(wù)。

      djcelery.setup_loader()將會(huì)使用你的應(yīng)用在INSTALLED_APPS里的包名,加上 .tasks.functionname。確保當(dāng)你調(diào)度你的任務(wù),你也使用同樣的名字導(dǎo)入它,否則可能會(huì)出現(xiàn)bugs。

      測(cè)試

      啟動(dòng)一個(gè)任務(wù)執(zhí)行單元

      正如我們提過(guò)的,一個(gè)單獨(dú)的程序,任務(wù)執(zhí)行單元,用來(lái)執(zhí)行你的Celery任務(wù)。下面是我們?nèi)绾螁?dòng)一個(gè)任務(wù)執(zhí)行單元滿足開(kāi)發(fā)需要。

      首先,打開(kāi)一個(gè)新終端或者新窗口。在終端里,設(shè)置相同的Django開(kāi)發(fā)環(huán)境--啟動(dòng)你的虛擬環(huán)境或者把它們添加到你的Python路徑里,這兩種方法都可以使你使用runserver運(yùn)行你的項(xiàng)目。

      現(xiàn)在,你可以在那個(gè)終端里這樣啟動(dòng)一個(gè)任務(wù)執(zhí)行單元:


      任務(wù)執(zhí)行單元將會(huì)在那個(gè)窗口里運(yùn)行,并且在那里顯示輸出。

      運(yùn)行任務(wù)

      回到你的第一個(gè)窗口,啟動(dòng)一個(gè)Django終端,運(yùn)行你的任務(wù):


      如果你在任務(wù)執(zhí)行單元的窗口里看到這些輸出,那么任務(wù)執(zhí)行單元已經(jīng)執(zhí)行完那個(gè)任務(wù)。


      一個(gè)例子

      前面我們提到過(guò)使用Celery來(lái)避免對(duì)一個(gè)頁(yè)面請(qǐng)求的響應(yīng)延遲。下面是一個(gè)使用這種技術(shù)的簡(jiǎn)單的Django事例。


      問(wèn)題處理

      嘗試使Celery任務(wù)工作可能會(huì)很困難,因?yàn)闀?huì)使用很多部分,并且這些部分之間還會(huì)相互聯(lián)系。許多常見(jiàn)的小技巧仍然起作用:

      •   先使最簡(jiǎn)單的配置能夠工作

      •   使用Python調(diào)試器以及輸出語(yǔ)句來(lái)觀察發(fā)生了什么

      •   提升日志級(jí)別(比如,將任務(wù)執(zhí)行單元設(shè)置為—loglevel debug)來(lái)獲得更多的信息

      也有一些Celery專(zhuān)用工具。

      Eager scheduling

      在你的Django設(shè)置里,可以添加:


      然后,Celery就會(huì)忽略全部調(diào)度機(jī)制,立即調(diào)用你的代碼。

      這就是說(shuō),設(shè)置了CELERY_ALWAYS_EAGER = True后,這兩個(gè)語(yǔ)句變得一樣:


      你可以使用這種方法使你的核心內(nèi)容在引入Celery調(diào)度問(wèn)題之前開(kāi)始工作。

      查看隊(duì)列

      只要你在開(kāi)發(fā)時(shí)使用Django自帶的中間件,你的隊(duì)列就存儲(chǔ)在Django數(shù)據(jù)庫(kù)里。這樣你就可以很容易的查看它。在你的應(yīng)用里向admin.py添加幾行:


      現(xiàn)在,你可以在/admin/django/message文件夾下查看隊(duì)列上是否有任務(wù)。每一個(gè)信息(message)就是一個(gè)來(lái)自Celery的請(qǐng)求--讓任務(wù)執(zhí)行單元執(zhí)行任務(wù)。信息的內(nèi)容很難理解,但是有時(shí)候僅僅只知道你的任務(wù)是否在隊(duì)列里就很有用了。信息會(huì)留在數(shù)據(jù)庫(kù)里,所以看到很多信息并不意味著你的任務(wù)只在被執(zhí)行。

      檢查結(jié)果

      任何時(shí)候調(diào)度一個(gè)任務(wù),Celery都會(huì)返回一個(gè)AsyncResult對(duì)象。你可以保存那個(gè)任務(wù),然后稍后使用它檢查任務(wù)是否執(zhí)行完成,是否成功,以及結(jié)果。


      周期性調(diào)度

      另一個(gè)常見(jiàn)例子是周期性調(diào)度任務(wù)。Celery使用另一個(gè)程序celerybeat來(lái)實(shí)現(xiàn)。Celerybeat一直運(yùn)行,等一個(gè)調(diào)度任務(wù)到執(zhí)行時(shí)間了,celerybeat就會(huì)把它加入隊(duì)列去執(zhí)行。

      顯而易見(jiàn),只有一個(gè)celerybeat程序可以運(yùn)行(不像任務(wù)執(zhí)行單元,只要你需要,你就可以運(yùn)行任意個(gè))

      啟動(dòng)celerybeat和啟動(dòng)一個(gè)任務(wù)執(zhí)行單元相似。打開(kāi)另一個(gè)窗口,設(shè)置Django環(huán)境,然后:


      有幾種方法告訴celery在調(diào)度上運(yùn)行一個(gè)任務(wù)。我們將使用在Django數(shù)據(jù)庫(kù)表里存儲(chǔ)計(jì)劃任務(wù)這種方法。這使你很容易地修改計(jì)劃任務(wù),即使Django和Celery正在運(yùn)行。

      添加這條配置信息:


      現(xiàn)在,你可以打開(kāi)Django admin文件夾,前往/admin/djcelery/periodictask/文件夾添加計(jì)劃任務(wù)。下面是一些字段的說(shuō)明:

      •   Name—用來(lái)標(biāo)記預(yù)訂的任務(wù)

      •   Task(registered)-只要你在添加任務(wù)后啟動(dòng)Django至少一次,這里應(yīng)該是任何一個(gè)你定義過(guò)的任務(wù)。如果你沒(méi)有看到你想要的任務(wù),最好檢查原因,修復(fù)它,然后再使用寫(xiě)一個(gè)字段。

      •   Task(custom)-這里你可以鍵入任務(wù)的全稱(chēng)(例如,myapp.tasks.add),但是最好使用上面registered tasks字段

      •   Enabled-由于某些原因,比如暫停它,你不想要任務(wù)真得運(yùn)行,你可以不選擇它

      •   Interval-如果你想要任務(wù)間隔一段時(shí)間重復(fù)運(yùn)行。你可能需要使用綠色的“+”定義一個(gè)新的計(jì)劃任務(wù)。這很簡(jiǎn)單,例如,每5分鐘運(yùn)行,5設(shè)置為“Every”,“Period”設(shè)置為minutes。

      •   Crontab-如果任務(wù)要在指定時(shí)間運(yùn)行,使用crontab替代Interval。使用綠色的“+”,填寫(xiě)minute, hour, day of week, day of month, and day of year。你可以使用“*”在任何字段替代一個(gè)具體值,但是注意-如果你使用“*”在minute字段,你的任務(wù)將會(huì)在選定的那個(gè)小時(shí)內(nèi)的每個(gè)分鐘里都執(zhí)行。例如:每天早上7:30執(zhí)行,設(shè)置minute為“30”,hour為“7”,其余字段為“*”。

      •   Arguments-如果需要為任務(wù)傳入?yún)?shù),你可以展開(kāi)這部分,設(shè)置*args和**kwargs字段。

      •  Execution Oprions-高級(jí)設(shè)置,這里我們不會(huì)討論。

      默認(rèn)計(jì)劃任務(wù)

      如果你想你的一些任務(wù)默認(rèn)計(jì)劃任務(wù),不依賴(lài)于某人在安裝完你的應(yīng)用后在數(shù)據(jù)庫(kù)里配置它們,你可以使用Django fixtures把你的計(jì)劃任務(wù)作為應(yīng)用的初始數(shù)據(jù)。

      • 在你的數(shù)據(jù)庫(kù)里配置你想要的計(jì)劃任務(wù)

      • 用json格式保存計(jì)劃任務(wù)


           

      • 在你的應(yīng)用里創(chuàng)建一個(gè)fixtures文件夾

      • 如果你再也不想編輯這些計(jì)劃任務(wù),你可以把你的json文件復(fù)制到fixtures文件夾中命名為initial_data.json。每次syncdb運(yùn)行時(shí),Django都會(huì)加載它,如果你在數(shù)據(jù)庫(kù)里編輯了計(jì)劃任務(wù),你就會(huì)得到錯(cuò)誤,或者失去更改。(你仍然可以添加新的計(jì)劃任務(wù),你只是不能更改從fixtures文件夾初始數(shù)據(jù)里加載的那些)

      • 如果你想把這些作為初始調(diào)度,把你的文件命名為其他的,當(dāng)配置一個(gè)使用你應(yīng)用的網(wǎng)站時(shí)加載它就可以了:


      提示和技巧

      不要把model對(duì)象傳遞給任務(wù)

      因?yàn)槿蝿?wù)不會(huì)立即運(yùn)行,當(dāng)一個(gè)任務(wù)運(yùn)行并使用傳入的model對(duì)象時(shí),數(shù)據(jù)庫(kù)的對(duì)應(yīng)紀(jì)錄可能已經(jīng)改變。如果任務(wù)此時(shí)對(duì)model對(duì)象做了一些修改并且保存起來(lái),數(shù)據(jù)庫(kù)里的這些改變就會(huì)被舊數(shù)據(jù)覆蓋了。

      更安全的做法是保存對(duì)象,傳遞紀(jì)錄的鍵名,在任務(wù)里重新獲得對(duì)象。


      在任務(wù)里調(diào)度其他任務(wù)

      執(zhí)行一個(gè)任務(wù)的時(shí)候調(diào)度另一個(gè)完全可行。這可以用于保證第二個(gè)任務(wù)在第一個(gè)任務(wù)做完一些必要的工作之前不會(huì)運(yùn)行。

      不要在一個(gè)任務(wù)里等待另一個(gè)任務(wù)

      如果一個(gè)任務(wù)等待另一個(gè)任務(wù),它的任務(wù)執(zhí)行單元將一直阻塞而不能做其他事情直到等待結(jié)束。這早晚造成死鎖。

      如果你的任務(wù)A里想要調(diào)度任務(wù)B,在任務(wù)B結(jié)束之后,做一些其他的工作,最好創(chuàng)建一個(gè)任務(wù)C做這些工作,在任務(wù)B結(jié)束時(shí)調(diào)度任務(wù)C。

      下一步

      一旦你理解了這些基礎(chǔ)部分,最好閱讀一下Celery用戶手冊(cè)中的部分內(nèi)容。我建議從這些章節(jié)開(kāi)始;其他的要不和Django沒(méi)有關(guān)系,要不太過(guò)高級(jí):

      在生產(chǎn)環(huán)境里使用Celery

      這里描述的Celery配置是為了開(kāi)發(fā)方便,絕不能應(yīng)用在生產(chǎn)環(huán)境。

      為了在生產(chǎn)環(huán)境里使用,最重要的修改是停止使用kombu.transport.djanggo作為中間件,使用RabbitMQ或者其他健壯的可伸縮的等價(jià)物替換。


      英文原文:https://www./blog/2014/06/23/scheduling-tasks-celery/
      譯者:CupKnight


        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類(lèi)似文章 更多