消息服務器工作流程
- 消息服務器(Message Server, MS)啟動.
- 啟動 WebSocket 服務端,監聽來自 BS 的 WebSocket 連接。
- 業務服務器(Business Server, BS)啟動。
- BS 作為 WebSocket 客戶端,建立其到 MS 的 WebSocket 連接,得到 bsCwsHandle。
- BS 作為 WebSocket 服務端啟動,監聽來自終端設備的 WebSocket 連接。
- 建立 BS 與 MS 之間的 WebSocket 連接。
- MS 收到來自 BS 的 WebSocket 連接得到 msSwsHandle。
- MS 以隨機生成的 UUID 作為此 BS 的 serverId。
- MS 以形如 <serverId, msSwsHandle> 的映射(swMap)存儲此 BS 的 ID 與 WebSocket 句柄。
- 建立終端與 BS 之間的 WebSocket 連接。
- BS 收到來自終端設備的 WebSocket 得到 bsSwsHandle。
- BS 以終端登錄用戶的 ${ hospitalCode-hosareaCode-uid } 聯合鍵(unionedUid)作為此終端的標識。
- BS 以形如 <unionedUid, bsSwsHandle> 的映射(uwMap)存儲此終端的標識與 WebSocket 句柄。
- 完成終端在 MS 處注冊終端設備。
- BS 在與終端建立完成 WebSocket 連接后,將 unionedUid 與傳輸類型 type=0 通過 bsCwsHandle 發送到 MS。
- MS 收到來自 BS 的 WebSocket 消息,匹配 type 為 0,則將傳來的 unionedUid 與相應的 serverId 存入 MongoDB 的 wsEndMapModel 中,wsEndMapModel 定義如下:
const wsEndMapModel = mongoConnection.model('wsEndMap', new Schema({ serverIdentifer: String, endIdentifer: String }));
- 發送當前完成注冊的終端在 MongoDB 中緩存了的屬于它的消息。
- MongoDB 中維護了一個定義如下的 msgListModel 來存儲當目標終端不在線時的消息,生存期為 600 秒。
const msgListModel = mongoConnection.model('msgList', new Schema({ endIdentifer: String, messageContent: String, createAt: { type: Date, expires: 600, default: Date.now } }));
- 根據 unionedUid 查看緩存中消息,如果有,則根據 MS 中維護的 swMap 獲得 當前終端所屬 BS 的 msSwsHandle,對其發送查詢得到的消息即可。
- MongoDB 中維護了一個定義如下的 msgListModel 來存儲當目標終端不在線時的消息,生存期為 600 秒。
- 終端或 BS 斷掉 WebSocket 的處理邏輯。
- 終端設備中斷 WebSocket 連接時,會觸發 BS 端的 onclose 事件,可以在事件函數里做以下邏輯。
- BS 主動中斷與終端設備的 WebSocket 連接時,BS 將此設備 unionedUid 與傳輸類型 type=1 通過 bsCwsHandle 發送到 MS,MS 刪除 MongoDB 中 wsEndMapModel 里 endIdentifer 是當前 unionedUid 的文檔,代表此終端設備已不在線。
- 終端或 BS 發送 WebSocket 的處理邏輯。
- 終端1(End1)發送消息給終端2(End2) 時,BS1 收到 End1 的消息,BS 將目標設備的 unionedUid 與傳輸類型 type=2 通過 bsCwsHandle 發送到 MS。
- MS 查找 wsEndMapModel 中有沒有 endIdentifer 是這個 unionedUid 的文檔(此終端在線與否),如果找到代表其在線,根據查找到的 serverIdentifer 到 swMap 中拿到這個 BS 對應的 WebSocket 句柄 msSwsHandle,發送具體的消息到這個 BS。
- 如果沒找到,則將這條消息存入 MongoDB 的 msgListModel 中,等待目標終端上線,或者過期清楚。