什麼是任務依賴,舉個栗子,互聯網公司常常在凌晨進行一些數據統計任務,這些任務之間有必定的依賴關係,好比:微信
1)task3須要使用task2的輸出做爲輸入架構
2)task2須要使用task1的輸出做爲輸入微信支付
這樣的話,tast1, task2, task3之間就有任務依賴關係,必須task1先執行,再task2執行,載task3執行。優化
對於這類需求,常見的實現方式是,使用cron人工排執行時間表:spa
1)task1,0:00執行,經驗執行時間爲50分鐘架構設計
2)task2,1:00執行(爲task1預留10分鐘buffer),經驗執行時間也是50分鐘設計
3)task3,2:00執行(爲task2預留10分鐘buffer)接口
這種方法的壞處是:事件
1)若是有一個任務執行時間超過了預留buffer的時間,將會獲得錯誤的結果,由於後置任務不清楚前置任務是否執行成功,此時要手動重跑任務,還有可能要調整排班表ip
2)總任務的執行時間很長,老是要預留不少buffer,若是前置任務提早完成,後置任務不會提早開始
3)若是一個任務被多個任務依賴,這個任務將會稱爲關鍵路徑,排班表很難體現依賴關係,容易出錯
4)若是有一個任務的執行時間要調整,將會有多個任務的執行時間要調整
不管如何,採用「cron排班表」的方法,各任務耦合,誰用過誰痛誰知道(採用此法的請評論留言)
優化方案是,採用MQ解耦:
1)task1準時開始,結束後發一個「task1 done」的消息
2)task2訂閱「task1 done」的消息,收到消息後第一時間啓動執行,結束後發一個「task2 done」的消息
3)task3同理
採用MQ的優勢是:
1)不須要預留buffer,上游任務執行完,下游任務總會在第一時間被執行
2)依賴多個任務,被多個任務依賴都很好處理,只須要訂閱相關消息便可
3)有任務執行時間變化,下游任務都不須要調整執行時間
須要特別說明的是,MQ只用來傳遞上游任務執行完成的消息,並不用於傳遞真正的輸入輸出數據。
上游須要關注執行結果時要用「調用」,上游不關注執行結果時,就可使用MQ了。
舉個栗子,58同城的不少下游須要關注「用戶發佈帖子」這個事件,好比招聘用戶發佈帖子後,招聘業務要獎勵58豆,房產用戶發佈帖子後,房產業務要送2個置頂,二手用戶發佈帖子後,二手業務要修改用戶統計數據。
對於這類需求,常見的實現方式是,使用調用關係:
帖子發佈服務執行完成以後,調用下游招聘業務、房產業務、二手業務,來完成消息的通知,但事實上,這個通知是否正常正確的執行,帖子發佈服務根本不關注。
這種方法的壞處是:
1)帖子發佈流程的執行時間增長了
2)下游服務當機,可能致使帖子發佈服務受影響,上下游邏輯+物理依賴嚴重
3)每當增長一個須要知道「帖子發佈成功」信息的下游,修改代碼的是帖子發佈服務,這一點是最噁心的,屬於架構設計中典型的依賴倒轉
優化方案是,採用MQ解耦:
1)帖子發佈成功後,向MQ發一個消息
2)哪一個下游關注「帖子發佈成功」的消息,主動去MQ訂閱
採用MQ的優勢是:
1)上游執行時間短
2)上下游邏輯+物理解耦,除了與MQ有物理鏈接,模塊之間都不相互依賴
3)新增一個下游消息關注方,上游不須要修改任何代碼
有時候上游須要關注執行結果,但執行結果時間很長(典型的是調用離線處理,或者跨公網調用),也常常使用回調網關+MQ來解耦。
舉個栗子,微信支付,跨公網調用微信的接口,執行時間會比較長,但調用方又很是關注執行結果,此時通常怎麼玩呢?
通常採用「回調網關+MQ」方案來解耦:
1)調用方直接跨公網調用微信接口
2)微信返回調用成功,此時並不表明返回成功
3)微信執行完成後,回調統一網關
4)網關將返回結果通知MQ
5)請求方收到結果通知
這裏須要注意的是,不該該由回調網關來調用上游來通知結果,若是是這樣的話,每次新增調用方,回調網關都須要修改代碼,仍然會反向依賴,使用回調網關+MQ的方案,新增任何對微信支付的調用,都不須要修改代碼啦。