μSOA 架構 - SOA 的有力替代和補充

白楊 2019-03程序員

baiy.cn算法

Copyright (C) 2016 - 2019 Bai Yang, baiy.cn / baiyang.name, baiyang@gmail.com, All Rights Reserved數據庫

AIO vs. SOA後端

長久以來,服務器端的高層架構大致被區分爲對立的兩類:SOA(Service-oriented architecture)以及 AIO(All in one)。SOA 將一個完整的應用分割爲相互獨立的服務,每一個服務提供一個單一標準功能(如:會話管理、交易評價、用戶積分等等)。服務間經過 RPC、WebAPI 等 IPC 機制暴露功能接口,並以此相互通訊,最終組合成一個完整的應用。api

而 AIO 則相反,它將一個應用規約在一個獨立的總體中,SOA 中的不一樣服務在 AIO 架構下呈現爲不一樣的功能組件和模塊。AIO應用的全部組件一般都運行在一個地址空間(一般是同一進程)內,全部組件的代碼也經常放在同一個產品項目中一塊兒維護。緩存

AIO 的優點是部署簡單,不須要分別部署多個服務,併爲每一個服務實現一套高可用集羣。與此同時,因爲可避免網絡傳輸、內存拷貝等 IPC 通訊所帶來的大量開銷,所以 AIO 架構的單點效率一般遠高於 SOA。服務器

另外一方面,因爲 AIO 架構中組件依賴性強,組件間常常知曉並相互依賴對方的實現細節,所以組件的可重用性及可替換性差,維護和擴展也較困難。特別是對於剛加入團隊的新人來講, 面對包含了大量互相深度耦合之組件和模塊的"巨型項目",經常須要花費大量努力、經歷不少挫折而且犯不少錯誤才能真正接手。而即便對於老手來講,因爲模塊 間各自對對方實現細節錯綜複雜的依賴關係,也容易發生在修改了一個模塊的功能後,莫名奇妙地影響到其它看起來絕不相干功能的狀況。微信

與此相反,SOA 模型部署和配置複雜——現實中,一個大型應用經常被拆分爲數百個相互獨立的服務,《程序員》期刊中的一份公開發表的論文顯示,某個國內 "完全擁抱" SOA 的著名(中國排名前5)電商網站將他們的 Web 應用拆分紅了一千多個服務。能夠想象,在多活數據中心的高可用環境內部署成百上千個服務器集羣,而且配置他們彼此間的協做關係是多大的工做量。最近的協程網絡癱瘓事件也是由於上千個服務組成的龐大 SOA 架構致使故障恢復緩慢。網絡

除了部署複雜之外,SOA 的另外一個主要缺點就是低效——從邏輯流的角度看,幾乎每次來自客戶端的完整請求都須要依次流經多個服務後,才能產生最終結果並返回用戶端。而請求(經過消息中間件)每"流經"一個服務都須要伴隨屢次網絡 IO 和磁盤訪問,多個請求可累計產生較高的網絡時延,使用戶請求的響應時間變得不可肯定,用戶體驗變差,並額外消耗大量資源。數據結構

混亂的SOA 依賴關係(圖片來自互聯網)

此外,不管是每一個 Service 各自鏈接不一樣的 DBMS 仍是它們分別接入同一個後端分佈式 DBMS 系統,實現跨服務的分佈式事務支持工做都要落到應用層開發者手中。而分佈式事務(XA)自己的實現複雜度恐怕就以超過大部分普通應用了,更況且還須要爲分佈式事務加上高可靠和高可用保證——須要在單個數據切片上使用 Paxos/Raft 或主從+Arbiter之類的高可用、強一致性算法,同時在涉及多個數據切片的事務上使用 2PC/3PC 等算法來保證事務的原子性。所以 SOA 應用中的跨 Service 事務基本都只能退而求其次,作到最終一致性保證,即使如此,也須要增長大量的額外工做——在稍微複雜點的系統裏,高可用,並能在指定時間內可靠收斂的最終一致性算法實現起來也不是那麼容易。

與此同時,大部分 SOA 系統還常常須要使用消息中間件來實現消息分發服務。若是對消息中間件的可用性(部分節點故障不會影響正常使用)、可靠性(即便在部分節點故障時,也確保消 息不丟失、不重複、並嚴格有序)、功能性(如:發佈/訂閱模型、基於輪轉的任務分發等)等方面有所要求的話,那麼消息中間件自己也容易成爲系統的瓶頸。

SOA 架構的優勢在於其高內聚、低耦合的自然特性。僅經過事先約定的 IPC 接口對外提供服務,再配合服務間隔離(一般是在獨立節點中)運行的特質,SOA 架構劃分出了清晰的接口和功能邊界,所以能夠被很是容易地重用和替換(任何實現了兼容IPC接口的新服務均可替換已有的老服務)。

從軟件工程和項目管理的視角來看,因爲每一個服務自己一般有足夠高的內聚性,而且單個服務實現的功能也較獨立,所以相對於 AIO 意大利麪式的,相互交織的結構來講,SOA 的服務很是便於維護——負責某一服務的開發人員只須要看好本身這一畝三分地便可,只要保持服務對外提供的 API 沒有發生不兼容的變化,就不須要擔憂修改代碼、替換組件等工做會影響到其它"消費者"。

同時,由多個獨立服務所組成的應用也更容易經過加入新服務和從新組合現有服務來進行功能變動和擴展。

 

μSOA 架構

在經歷了大量實際項目中的權衡、思索和實踐後,我逐步定義、實現和完善了可以兼二者之長的 "μSOA"(Micro SOA)架構。在 μSOA 架構中,獨立運行的服務被替換成了支持動態插拔的跨平臺功能插件(IPlugin);而插件則經過(並僅可經過)API Nexus 來動態地暴露(註冊)和隱藏(註銷)自身所提供的功能接口,同時也使用 API Nexus 來消費其它插件提供服務。

μSOA 徹底繼承了 SOA 架構高內聚、低耦合的優勢,每一個插件如獨立的服務同樣,有清晰的接口和邊界,可容易地被替換和重用。在可維護性上,μSOA 也與 SOA 徹底一致,每一個插件均可以被單獨地開發和維護,開發人員只須要管好本身維護的功能插件便可。經過加入新插件以及對現有功能插件的從新組合,甚至可比 SOA 模式更容易地對現有功能進行變動和擴展。

而在性能方面,因爲全部功能插件都運行在同一個進程內,所以經過 API Nexus 的相互調用不須要任何網絡 IO、磁盤訪問和內存拷貝,也沒有任何形式的其它 IPC 開銷,所以其性能和效率都可與 AIO 架構保持在相同量級。

與此同時,μSOA 的部署與 AIO 一樣簡單——部署在單個節點便可使用,只需部署一個集羣便可實現高可用和橫向擴展。在配置方面也遠比 SOA 簡單,僅須要比 AIO 應用多配置一個待加載模塊列表而已,而且這些配置也可經過各類配置管理產品來實現批量維護。簡單的部署和配置過程不但簡化了運營和維護工做,也大大方便了開發和測試環境的構建。

此外,μSOA 也在極大程度上避免了對消息中間件的依賴,取而代之的是經過 API Nexus 的直接API調用;或是在須要削峯填谷的場合中,使用由內存零拷貝和無鎖算法高度優化的線程間消息隊列。這一方面大大增長了吞吐,避免了延遲,另外一方面也避免了部署和維護一個高可用的消息分發服務集羣所帶來的巨大工做量——μSOA 集羣內的節點間協做和協調通訊需求已被將至最低,對消息分發的可靠性、可用性和功能性都沒有過高要求。在多數狀況下,使用 Gossip Protocol 等去中心化的 P2P 協議即足以知足須要,有時甚至能夠徹底避免這種集羣內的節點間通訊。

從 μSOA 的角度看,也能夠將 DBC 視做一種幾乎全部服務器端應用都須要使用的基礎功能插件,因爲其經常使用性,所以他們被事先實現並加進了 libapidbc 中。由此,經過提供 IPlugin、API Nexus 以及 DBC 等幾個關鍵組件,libapidbc 爲 μSOA 架構奠基了良好的基礎設施。

固然,μSOA 與 SOA 和 AIO 三者間並非互斥的選擇。在實際應用場景中,能夠經過三者間的有機組合來達成最合理的設計。例如:對於視頻轉碼等很是耗時而且不須要同步等待其完成並返回結果的異步操做來講,因爲其絕大部分開銷都耗費在了視頻編解碼計算上,所以將其做爲插件加入其它 App Server 就徹底沒有必要,將它做爲獨立的服務,部署在配置了專用加速硬件的服務器集羣上應該是更好的選擇。

 

消息端口交換服務

白楊消息端口交換服務(BYPSS)設計用於單點支撐百億量級端口、十萬量級節點規模,每秒處理百萬至千萬量級消息的高可用、強一致、高性能分佈式協調和消息交換服務。其中關鍵概念包括:

    • 鏈接(Connection):每一個客戶端(應用集羣中的服務器)節點至少與端口交換服務保持一個 TCP 長鏈接。

    • 端口(Port):每一個鏈接上能夠註冊任意多個消息端口,消息端口由一個 UTF-8 字符串描述,必須在全局範圍內惟一,若其它客戶端節點已註冊了相同的消息端口,則端口註冊失敗。

端口交換服務對外提供的 API 原語包括:

    • 等待消息(WaitMsg):客戶端集羣中的每一個節點均應保持一個到端口交換服務的 TCP 長鏈接,並調用此方法等待消息推送。此方法將當前客戶端鏈接由消息發送鏈接升級爲消息接收鏈接。

      每一個節點號只能對應一個消息接收鏈接,若一個節點嘗試同時發起兩個消息接收鏈接,則較早的那個接收鏈接將被關閉,而且綁定到當前節點上的全部端口都將被註銷。
       
    • 續租(Relet):若端口交換服務在指定的間隔內未收到來自某個消息接收鏈接的續租請求,則斷定該節點已經下線,並釋放全部屬於該節點的端口。續租操做用來週期性地向端口交換服務提供心跳信號。
       
    • 註冊端口(RegPort):鏈接成功創建後,客戶端應向端口交換服務註冊全部屬於當前節點的消息端口。能夠在一個端口註冊請求中包含任意多個待註冊端口,端口交換服務會返回全部註冊失敗(已被佔用)的端口列表。調用者能夠選擇是否須要爲註冊失敗的端口訂閱端口註銷通知。

      須要注意的是,每次調用 WaitMsg 重建消息接收鏈接後,都須要從新註冊當前節點上的全部端口。
       
    • 註銷端口(UnRegPort):註銷數據當前節點的端口,可一次提交多個端口執行批量註銷。
       
    • 消息發送(SendMsg):向指定的端口發送消息(BLOB),消息格式對交換服務透明。若指定的端口爲空串,則向端口交換服務上的全部節點廣播此消息;亦可同時指定多個接收端口,實現消息組播。若指定的端口不存在,則安靜地丟棄該消息。客戶端可在一次請求中包含多個消息發送命令,主動執行批量發送,服務器端也會將發往同一節點的消息自動打包,實現消息批量推送。
       
    • 端口查詢(QueryPort):查詢當前佔用着指定端口的節點號,及其 IP 地址。此操做主要用於實現帶故障檢測的服務發現,消息投遞時已自動執行了相應操做,故無需使用此方法。可在同一請求中包含多個端口查詢命令,執行批量查詢。
       
    • 節點查詢(QueryNode):查詢指定節點的 IP 地址等信息。此操做主要用於實現帶故障檢測的節點解析。能夠一次提交多個節點,實現批量查詢。

 端口交換服務的客戶端鏈接分爲如下兩類:

    • 消息接收鏈接(1:1):接收鏈接使用 WaitMsg 方法完成節點註冊並等待消息推送,同時經過 Relet 接口保持屬於該節點的全部端口被持續佔用。客戶端集羣中的每一個節點應當而且僅可以保持一個消息接收鏈接。此鏈接爲長鏈接,因爲鏈接中斷重連後須要從新進行服務選舉(註冊端口),所以應儘量一直保持該鏈接有效並及時完成續租。

    • 消息發送鏈接(1:N):全部未使用 WaitMsg API 升級的客戶端鏈接均被視爲發送鏈接,發送鏈接無需經過 Relet 保持心跳,僅使用 RegPort、UnRegPort、SendMsg 以及 QueryPort 等原語完成非推送類的客戶端請求。集羣中的每一個服務器節點一般都會維護一個消息發送鏈接池,以方便各工做線程高效地與端口轉發服務保持通訊。

 與傳統的分佈式協調服務以及消息中間件產品相比,端口轉發服務主要有如下特色:

    • 功能性:端口轉發服務將標準的消息路由功能集成到了服務選舉(註冊端口)、服務發現(發送消息和查詢端口信息) 、故障檢測(續租超時)以及分佈式鎖(端口註冊和註銷通知)等分佈式協調服務中。是帶有分佈式協調能力的高性能消息轉發服務。經過 QueryPort 等接口,也能夠將其單純地看成帶故障檢測的服務選舉和發現服務來使用。
       
    • 高併發、高性能:由 C/C++/彙編實現;爲每一個鏈接維護一個消息緩衝隊列,將全部端口定義及待轉發消息均保存在內存中(Full in-memory);主從節點間無任何數據複製和狀態同步開銷;信息的發送和接收均使用純異步 IO 實現,於是可提供高併發和高吞吐的消息轉發性能。
       
    • 可伸縮性:在單點性能遭遇瓶頸後,可經過級聯上級端口交換服務來進行擴展(相似 IDC 接入、匯聚、核心等多層交換體系)。
       
    • 可用性:兩秒內完成故障檢測和主備切換的高可用保證,基於多數派的選舉算法,避免由網絡分區引發的腦裂問題。
       
    • 一致性:保證任意給定時間內,最多隻有一個客戶端節點可持有某一特定端口。不可能出現多個客戶端節點同時成功註冊和持有相同端口的狀況。
       
    • 可靠性:全部發往未註冊(不存在、已註銷或已過時)端口的消息都將被安靜地丟棄。系統保證全部發往已註冊端口消息有序且不重複,但在極端狀況下,可能發生消息丟失:
       
      • 端口交換服務宕機引發主從切換:此時全部在消息隊列中排隊的待轉發消息均會丟失;全部已註冊的客戶端節點均須要從新註冊; 全部已註冊的端口(服務和鎖)均須要從新進行選舉/獲取(註冊)。
         
      • 客戶端節點接收鏈接斷開重連:消息接收鏈接斷開或重連後,全部該客戶端節點以前註冊的端口均會失效並需從新註冊。在接收鏈接斷開到重連的時間窗口內,全部發往以前與該客戶端節點綁定的,且還沒有被其它節點從新註冊的端口之消息均被丟棄。

可見,白楊消息端口轉發服務自己是一個集成了故障檢測、服務選舉、服務發現和分佈式鎖等分佈式協調功能的消息路由服務。它經過犧牲極端條件下的可靠性,在保證了 強一致、高可用、可伸縮(橫向擴展)的前提下,實現了極高的性能和併發能力。

能夠認爲消息端口交換服務就是爲 μSOA 架構量身定作的集羣協調和消息分發服務。μSOA 的主要改進即:將在 SOA 中,每一個用戶請求均須要牽扯網絡中的多個服務節點參與處理的模型改進爲大部分用戶請求僅須要同一個進程空間內的不一樣 BMOD 參與處理。

這樣的改進除了便於部署和維護,以及大大下降請求處理延遲外,還有兩個主要的優勢:

    • 將 SOA 中,須要多個服務節點參與的分佈式事務或分佈式最終一致性問題簡化成爲了本地 ACID Transaction 問題(從應用視角來看是如此,對於分佈式 DBS 來講,以 DB 視角看來,事務仍然能夠是分佈式的),這不只極大地簡化了分佈式應用的複雜度,加強了分佈式應用的一致性,也大大減小了節點間通訊(由服務間的 IPC 通訊變成了進程內的指針傳遞),提升了分佈式應用的總體效率。
       
    • 全對等節點不只便於部署和維護,還大大簡化了分佈式協做算法。同時因爲對一致性要求較高的任務都已在同一個進程空間內完成,所以節點間通訊不但大大減小, 並且對消息中間件的可靠性也再也不有太高的要求(一般消息丟失引發的不一致可簡單地經過緩存超時或手動刷新來解決,可確保可靠收斂的最終一致性)。

在此前提下,消息端口交換服務以容許在極端狀況下丟失少許將來得及轉發的消息爲代價,來避免磁盤寫入、主從複製等低效模式,以提供極高效率。這對 μSOA 來講是一種很是合理的選擇。

 

極端條件下的可靠性

傳統的分佈式協調服務一般使用 Paxos 或 Raft 之類基於多數派的強一致分佈式算法實現,主要負責爲應用提供一個高可用、強一致的分佈式元數據 KV 訪問服務。並以此爲基礎,提供分佈式鎖、消息分發、配置共享、角色選舉、服務發現、故障檢測等分佈式協調服務。常見的分佈式協調服務實現包括 Google Chubby(Paxos)、Apache ZooKeeper(Fast Paxos)、etcd(Raft)、Consul(Raft+Gossip)等。

Paxos、Raft 等分佈式一致性算法的最大問題在於其極低的訪問性能和極高的網絡開銷:對這些服務的每次訪問,不管讀寫,都會產生至少三次網絡廣播——以投票的方式確 定本次訪問通過多數派確認(讀也須要如此,由於主節點須要確認本次操做發生時,本身仍擁有多數票支持,還是集羣的合法主節點)。

在實踐中,雖可經過下降系統總體一致性或加入租期機制來優化讀操做的效率,但其整體性能仍十分低下,而且對網絡 IO 有很高的衝擊:Google、Facebook、Twitter 等公司的歷次重大事故中,不少都是因爲發生網絡分區或人爲配置錯誤致使 Paxos、Raft 等算法瘋狂廣播消息,導致整個網絡陷入廣播風暴而癱瘓。

此外,因爲 Paxos、Raft 等分佈式一致性算法對網絡 IO 的吞吐和延遲等方面均有較高要求,而鏈接多座數據中心機房(IDC)的互聯網絡一般又很難知足這些要求,所以致使依賴分佈式協調算法的強一致(抗腦裂)多活 IDC 高可用集羣架構難以以合理成本實現。做爲實例:2015 年 8 月 20 日 Google GCE 服務中斷 12 小時並永久丟失部分數據;2015 年 5 月 27 日和 2016 年 7 月 22 日支付寶兩次中斷數小時;2013 年 7 月 22 日微信服務中斷數小時;以及 2017 年 5 月英國航空癱瘓很多天等重大事故均是因爲單個 IDC 因市政施工(挖斷光纖)等緣由下線,同時未能成功構建多活 IDC 架構,所以形成 IDC 單點依賴所致使的。

前文也已提到過:因爲大部分採用 SOA 架構的產品須要依賴消息中間件來確保系統的最終一致性。所以對其可用性(部分節點故障不會影響正常使用)、可靠性(即便在部分節點故障時,也確保消息不丟 失、不重複、並嚴格有序)、功能性(如:發佈/訂閱模型、基於輪轉的任務分發等)等方面均有較嚴格的要求。這就必然要用到高可用集羣、節點間同步複製、數 據持久化等低效率、高維護成本的技術手段。所以消息分發服務也經常成爲分佈式系統中的一大主要瓶頸。

與 Paxos、Raft 等算法相比,BYPSS 一樣提供了故障檢測、服務選舉、服務發現和分佈式鎖等分佈式協調功能,以及相同等級的強一致性、高可用性和抗腦裂(Split Brain)能力。在消除了幾乎所有網絡廣播和磁盤 IO 等高開銷操做的同時,提供了數千、甚至上萬倍於前者的訪問性能和併發處理能力。 可在對網絡吞吐和延遲等方面無附加要求的前提下,構建跨多個 IDC 的大規模分佈式集羣系統。

與各個常見的消息中間件相比,BYPSS提供了一騎絕塵的單點百萬至千萬條消息每秒的吞吐和路由能力——一樣達到千百倍的性能提高,同時保證消息不重複和嚴格有序。

然而天下沒有免費的午飯,特別是在分佈式算法已經很是成熟的今天。在性能上擁有絕對優點的同時,BYPSS 必然也有其妥協及取捨——BYPSS 選擇放棄極端(平均每一年2次,而且大多由維護引發,控制在低谷時段,基於實際生產環境多年統計數據)情形下的可靠性,對分佈式系統的具體影響包括如下兩方面:

    • 對於分佈式協調服務來講,這意味着每次發生 BYPSS 主節點故障掉線後,全部的已註冊端口都會被強制失效,全部活動的端口都須要從新註冊。

      例如:若分佈式 Web 服務器集羣以用戶爲最小調度單位,爲每位已登錄用戶註冊一個消息端口。則當 BYPSS 主節點因故障掉線後,每一個服務器節點都會得知本身持有的全部端口均已失效,並須要從新註冊當前本身持有的全部活動(在線)用戶。

      幸運的是,該操做能夠被批量化地完成——經過批量端口註冊接口,可在一次請求中同時提交多達數百萬端口的註冊和註銷操做,從而大大提高了請求處理效率和網絡利用率:在 2013 年出廠的至強處理器上(Haswell 2.0GHz),BYPSS 服務可實現每核(每線程)100 萬端口/秒的處理速度。同時,得益於我方自主實現的併發散列表(每一個 arena 都擁有專屬的彙編優化用戶態讀者/寫者高速鎖),所以可經過簡單地增長處理器核數來實現處理能力的線性擴展。

      具體來講,在 4 核處理器+千兆網卡環境下,BYPSS 可達成約每秒 400 萬端口註冊的處理能力;而在 48 核處理器+萬兆網卡環境下,則可實現約每秒 4000 萬端口註冊的處理能力(測試時每一個端口名稱的長度均爲 16 字節),網卡吞吐量和載荷比都接近飽和。再加上其發生機率極低,而且恢復時只須要隨着對象的加載來逐步完成從新註冊,所以對系統總體性能幾乎不會產生什麼波動。

      爲了說明這個問題,考慮 10 億用戶同時在線的極端情形,即便應用程序爲每一個用戶分別註冊一個專用端口(例如:用來肯定用戶屬主、完成消息分發等),那麼在故障恢復後的第一秒內,也不可能出現"全球 10 億用戶心有靈犀地同時按下刷新按鈕"的狀況。相反,基於 Web 等網絡應用的固有特性,這些在線用戶一般要通過幾分鐘、幾小時甚至更久纔會逐步返回服務器(同時在線用戶數=每秒併發請求數x用戶平均思考時間)。即便按照比較嚴苛的 "1分鐘內所有返回"(平均思考時間 1 分鐘)來計算,BYPSS 服務每秒也僅需處理約 1600 萬條端口註冊請求。也就是說,一臺配備了 16 核至強處理器和萬兆網卡的入門級 1U PC Server 便可知足上述需求。

      做爲對比實例:官方數據顯示,淘寶網 2015 年雙十一當天的日活用戶數(DAU)爲 1.8 億,同時在線用戶數峯值爲 4500 萬。因而可知,目前超大型站點瞬時併發用戶數的最高峯值仍遠低於前文描述的極端狀況。即便再提升數十倍,BYPSS 也足可輕鬆支持。
       
    • 另外一方面,對於消息路由和分發服務來講,這意味着每次發生 BYPSS 主節點故障掉線後,全部暫存在 BYPSS 服務器消息隊列中,未及發出的待轉發消息都將永久丟失。可喜的是,μSOA 架構不須要依賴消息中間件來實現跨服務的事務一致性。所以對消息投遞的可靠性並沒有嚴格要求。

      意即:μSOA 架構中的消息丟失最多致使對應的用戶請求徹底失敗,此時仍可保證數據的全局強一致性,毫不會出現 "成功一半" 之類的不一致問題。在絕大多數應用場景中,這樣的保證已經足夠——即便支付寶和四大行的網銀應用也會偶爾發生操做失敗的問題,這時只要資金等賬戶數據未出現錯誤,那麼稍候重試便可。

      此外,BYPSS 服務也經過高度優化的異步 IO,以及消息批量打包等技術有效下降了消息在服務器隊列中的等待時間。具體來講,這種消息批量打包機制由消息推送和消息發送機制兩方面組成:

      BYPSS 提供了消息批量發送接口,可在一次請求中同時提交數以百萬計的消息發送操做,從而大大提高了消息處理效率和網絡利用率。另外一方面,BYPSS 服務器也實現了消息批量打包推送機制:若某節點發生消息浪涌,針對該節點的消息大量到達並堆積在服務器端消息隊列中。則 BYPSS 服務器會自動開啓批量消息推送模式——將大量消息打包成一次網絡請求,批量推送至目的節點。

      經過上述的批量處理機制,BYPSS 服務可大大提高消息處理和網絡利用效率,確保在大部分狀況下,其服務器端消息隊列基本爲空,所以就進一步下降了其主服務器節點掉線時,發生消息丟失的機率。

      然而,雖然消息丟失的機率極低,而且 μSOA 架構先天就不怎麼須要依賴消息中間件提供的可靠性保證。但仍然可能存在極少數對消息傳遞要求很高的狀況。對於此類狀況,可選擇使用下列解決方案:
       
      • 自行實現回執和超時重傳機制:消息發送方對指定端口發送消息,並等待接收該消息處理回執。若在指定時段內未收到回執,則從新發送請求。
         
      • 直接向消息端口的屬主節點發起 RPC 請求:消息發送方經過端口查詢命令獲取該端口屬主節點的IP地址等信息,並直接與該屬主節點創建鏈接、提交請求並等待其返回處理結果。BYPSS 在此過程當中僅擔當服務選舉和發現的角色,並不直接路由消息。對於視頻推流和轉碼、深度學習等有大量數據流交換的節點間通訊,也建議使用此方式,以避免 BYPSS 成爲 IO 瓶頸。
         
      • 使用第三方的可靠消息中間件產品:若須要保證可靠性的消息投遞請求較多,規則也較複雜,也可單獨搭建第三方的可靠消息分發集羣來處理這部分請求。

綜上所述,能夠認爲 BYPSS 服務就是爲 μSOA 架構量身定作的集羣協調和消息分發服務。BYPSS 和 μSOA 架構之間造成了揚長避短的互補關係:BYPSS 以極端條件下系統總體性能的輕微波動爲代價,極大提高了系統的整體性能表現。適合用來實現高效率、高可用、高可靠、強一致的 μSOA 架構分佈式系統。

 

BYPSS特性總結

BYPSS 和基於 Paxos、Raft 等傳統分佈式一致性算法的分佈式協調產品特性對好比下:

特性 BYPSS ZooKeeper、Consul、etcd…
可用性 高可用,支持多活 IDC 高可用,支持多活 IDC
一致性 強一致,主節點經過多數派選舉 強一致,多副本複製
併發性 千萬量級併發鏈接,可支持數十萬併發節點 不超過 5000 節點
容量 每 10GB 內存可支持約 1 億消息端口;每 1TB 內存可支持約 100 億消息端口;兩級併發散列表結構確保容量可線性擴展至 PB 級。 一般最高支持數萬 KV 對。開啓了變動通知時則更少。
延遲 相同 IDC 內每次請求延遲在亞毫秒級(阿里雲中實測爲 0.5ms);相同區域內的不一樣 IDC 間每次請求延遲在毫秒級(阿里雲環境實測 2ms)。 因爲每次請求須要至少三次網絡廣播和屢次磁盤 IO,所以相同 IDC 中的每操做延遲在十幾毫秒左右;不一樣 IDC 間的延遲則更長(詳見下文)。
性能 每 1Gbps 網絡帶寬可支持約 400 萬次/秒的端口註冊和註銷操做。在 2013 年出廠的入門級至強處理器上,每核心可支持約 100 萬次/秒的上述端口操做。性能可經過增長帶寬和處理器核心數量線性擴展。 算法自己的特性決定了沒法支持批量操做,不到 100 次每秒的請求性能(因爲每一個原子操做都須要至少三次網絡廣播和屢次磁盤 IO,所以支持批量操做毫無心義,詳見下文)。
網絡利用率 高:服務器端和客戶端均具有端口註冊、端口註銷、消息發送的批量打包能力,網絡載荷比可接近 100%。 低:每請求一個獨立包(TCP Segment、IP Packet、Network Frame) ,網絡載荷比一般低於 5%。
可伸縮性 有:可經過級聯的方式進行橫向擴展。 無:集羣中的節點越多(由於廣播和磁盤IO的範圍更大)性能反而越差。
分區容忍 無多數派分區時系統下線,但不會產生廣播風暴。 無多數派分區時系統下線,有可能產生廣播風暴引起進一步網絡故障。
消息分發 有,高性能,客戶端和服務器均包含了消息的批量自動打包支持。 無。
配置管理 無,BYPSS 認爲配置類數據應交由 Redis、MySQL、MongoDB 等專門的產品來維護和管理。固然,這些 CMDB 的主從選舉等分佈式協調工做仍可由 BYPSS 來完成。 有,可看成簡單的 CMDB 來使用,這種功能和職責上的混淆不清進一步劣化了產品的容量和性能。
故障恢復 須要從新生成狀態機,但能夠數千萬至數億端口/秒的性能完成。實際使用中幾無波動。 不須要從新生成狀態機。

上述比較中,延遲和性能兩項主要針對寫操做。這是由於在常見的分佈式協調任務中,幾乎所有有意義的操做都是寫操做。例如:

操做 對服務協調來講 對分佈式鎖來講
端口註冊 成功:服務選舉成功,成爲該服務的屬主。
失敗:成功查詢到該服務的當前屬主。
成功:上鎖成功。
失敗:上鎖失敗,同時返回鎖的當前屬主。
端口註銷 放棄服務全部權。 釋放鎖。
註銷通知 服務已下線,可更新本地查詢緩存或參與服務競選。 鎖已釋放,可從新開始嘗試上鎖。

上表中,BYPSS 的端口註冊對應 ZooKeeper 等傳統分佈式產品中的「寫/建立KV對」;端口註銷對應「刪除KV對」;註銷通知則對應「變動通知」服務。

因而可知,爲了發揮最高效率,在生產環境中一般不會使用單純的查詢等只讀操做。而是將查詢操做隱含在端口註冊等寫請求中,請求成功則當前節點自身成爲屬主;註冊失敗天然會返回請求服務的當前屬主,所以變相完成了屬主查詢( 服務發現/名稱解析)等讀操做。

須要注意的是,就算是端口註冊等寫操做失敗,其實仍是會伴隨一個成功的寫操做。由於仍然要將發起請求的當前節點加入到指定條目的變動通知列表中,以便在端口註銷等變動事件發生時,向各個感興趣的節點推送通知消息。 所以寫操做的性能差別極大地影響了現實產品的實際表現。

 

基於 BYPSS 的高性能集羣

從高性能集羣(HPC)的視角來看,BYPSS 與前文所述的傳統分佈式協調產品之間,最大的區別主要體如今如下兩個方面:

  1. 高性能:BYPSS 經過消除網絡廣播、磁盤 IO 等開銷,以及增長批處理支持等多種優化手段使分佈式協調服務的總體性能提高了上萬倍。
     
  2. 大容量:約每 10GB 內存 1 億個消息端口的容量密度,因爲合理使用了併發散列表等數據結構,使得容量和處理性能可隨內存容量、處理器核心數量以及網卡速率等硬件升級而線性擴展。

因爲傳統分佈式協調服務的性能和容量等限制,在經典的分佈式集羣中,多以服務或節點做爲單位來進行分佈式協調和調度,同時儘可能要求集羣中的節點工做在無狀態模式。服務節點無狀態的設計雖然對分佈式協調服務的要求較低,但同時也帶來了集羣總體性能低下等問題。

與此相反,BYPSS 可輕鬆實現每秒千萬次請求的處理性能和百億至千億量級的消息端口容量。這就給分佈式集羣的精細化協做構建了良好的基礎。與傳統的無狀態集羣相比,基於 BYPSS 的精細化協做集羣可以帶來巨大的總體性能提高。

咱們首先以最多見的用戶和會話管理功能來講明:在無狀態的集羣中,在線用戶並沒有本身的屬主服務器,用戶的每次請求均被反向代理服務隨機地路由至集羣中的任意節點。雖然 LVS、Nginx、HAProxy、TS 等主流反向代理服務器均支持基於 Cookie 或 IP 等機制的節點粘滯選項,但因爲集羣中的節點都是無狀態的,所以該機制僅僅是增長了相同客戶端請求會被路由到某個肯定後臺服務器節點的機率而已,仍沒法提供全部權保證,也就沒法實現進一步的相關優化措施。

而得益於 BYPSS 突出的性能和容量保證,基於 BYPSS 的集羣能夠用戶爲單位來進行協調和調度(即:爲每一個活動用戶註冊一個端口),以提供更優的總體性能。具體的實現方式爲:

  1. 與傳統模式同樣,在用戶請求到達反向代理服務時,由反向代理經過 HTTP Cookie、IP 地址或自定義協議中的相關字段等方式來斷定當前請求應該被轉發至哪一臺後端服務器節點。若請求中尚無粘滯標記,則選擇當前負載最輕的一個後端節點來處理。
     
  2. 服務器節點在收到用戶請求後,在本地內存表中檢查該用戶的屬主是否爲當前節點。
     
    1. 若當前節點已經是該用戶屬主,則由此節點繼續處理用戶請求。
       
    2. 若當前節點不是該用戶的屬主,則向 BYPSS 發起 RegPort 請求,嘗試成爲該用戶的屬主。此請求應使用批量方式發起,以進一步提升網絡利用率和處理效率。
       
      1. 若 RegPort 請求成功,說明當前節點已成功獲取該用戶的全部權,此時可將用戶信息由後端數據庫加載到當前節點的本地緩存中(應使用批量加載優化),並繼續處理此用戶相關請求。
         
      2. 若 RegPort 請求失敗,說明指定用戶正歸於另外一個節點管轄,此時應從新設置反向代理可以識別的 Cookie 等粘滯字段,將其指向正確的屬主節點。並要求反向代理服務或客戶端重試請求。

與傳統架構相比,考慮到無狀態服務也須要經過 MySQL、Memcached 或 Redis 等技術來實現專門的用戶和會話管理機制,所以以上實現並未增長多少複雜度,可是其帶來的性能提高卻很是巨大,對好比下:

項目 BYPSS HPC 集羣 傳統無狀態集羣
1
運維
省去用戶和會話管理集羣的部署和維護成本。 須要單獨實施和維護用戶管理集羣,併爲用戶和會話管理服務提供專門的高可用保障,增長故障點、增長系統總體複雜性、增長運維成本。
2
網絡
幾乎全部請求的用戶匹配和會話驗證工做都得以在其屬主節點的內存中直接完成。內存訪問爲納秒級操做,對比毫秒級的網絡查詢延遲,性能提高十萬倍以上。同時有效下降了服務器集羣的內部網絡負載。 每次須要驗證用戶身份和會話有效性時,均須要經過網絡發送查詢請求到用戶和會話管理服務,並等待其返回結果,網絡負載高、延遲大。

因爲在一個典型的網絡應用中,大部分用戶請求都須要在完成用戶識別和會話驗證後才能繼續處理,所以這對總體性能的影響很大。
3
緩存
由於擁有了穩定的屬主服務器,而用戶在某個時間段內老是傾向於重複訪問相同或類似的數據(如自身屬性,本身剛剛發佈或查看的商品信息等)。所以服務器本地緩存的數據局部性強、命中率高。

相較於分佈式緩存而言,本地緩存的優點很是明顯:
  • 省去了查詢請求所需的網絡延遲,下降了網絡負載(詳見本表「項目2」中的描述)。
  • 直接從內存中讀取已展開的數據結構,省去了大量的數據序列化和反序列化工做。
與此同時,如能儘可能按照某些規律來分配用戶屬主,還可進一步地提高服務器本地緩存的命中率。例如:
  • 按租戶(公司、部門、站點)來分組用戶;
  • 按區域(地理位置、遊戲中的地圖區域)來分組用戶;
  • 按興趣特徵(遊戲戰隊、商品偏好)來分組用戶。

等等,而後儘可能將屬於相同分組的用戶優先分配給同一個(或同一組)服務器節點。顯而易見,選擇合適的用戶分組策略可極大提高服務器節點的本地緩存命中率。

這使得絕大部分與用戶或人羣相關的數據都可在本地緩存命中,不但提高了集羣總體性能,還消除了集羣對分佈式緩存的依賴,同時大大下降了後端數據庫的讀負載。
無專屬服務器,用戶請求隨機到達集羣中的任意服務器節點;本地緩存命中率低;各節點重複緩存的內容多;須要以更高的成本爲代價依賴分佈式緩存。

後端數據庫服務器的讀壓力高,要對其進行分庫分表、讀寫分離等額外優化。
4
更新
因爲全部權肯定,能在集羣全局確保任意用戶在給定時間段內,均由特定的屬主節點來提供服務。再加上現代服務器突發宕機故障的機率也較低。

所以能夠將用戶屬性中頻繁變化但重要性或時效性較低的部分緩存在內存中,待積累一段時間後再批量更新至數據庫。這可大大下降後端數據庫服務器的寫壓力。

例如:商城系統可能隨着用戶的瀏覽(好比每次查看商品)進程,隨時收集並記錄用戶的偏好信息。若每次用戶查看了新商品後,都須要即時更新數據庫,則負載較高。再考慮到由於服務器偶發硬件故障致使丟失最後數小時商品瀏覽偏好數據徹底能夠接受,所以可由屬主節點將這些數據臨時保存在本地緩存中,每積累數小時再批量更新一次數據庫。

再好比:MMORPG 遊戲中,用戶的當前位置、狀態、經驗值等數據隨時都在變化。屬主服務器一樣能夠將這些數據變化積累在本地緩存中,並以適當的間隔(好比:每 5 分鐘一次)批量更新到數據庫中。

這不但極大地下降了後端數據庫要執行的請求數量,並且將多個用戶的數據在一個批量事務中打包更新也大大減小數據庫操做時的磁盤刷新動做,進一步提高了效率。

此外,由專門的屬主節點發起對用戶屬性的更新也避免了無狀態集羣中多個節點同時請求更新同一對象時的爭搶問題,進一步提升了數據庫性能。
因爲用戶的每次請求均可能被轉發到不一樣服務器節點來處理,所以沒法實現累積寫入優化和批量寫入優化。後端數據庫的寫負擔很是重。

存在多個節點爭搶更新同一條記錄的問題,進一步加劇了數據庫負擔。

爲此要對後端數據庫進行額外的分庫分表等優化,還會引起「須要由應用層來自行處理分佈式事務」等反作用。
5
推送
因爲同一用戶發起的全部會話均被集中在同一個屬主節點內統一管理,所以可很是方便地向用戶推送即時通知消息(Comet)。

若發送消息的對象與消息接收消息的用戶處於相同節點,則可直接將該消息推送給收件人麾下的全部活動會話。

不然只需將消息定向投遞到收件人的屬主節點便可。消息投遞可以使用 BYPSS 實現(直接向收件人對應端口發消息,應啓用消息批量發送機制來優化),亦可經過專用的消息中間件(如:Kafka、RocketMQ、RabbitMQ、ZeroMQ等)來完成。

若按照本表「項目3」中描述的方法,優先將關聯更緊密的用戶分配到相同屬主節點的話,則可大大提高消息推送在相同節點內完成的機率,此舉可顯著下降服務器間通訊的壓力。

所以咱們鼓勵針對業務的實際狀況來妥善定製用戶分組策略,合理的分組策略可實現讓絕大部分消息都在當前服務器節點內本地推送的理想效果。

例如:對遊戲類應用,可按地圖對象分組,將處於相同地圖副本內的玩家交由同一屬主節點進行管理——傳統 MMORPG 網遊中的絕大部分消息推送都發生在同一地圖副本內的玩家之間(AOI 範圍)。

再好比:對於 CRM、HCM、ERP 等 SaaS 應用來講,可按照公司來分組,將隸屬於相同企業的用戶集中到同一屬主節點上——很顯然,此類企業應用中,近 100% 的通訊都來自於企業內部成員之間。

這樣便可實現近乎 100% 的本地消息推送,達到幾乎免除了服務器間消息投遞的效果,極大地下降了服務器集羣的內部網絡負載。
因爲同一用戶的不一樣會話被隨機分配到不一樣節點處理,所以須要開發、部署和維護專門的消息推送集羣,同時專門確保該集羣的高性能和高可用性。

這不但增長了開發和運維成本,並且因爲須要將每條消息先投遞到消息推送服務後,再由該服務轉發給客戶端,所以也加劇了服務器集羣的內部網絡負載,同時也加大了用戶請求的處理延遲。
6
平衡
集羣可以使用主被動負載平衡相結合的手段進行調度。

被動平衡:集羣中的每一個節點均會按期將其麾下再也不活躍的用戶和會話卸載掉,同時批量通知 BYPSS 服務釋放這些用戶所對應的端口。此算法實現了宏觀上的負載平衡(以較長的時間週期來講,集羣是平衡的)。

主動平衡:集羣會經過 BYPSS 服務推選出負載平衡協調節點,該節點連續監視集羣中各個節點的負載狀況,並主動發出指令進行負載調度(如:要求 A 節點將其麾下 5000 位用戶的全部權轉移給 B 節點)。不一樣於宏觀層面的被動平衡,主動平衡機制能夠在更短的時間片內,以迅捷的反應速度來達成集羣的快速配平。

主動平衡一般在集羣中的部分節點剛剛從故障中恢復(所以處於空載狀態)時效果明顯,它比被動平衡反應更加迅速。如:在一個多活 IDC 集羣中,某個 IDC 的光纜故障剛剛被修復而恢復上線時。
若啓用了反向代理中的節點粘滯選項,則其負載平衡性與 BYPSS 集羣的被動平衡算法至關。

若未啓用反向代理中的節點粘滯選項,則在從故障中恢復時,其平衡性低於 BYPSS 主動平衡集羣。與此同時,爲了保證本地緩存命中率等其它性能指標不被過度劣化,管理員一般不會禁用節點粘滯功能。

另外,SOA 架構的多個服務間,容易產生負載不平衡,出現一些服務超載,另外一些輕載的狀況,μSOA 集羣則無此弊端。

值得一提的是,這樣的精準協做算法並不會形成集羣在可用性方面的任何損失。考慮集羣中的某個節點因故障下線的狀況:此時 BYPSS 服務會檢測到節點已下線,並自動釋放屬於該節點的全部用戶。待其用戶向集羣發起新請求時,該請求會被路由到當前集羣中,負載最輕的節點。這個新節點將代替已下線的故障節點,成爲此用戶的屬主,繼續爲該用戶提供服務(見前文中的步驟 2-b-i)。此過程對用戶透明,不須要在客戶端中加入額外的處理邏輯。

上述討論以幾乎全部網絡應用中都會涉及的用戶和會話管理功能爲例,爲你們展現了 BYPSS HPC 集羣精細協調能力的優點。但在多數真實應用中,並不僅有用戶管理功能。除此以外,應用中一般還會包含可供其用戶操做的其它對象。例如在優酷、土豆、youtube 等視頻網站中,除了用戶之外,至少還有「可供播放的視頻」這種對象。

下面咱們就以「視頻對象」爲例,探討如何使用 BYPSS 的精細化調度能力來大幅提高集羣性能。

在這個假想的視頻點播類應用中,與前文描述的用戶管理功能相似,咱們首先經過 BYPSS 服務爲每一個活動的視頻對象選取一個屬主節點。其次,咱們將視頻對象的屬性分爲如下兩大類:

  1. 普通屬性:包含了那些較少更新,而且尺寸較小的屬性。如:視頻封面和視頻流數據在S3 / OSS等對象存儲服務中的ID、視頻標題、視頻簡介、視頻標籤、視頻做者UID、視頻發佈時間等等。這些屬性均符合讀多寫少的規律,其中大部分字段甚至在視頻正式發佈後就沒法再作修改。

    對於這類尺寸小、變化少的字段,能夠將其分佈在當前集羣中,各個服務器節點的本地緩存內。本地緩存有高性能、低延遲、無需序列化等優勢,加上緩存對象較小的尺寸,再配合用戶分組等進一步提高緩存局部性的策略,能夠合理的內存開銷,有效地提高應用總體性能(詳見下文)。
     
  2. 動態屬性:包含了全部須要頻繁變動,或尺寸較大的屬性。如:視頻的播放次數、點贊次數、差評次數、平均得分、收藏數、引用次數,以及視頻討論區內容等。

    咱們規定這類尺寸較大(討論區內容)或者變化較快(播放次數等)的字段只能由該視頻對象的屬主節點來訪問。其它非屬主節點如需訪問這些動態屬性,則須要將相應請求提交給對應的屬主節點來進行處理。

    意即:經過BYPSS的全部權選舉機制,咱們將那些須要頻繁變動(更新數據庫和執行緩存失效),以及那些佔用內存較多(重複緩存代價高)的屬性都交給對應的屬主節點來管理和維護。這就造成了一套高效的分佈式計算和分佈式緩存機制,大大提高了應用總體性能(詳見下文)。

此外,咱們還規定對視頻對象的任何寫操做(無論是普通屬性仍是動態屬性)均必須交由其屬主來完成,非屬主節點只能讀取和緩存視頻對象的普通屬性,不能讀取動態屬性,也不能執行任何更新操做。

由此,咱們能夠簡單地推斷出視頻對象訪問的大致業務邏輯以下:

  1. 在普通屬性的讀取類用戶請求到達服務器節點時,檢查本地緩存,若命中則直接返回結果,不然從後端數據庫讀取視頻對象的普通屬性部分並將其加入到當前節點的本地緩存中。
     
  2. 在更新類請求或動態屬性讀取類請求到達服務器節點時,經過本地內存表檢查當前節點是否爲對應視頻對象的屬主。
     
    1. 若當前節點已經是該視頻的屬主,則由當前節點繼續處理用戶請求:讀操做直接從當前節點的本地緩存中返回結果;寫操做視情形累積在本地緩存中,或直接提交給後端數據庫並更新本地緩存。
       
    2. 若當前節點不是該視頻的屬主,但在當前節點的名稱解析緩存表中找到了與該視頻匹配的條目,則將當前請求轉發給對應的屬主節點。
       
    3. 若當前節點不是該視頻的屬主,同時並未在當前節點的名稱解析緩存表中查找到對應的條目,則向 BYPSS 發起 RegPort 請求,嘗試成爲該視頻的屬主。此請求應使用批量方式發起,以進一步提升網絡利用率和處理效率。
       
      1. 若 RegPort 請求成功,說明當前節點已成功獲取該視頻的全部權,此時可將視頻信息由後端數據庫加載到當前節點的本地緩存中(應使用批量加載優化),並繼續處理此視頻相關請求。
         
      2. 若 RegPort 請求失敗,說明指定視頻對象正歸於另外一個節點管轄,此時可將該視頻及其對應的屬主節點ID加入到本地名稱解析緩存表中,並將請求轉發給對應的屬主節點來處理。

        注意:因爲 BYPSS 可以在端口註銷時(不管是因爲屬主節點主動放棄全部權,仍是該節點故障宕機),向全部對此事件感興趣的節點推送通知。所以名稱解析緩存表不須要相似 DNS 緩存的 TTL 超時淘汰機制,僅需在收到端口註銷通知或 LRU 緩存滿時刪除對應條目便可。這不但可以大大加強查詢表中條目的時效性和準確性,同時也有效地減小了 RegPort 請求的發送次數,提升了應用的總體性能。

與經典的無狀態 SOA 集羣相比,上述設計帶來的好處以下:

項目 BYPSS HPC 集羣 傳統無狀態集羣
1
運維
基於全部權的分佈式緩存架構,省去 Memcached、Redis 等分佈式緩存集羣的部署和維護成本。 須要單獨實施和維護分佈式緩存集羣,增長系統總體複雜性。
2
緩存
普通屬性的讀操做在本地緩存命中,若使用「優先以用戶偏好特徵來分組」的用戶屬主節點分配策略,則可極大加強緩存局部性,增長本地緩存命中率,下降本地緩存在集羣中各個節點上的重複率。

正如前文所述,相對於分佈式緩存而言,本地緩存有消除網絡延遲、下降網絡負載、避免數據結構頻繁序列化和反序列化等優勢。

此外,動態屬性使用基於全部權的分佈式緩存來實現,避免了傳統分佈式緩存的頻繁失效和數據不一致等問題。同時因爲動態屬性僅被緩存在屬主節點上,所以也顯著提高了系統總體的內存利用率。
無專屬服務器,用戶請求隨機到達集羣中的任意服務器節點;本地緩存命中率低;各節點重複緩存的內容多;須要以更高的成本爲代價依賴額外的分佈式緩存服務。

後端數據庫服務器的讀壓力高,要對其實施分庫分表、讀寫分離等額外優化。

此外,即便爲 Memcached、Redis 等產品加入了基於 CAS 原子操做的 Revision 字段等改進,這些獨立的分佈式緩存集羣仍沒法提供數據強一致保證(意即:緩存中的數據與後端數據庫裏的記錄沒法避免地可能發生不一致)。
3
更新
因爲全部權肯定,能在集羣全局確保任意視頻對象在給定時間段內,均由特定的屬主節點來提供寫操做和動態屬性的讀操做等相關服務,再加上現代服務器突發宕機故障的機率也較低。

所以能夠將動態屬性中頻繁變化但重要性或時效性較低的部分緩存在內存中,待積累一段時間後再批量更新至數據庫。這可大大下降後端數據庫服務器的寫壓力。

例如:視頻的播放次數、點贊次數、差評次數、平均得分、收藏數、引用次數等屬性都會隨着用戶點擊等操做密集地變化。若每次發生相關的用戶點擊事件後,都須要即時更新數據庫,則負載較高。而在發生「屬主節點因爲硬件故障宕機」等極端狀況時,丟失幾分鐘的上述統計數據徹底能夠接受。所以,咱們能夠將這些字段的變動積累在屬主節點的緩存中,每隔數分鐘再將其統一地批量寫回後端數據庫。

這不但極大地下降了後端數據庫收到的請求數量,並且將多個視頻的數據在一個批量事務中打包更新,也大大減小數據庫操做時的磁盤刷新動做,進一步提高了效率。

此外,由專門的屬主節點單獨發起對視頻記錄的更新也避免了無狀態集羣中多個節點同時請求更新同一對象時的爭搶問題,進一步提升了數據庫性能。
因爲每次請求均可能被路由到不一樣服務器節點來處理,所以沒法實現累積寫入優化和批量寫入優化。後端數據庫服務器的寫負擔很是重。存在多個節點爭搶更新同一條記錄的問題,這進一步加劇了數據庫負擔。

爲此要對後端數據庫進行額外的分庫分表等優化,還會引起「須要由應用層來自行處理分佈式事務」等反作用。
4
平衡
集羣可以使用主被動負載平衡相結合的手段進行調度。

被動平衡:集羣中的每一個節點均會按期將其麾下再也不活躍的視頻對象卸載掉,同時批量通知 BYPSS 服務釋放這些視頻對應的端口。此算法實現了宏觀上的負載平衡(以較長的時間週期來講,集羣是平衡的)。

主動平衡:集羣會經過 BYPSS 服務推選出負載平衡協調節點,該節點連續監視集羣中各個節點的負載狀況,並主動發出指令進行負載調度(如:要求 A 節點將其麾下 10000 個視頻對象的全部權轉移給 B 節點)。不一樣於宏觀層面的被動平衡,主動平衡機制能夠在更短的時間片內,以迅捷的反應速度來達成集羣的快速配平。

主動平衡一般在集羣中的部分節點剛剛從故障中恢復(所以處於空載狀態)時效果明顯,它比被動平衡反應更加迅速。如:在一個多活 IDC 集羣中,某個 IDC 的光纜故障剛剛被修復而恢復上線時。
在從故障中恢復時,其平衡性低於 BYPSS 主動平衡集羣。正常狀況下則相差不大。

另外,SOA 架構的多個服務間,容易產生負載不平衡,出現一些服務超載,另外一些輕載的狀況,μSOA集羣則無此弊端。

與前文說起的用戶管理案例相似,上述精準協做算法不會爲集羣的服務可用性方面帶來任何損失。考慮集羣中的某個節點因故障下線的狀況:此時 BYPSS 服務會檢測到節點已下線,並自動釋放屬於該節點的全部視頻對象。待用戶下次訪問這些視頻對象時,收到該請求的服務器節點會從 BYPSS 得到此視頻對象的全部權並完成對該請求的處理。至此,這個新節點將代替已下線的故障節點成爲此視頻對象的屬主(見前文中的步驟 2-c-i)。此過程對用戶透明,不須要在客戶端中加入額外的處理邏輯。

以上對「用戶管理」和「視頻服務」案例的剖析均屬拋磚引玉。在實際應用中,BYPSS 經過其高性能、大容量等特徵提供的資源精細化協調能力可適用於包括互聯網、電信、物聯網、大數據批處理、大數據流式計算等普遍領域。

咱們之後還會陸續增長更多實用案例,以供你們參考。

 

testtesttesttest 20190304 更新記錄測試(for 呂老師)

更新測試:2019-3-3 阿里雲由於 io hang 大面積宕機。

 

注:本文節選自《白楊應用支撐平臺》中的「5.4 μSOA 基礎庫-libapidbc」小節。

注2:以上所述 μSOA 架構和 BYPSS 分佈式協調算法均受到多項國家和國際發明專利保護。

相關文章
相關標籤/搜索