我試圖解決以下問題:在谷歌應用程序引擎上使用任務隊列時,如何優先處理任務?
- 我有一系列的「任務」,我想執行
- 我有一個固定數量的工人來執行這些工人(因爲他們叫使用urlfetch的外部API和並行調用這個API的數量是有限的)
- 我想爲這些「任務」儘快執行(即最小延遲)
- 這些任務是部分可以根據原始任務的大小進行分類(即一個小的原始任務可能產生1到100個任務s,100到1000的中等和1000以上的大)。
棘手的部分:我想盡可能有效地做到這一點(即最小延遲和儘可能多的並行API調用 - 沒有超過限制),但同時嘗試防止大從「大型」原始任務生成的任務數量,以延遲從「小型」原始任務生成的任務。換句話說:我希望爲具有較高優先級的「小」任務的每個任務分配一個「優先級」,從而防止從「大」任務中匱乏。
一些摸索似乎並沒有表明任何預先製作是可用的,所以我想出了以下內容:
- 創建三個推送隊列:
tasks-small
,tasks-medium
,tasks-large
- 集併發請求的最大數量,以使總數爲併發API調用的最大數量(例如,如果最大併發API調用數量爲200,則可以設置
tasks-small
以使max_concurrent_requests
爲30,tasks-medium
60和tasks-large
100) - 排隊任務時,請檢查編號。 (使用類似QueueStatistics類的待處理任務),並且如果其他隊列未被100%利用,則將任務排隊到那裏,否則只需將隊列排入具有相應大小的隊列中。
例如,如果我們有任務T1
這是一個小任務的一部分,首先檢查tasks-small
有免費的「槽」和排隊在那裏。否則檢查tasks-medium
和tasks-large
。如果它們都沒有空閒插槽,則無論如何都將其排入tasks-small
,並在處理它之前添加任務之後處理它(注意:這不是最佳的,因爲如果其他隊列上的「插槽」釋放,它們仍然不會tasks-small
隊列中的進程掛起任務)
另一種選擇是使用PULL隊列,並根據優先級從該隊列中拉出一箇中心「協調器」並分配它們,但似乎會增加一點延遲。
但是,這似乎有點hackish,我想知道是否有更好的選擇。
編輯:之後的一些想法和反饋我想通過以下方式使用拉入隊列畢竟:
- 有兩個拉入隊列(
medium-tasks
和large-tasks
) - 有一個調度員(PUSH)隊列併發性爲1(因此只有一個調度任務在任何時候運行)。調度任務以多種方式發佈:
- 通過一次一分鐘的cron作業
- 工人的任務後增加一箇中型/大型任務推送隊列
- 後完成
- 有職工(PUSH)隊列併發等於工人
的數量和工作流程:
- 小任務直接添加到工作隊列
- 調度任務,無論何時被觸發,執行以下操作:
- 估計自由工人的數量(通過查看正在運行的任務數工作者隊列)
- 對於任何「空閒」時隙,它從中等/大型任務PULL隊列中抽取一個任務並將其排入工作者(或更準確地說:將其添加到工作者PUSH隊列中,這將導致它被執行 - 最終 - 在工人身上)。
一旦這樣實施,至少是適度測試我馬上彙報。