應用多節點部署,操作同步的實現方案

系統功能概述:
我們的應用所面向的終端用戶是醫學人員,系統部署後,用戶可以通過複雜的醫學條件檢索出符合條件的病人,稱之爲隊列,然後定義變量,也就是再次查詢每一個病人的具體信息,如年齡,性別,是否服藥,檢測的血壓值是多少等等,有了這些數據,就可以做統計學方面的分析,得出一些醫學結論。

業務需求和解釋:
客戶提出了一個應用多節點部署,並且操作同步的業務需求。這個客戶是省市級的醫院,其下還有鄉鎮,社區醫院,應用要在每一家醫院部署,數據庫 Schema 也是一樣的,只是每家醫院的數據各自來源於自己的 HIS, EMR 等系統(我們部署前會從這些數據源抽取數據到我們應用依賴的數據庫裏去)。假設部署了 A,B,C,D,E 五家醫院, A 作爲研究項目的發起方,可以邀請 B,C,D 三家醫院(任意家都行)共同做一個科學研究, 三家被邀請的醫院都同意了, A 作爲請求方就通過應用的界面進行操作, B,C,D 不需要人工干預, 就能完成步驟一模一樣的科研,最終和 A 一樣得出醫學統計結果. A 也可以讓 B,C,D 把病人的必要信息傳過來,在自己的應用上做統計分析. 應用的初衷就是這些醫院組成一個聯盟,擴大數據庫樣本,有條件(數據不共享,即使共享也是脫敏後必需的信息共享)地進行科研.

實現要點:
1. 被邀請節點的業務操作和 A 節點同步, 節點間的通信是消息驅動還是直接 WebService 請求?
2. 請求被處理的時長可能相差 N 個數量級,怎麼協同?
3. 如何保障通信的健壯,不丟失,且不會多次執行,即便多次執行,是否能夠冪等?

正如業務功能概述裏所說,系統功能大致分成了幾個步驟,這些步驟都是強依賴的鏈路,任何一環出問題,都無法繼續下去。雖然數據庫 Schema 一樣,但各醫院的數據體量不一樣,同樣一個查詢,各個應用的響應時間差別很大,有些查詢,幾秒到幾十分鐘的差別都是可能的。我們的實現的方案採用了本地消息表的方式,消息發送後等待反饋保證通信成功,健壯性則是通過消息的消費順序和發送順序一致,加上冪等操作。業務上,我們對一個科研請求涉及到的後臺請求做整合,提煉出幾個必須要進行同步的接口,使用 Spring AOP 進行監控,一旦接口被調用,就對數據庫的業務表進行查詢,檢索出必需的數據,轉成對象,序列化成 JSON。然後將接口信息,包括請求體JSON,發送時間等存到本地消息表。成功後,再通過 WebService 將消息發送到到被邀請的節點,被邀請節點返回一個反饋,然後自己消費消息。

技術難點和實現:
1. 消息的消費時長千差萬別,發送方不可能等待接收方消費完消息再返回反饋。所以消息接收方在把消息存入本地庫後,主線程立即返回反饋(HTTP響應),然後開一個子線程消費消息
2. 對請求方來說,人工操作,發送的消息時間先後順序是確定的,那麼消息要包含消息的發送時間,接收方消費消息以發送時間排序,逐個消費
3. 請求方如果超時時間內,沒有收到反饋,消息就標記爲失敗,可以通過定時任務或者可視化界面手動觸發消息的重發
4. 請求方重發消息,則一定是逐條發送,成功一個才發下一個,確保接收方收消息有序
5. 消息要包含一個 checkSum, 接收方通過這個屬性判斷消息是否接收過
6. 接收方消費消息時,要檢查當前應用是否正在消費依賴消息,或者依賴的消息消費失敗,然後決定是否可以消費剛剛接收到的消息
7. 消費消息前,要對相關表數據做一次清除,保證不會因爲之前消息消費的失敗,導致數據出錯,進一步確保操作的冪等
8. 接收方如果消費消息失敗,也是通過定時任務或者可視化界面手動觸發消息的消費

由於消息鏈路的強依賴,各個消息之前也是有關聯的,比如 ANALYSIS 對象裏面有個 projectId, 不同的節點在新建 PROJECT 的時候使用的是本地 Oracle 的 Sequence,所以 ID 值都不會相同,如果請求方直接把 projectId 發出去,那麼消費方通過 projectId 關聯對象時,數據就是錯亂的。我們根據對業務的分析,發現相關業務表的數據不可能超過一個億,所以就給每個節點分配一個大數,比如 A 節點是一億,B 節點是兩億,C 是三億等等。然後 Spring AOP 監控相關業務表的 INSERT 語句,通過 afterReturning 註解獲取 Sequence 的 ID,加上給定的大數作爲新的 ID,這樣就能保證如 projectId 在各個節點的唯一性。

PS:
爲了業務上的需要,我們還引入了一箇中心節點,請求方的消息只是點對點發給中心節點,中心節點再轉發到所有被邀請節點(中心節點也可以是被邀請節點)。


1. 首先對需要同步的接口進行 AOP 攔截

2. 構建消息,存入本地庫,然後發送並等待反饋:

3. 接收方處理接收到的消息

4. 判斷是否可以消費接收到的消息

最後,是保證各節點 ID 唯一性的實現:

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章