集成平台集群任务动态分派
源寶導讀:MIP集成平臺是為了解決企業大量異構系統之間快速、穩定集成的需要,助力企業數字化轉型,明源云自主研發的平臺系統。本文將對"事件任務分派"場景的架構設計以及實踐成果進行分享。
背景
? ? MIP集成平臺是為了解決企業大量異構系統之間快速、穩定集成的需要,助力企業數字化轉型,明源云自主研發的平臺系統。在MIP中,事件中心組件提供了低耦合、準實時、高可靠的數據或消息傳輸服務,解決企業信息系統之間的異步的通知和數據同步需求。在事件管理中,用戶可以通過創建事件源和事件訂閱者,來實現事件的訂閱與發布,最終實現數據或消息在應用之間進行傳遞。后臺系統會通過調度模塊進行事件任務的分配,然后下發到運行模塊進行事件任務的運行(監聽和訂閱),本文將對"事件任務分派"場景的架構設計以及實踐成果進行分享。基于篇幅,本次主要分享分派調度策略的處理邏輯的這個層面。
一、需求分析
? ? 基于上面的描述,我們可以認為這是一個分布式任務調度的場景,相對簡單且有其特點。
調度分配以事件為單位,調度時只需要根據分配原則把指定的事件在運行模塊節點上啟動即可。
持續運行,不需要Job形式的定時調度,為了保證準實時性,事件任務一旦啟動,將會持續運行,除非重新被分配。
一致性,為了保證消息和數據不會重復,同一時間一個事件只能在一個運行節點中執行。
故障轉移,當一個運行節點不可用時,需要把上面正在運行的事件任務轉移到其它的運行節點中運行。
動態平衡,當有新的運行節點加入時,需要轉移部分事件任務到新的節點,以保證各節點的任務數平衡;同時當有事件被新發布或下線時,也要執行平衡。
.net core技術棧和Consul中間件,MIP采用.net core進行開發,同時引入了Consul來支持集群一致性,所以盡量在已有條件基礎上考慮解決方案。
二、架構設計
? ? 通過上面的分析和權衡考慮,我們沒有選擇現成的第三方調度框架,而是進行自主研發,而集群一致性方面則依賴于Consul作為基礎。
? ? 所有的調度結果保存成一份清單數據,存儲在Consul中,然后再根據清單數據下發事件任務的啟動/停止命令,清單數據的結構類似于這樣:
我們把主要功能分為"調度模塊"和"運行模塊"兩個部分,參考圖1。
2.1 調度模塊:
? ? 調度模塊主要負責事件任務的分配邏輯,并發送相應的事件任務啟動/停止命令到運行模塊。
事件任務調度,調度模塊從Consul中獲取正在運行的運行模塊服務信息,把事件任務平均分配到運行模塊節點中。
一致性,因為調度邏輯占用資源較小,所以不需要所有的節點都執行邏輯,各節點通過爭搶Consul的KV鎖來完成Leader的選舉,由Leader來執行調度邏輯。
根據運行模塊各節點的狀態,動態的調整分配(超過一定時間持續無法連接的節點認為是故障節點)。
事件任務調度的清單數據存儲到Consul中。
接收從"事件管理"發送過來的事件發布、下線通知,重新調度。
事件任務調度的三個觸發點:第一次啟動初始化,事件變化通知,定時觸發。
2.2 運行模塊:
? ? 運行模塊則接收調度模塊的命令,負責執行事件任務,并把啟動/停止的狀態結果返回給調度模塊,并提供查詢事件任務狀態的API。
事件任務運行,接收調度命令,啟動/停止事件任務的運行,并且保證在接收并完成事件任務的啟動命令后事件持續運行(即如果事件任務異常退出則重新啟動)。
一致性,由調度模塊來保證,根據調度模塊的命令來執行任務。
提供當前正在運行的事件任務的狀態查詢API。
把自身服務注冊到Consul,反映節點的健康狀態。
當發現自身不健康時(無法連接到Consul),超過一定時間后(需要小于調度模塊認為運行節點故障的間隔時間),停止當前節點上的所有事件任務運行。
圖1 架構示意圖
三、調度場景分析
3.1 第一次啟動初始化:
? ? 第一次啟動時,事件任務清單數據為空,所以全新獲取所有的事件信息和所有的運行節點信息,按照平均分配的邏輯分配事件任務,先把分配結果保存到清單,再根據清單逐個去調用運行節點啟動事件任務。
圖2 第一次啟動初始化
3.2 運行節點新增:
? ? 當運行節點新增時,根據已經運行的事件任務清單,還是采取平均分配的原則,從正在運行的節點上,移出部分事件任務到新節點上啟動。
圖3?運行節點新增
3.3 運行節點故障/下線:
? ? 當判斷出某個節點的狀態為不可用時,把該節點上所有的任務轉移到其它節點上執行。
圖4?運行節點故障/下線
3.4 事件發布/下線:
? ? 當調度模塊接收到事件的發布/下線通知時,重新執行調度邏輯,去相應的啟動或停止事件任務。
圖5?事件發布/下線
四、實現邏輯
? ? 通過前面的分析,接下來就是考慮如何去實現了。我們分析了幾種調度發生的場景,是不是按照這個邏輯把代碼實現出來就可以了呢?其實不然,細想一下,我們會發現還有一些其它特性需要考慮,主要從擴展性、可靠性和性能方面考慮。
我們發現每一種調度場景下做的事情都很類似,比如都需要重新獲取運行模塊節點信息和任務清單,并去最終都是去調用運行模塊節點的api去執行操作,那么我們是不是需要在實現設計時再往上抽象一層?如果再抽象是否只是把通用邏輯提取出來,在不同的調度場景調用呢?
我們現在的處理思路是,根據分配邏輯生成任務清單,再根據清單去調用運行模塊的api執行任務的啟動/停止,但是如果在兩次調度的間隔內,某一個運行模塊節點上的某一個或某幾個任務異常停止了(比如某個運行節點執行了重啟,但是因為我們是定時調度,沒有檢測到節點的一次下線和一次上線動作),我們如何保證最終一定是按照清單在運行任務?
還是運行節點重啟了,我們檢測到了下線和上線,但是因為節點下線超過一定時間我們才認為是真正的下線了,并且馬上又有一次新節點的上線,那這個邏輯是不是又變的復雜了,我們的程序到底應該如何處理呢?重啟運行節點是不是需要單獨列為一個場景呢?
上面我們單獨分析了每個調度的場景,邏輯看上去也還簡單,但是如果是多個場景同時發生,我們又該如何實現邏輯呢?相互之間是否會有沖突,又如何保證可靠性呢?
目前每一個事件的發布/下線都會發送一次通知,如果在批量操作時,會頻繁觸發調度,有沒有辦法在不改變事件通知的情況下,盡量合并調度呢?
? ? 我們回過頭來仔細想一想,其實從計算機的角度看,我們的程序主要做了兩件事情:
根據當前的情況,計算出任務分配清單,生成事件任務操作命令。
根據生成好的命令,調用運行節點api。
? ? 接下來就比較清晰了,我們的程序就是要保證上面兩件事件穩定、可靠、高效的完成,大體的處理邏輯如下:
圖6?實現邏輯
? ? 接下來我們再把兩種特殊場景接入到這種日常調度邏輯里面來:
第一次初始化時,在最開始的時候根據節點和總的事件清單,生成一個完整的節點任務清單,然后直接進入日常調度邏輯。
當有新的事件發布/下線通知進來的時候,根據通知內容去更新節點任務清單,同時對內存變量進行一個標記,然后直接進入日常調度邏輯。并且目前調度的定時器是2秒觸發一次,但是不會每次都執行調度邏輯,而是會判斷是否達到定時調度的時間,或者是事件變更通知的內存標記為已變更,也避免頻繁調度造成的性能和穩定性風險。
五、結束
? ? 經過我們的分析設計,我們把一個看似繁雜的分布式調度的場景變的簡單了,提煉出其中的核心邏輯,然后去實現和完善它,以不變應萬變,只要保證其中的核心邏輯的穩定,不管外面的接入場景如何多變,我們都能從容的應對。
? ? 在本篇中,我們沒有去涉及什么很高深的框架和組件以及具體的實現代碼,主要還是對我們在實現這個分布式調度過程中的思路進行了一些分享。我們不敢說一定是最對最好的,但是當思路清楚了,實現起來也就不復雜了。
------ END ------
作者簡介
王同學:?架構師,目前負責ERP集成平臺架構的規劃與設計工作。
也許您還想看
MIP服務發現的高可用架構實踐
基于消息的高穩定集成架構方案
一個全棧式的應用集成平臺,打破“信息孤島”
研發協同平臺持續集成2.0架構演進
總結
以上是生活随笔為你收集整理的集成平台集群任务动态分派的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员过关斩将-- 喷一喷坑爹的面向UI
- 下一篇: [头脑风暴] 解读Docker Brid