集羣下處理請求的時序問題

一、環境介紹

所述軟件爲WEB產品,爲一個整體解決方案的中間層,具體爲同一套軟件部署在多臺服務器,相互之間可以組成集羣,以共同處理用戶請求。對上層調用者來說,其中有一臺爲主,其餘爲備。對下層中的某一個被管理者來說,該集羣中某一臺爲主控,其他服務器可以是它的備控,上層和下層認爲的主不一定相同。

二、問題描述

本次的問題出在被管理單位的主控和備控之間。

在主控上發出請求時,業務處理流程爲:
    1.清空本服務器的緩存
    2.清空集羣的共享緩存
    3.下發請求指令給下層被管理者
    4.在此下發略作改動的請求指令給下層
    5.下層被管理者將按指令處理後的結果給共享緩存
    6.從共享緩存中取出結果,返回用戶
需要說明的是:
    本服務器的緩存,爲本服務器所有實例共享,所以每一個新的請求都應清空該緩存
    集羣的共享緩存,爲該集羣內所有服務器共享,具體有數據同步的模塊負責。對於新的請求也應清理該緩存

在被控上走此流程時出現異常:
    只有改動後的請求指令對應的結果,沒有改動前對應的結果

三、定位問題

主控與被控部署在兩臺服務器上,但使用的是同一套軟件。當請求傳給備控時,備控無法直接將指令下發給下層設備,必須通過主控間接得到結果。
原流程中的步驟3和4具體邏輯爲:判斷是否是主控,若是,直接處理,若不是,將數據重新封裝爲一個實體,通過調用主控中同樣的對外接口,將請求轉交給主控,主控處理後將結果再封裝,返回給備控。
簡單以線程說明:

備控中的處理線程:1 —— 2 —— 3(主控起一新的線程t1) —— 4(主控再起一新的線程t2) —— 5 —— 6
主控中的處理線程t1:        1 —— 2 —— 3 —— 4 —— 5 —— 6
主控中的處理線程t2:                              1 —— 2 —— 3 —— 4 —— 5 —— 6

可以看到,每新起一個線程,都會執行清理緩存操作,使有效的數據丟失。
具體來說,備控中的步驟4,多餘且將本地緩存和共享緩存都刪除。
主控t2線程完全多餘,其步驟4會將之前的共享緩存都刪除。所以最後得到的結果就只剩t2的步驟4得到的結果。在此之前的都將被覆蓋。

四、解決方法

需要說明的是,主控和備控使用的軟件是一樣的,備控的請求傳給主控時,就相當於在主控中重新執行了該請求。解決的依據是我可以得到兩個標記:
標記一:在步驟3或4中的方法,我可以在執行這個步驟後得到一個信息:isSelf,這個請求是本服務器處理,即本服務器爲主控時返回true;需要轉交給主控處理,即本服務器爲備控時,返回false。說明每次執行該步驟isSelf都會更新,即備控執行後返回false,並將請求移交給主控,主控再執行時返回true。
標記二:可以通過一個接口isQuery(),得到請求的來源,當是直接從前端獲取到的時候,爲true,當請求是被備控轉交過來時,爲false。
處理方式:
執行流程不變,只是在其中幾步上加上判斷條件:
步驟2加上限定,只有在請求是前端直接給的,即isQuery()爲true時,才執行步驟1,清除共享緩存。保證共享緩存在一次請求中只被清理一次,且是在最初時被清理。
步驟4加上限定,只有從步驟3中得到的isSelf爲true(表明,步驟3的確是被本服務器處理的)時,才執行步驟4,否則跳過。

修改後最終結果:
當請求直接發給主控時,所有條件都滿足,順序執行
當請求發給備控時,備控執行至步驟3,跳過步驟4,5,6,等待主控返回結果;當請求有備控轉交給主控時,主控只會執行步驟1,跳過步驟2,執行3,4,5,6,得到結果,至於結果是封裝返回給備控,還是其他處理,不需關心。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章