1. 程式人生 > >分散式服務框架選型:面對Dubbo,阿里巴巴為什麼選擇了HSF?

分散式服務框架選型:面對Dubbo,阿里巴巴為什麼選擇了HSF?

阿里巴巴集團內部使用的分散式服務框架 HSF(High Speed Framework,也有人戲稱“好舒服”)已經被很多技術愛好者所熟知,目前已經支撐著近 2000 多個應用的執行。

其對應早期的開源專案 Dubbo(因為某些原因,Dubbo 專案在 2012 年年底,阿里巴巴就停止了對此開源專案的更新),則更是在網際網路領域有著非常高的知名度和廣泛的使用。

本文通過對阿里巴巴 HSF 服務框架的介紹,讓大家能對這類分散式服務框架架構設計、執行原理,以及如何實現作為一個 SOA 架構需要滿足的各個特性有一個清晰的認識。

HSF 服務框架主要元件

1、服務提供者

群部署。

每一個 HSF 的應用均是以 War 包的形式存在,執行在阿里巴巴優化定製後的 Tomcat 容器中,在 Tomcat 容器層已經集成了 HSF 服務框架對服務提供者或服務呼叫者進行配置伺服器發現、服務註冊、訂閱、失效轉移等相關功能,所以不管是在服務提供者還是呼叫者開發時,只需要進行服務相關的配置操作,應用中無需引入任何 HSF 相關的 Jar 依賴包。

考慮到應用故障的隔離、更方便的服務管控,目前淘寶內部大部分應用的部署方式還是一個虛擬機器(對應一個作業系統)執行一個 Tomcat 容器,每個 Tomcat 執行一個服務應用,隨著近幾年以 Docker 容器技術的發展和流行,現在阿里巴巴內部也正在進行應用容器化部署的工作,讓伺服器的資源利用更加科學和高效。

2、服務呼叫者

作為服務的消費者,大多數也是以 WAR 應用包的方式執行在 Tomcat 容器中,在阿里巴巴集團內部也有一部分是基於 C/C++、PHP、Node.js 等語言開發的服務呼叫者。

3、地址伺服器

在 HSF 服務框架中,地址伺服器肩負著給服務提供者和服務呼叫者提供部署環境中所有配置伺服器和 Diamond 伺服器的伺服器列表資訊,是由 Nginx( 是一個高效能的 HTTP 和反向代理伺服器)提供該服務能力。

在部署 HSF 服務環境時,會將整個環境中的配置伺服器叢集(伺服器 IP 列表)和 Diamond 伺服器叢集資訊設定在地址伺服器上,在實際生產部署中,也會部署多臺地址伺服器提供負載均衡和高可用性的服務,服務提供者和呼叫者通過統一域名的方式訪問這些地址伺服器(比如“xxx.tbsite.net”),通過 DNS 輪詢實現地址伺服器訪問的高可用性。

4、配置伺服器

配置伺服器在 HSF 框架中主要負責記錄環境內所有服務釋出(服務提供者的 IP 地址和服務埠資訊)和服務訂閱(服務呼叫者的 IP 地址和服務埠資訊)資訊,並將服務相關資訊推送到服務節點上。為了追求服務釋出和訂閱的推送效率,所有的服務釋出和訂閱資訊均是儲存在記憶體中。

配置伺服器與所有服務者提供者和呼叫者均是長連線,採用心跳的方式可監控到各服務執行節點的狀況,一旦出現服務提供者服務節點出現故障時,會自動推送更新後(將出問題的服務提供者服務節點資訊從列表中刪除)的服務提供者列表給相關的服務呼叫者端。

在生產環境中,會部署多臺配置伺服器,用於服務釋出、訂閱、推送的負載均衡,在多臺配置伺服器間會進行實時的資料同步,保證服務釋出和訂閱資訊儘快能同步到各服務節點上。

某種程度上,配置伺服器在 HSF 框架中扮演了服務呼叫排程的指揮官,通過給服務呼叫者端推送不同的服務提供者列表就可以輕易的調整服務呼叫的路由,這一特性在淘寶平臺實現單元化(即某一客戶在訪問淘寶時,訪問請求一旦路由到某一個淘寶機房後,在淘寶上進行的所有業務的操作均可以在該機房完成,而無需訪問其他機房的服務,也是實現異地多活的基礎)、異地多活起到了至關重要的作用。

5、Diamond 伺服器

本質上,Diamond 伺服器是一個通用的統一配置管理服務,類似 ZooKeeper,給應用提供統一的配置設定和推送服務,使用場景非常廣泛,在阿里巴巴內部有很多的產品在需要進行配置的儲存和獲取時都會使用 Diamond 伺服器。

在 HSF 服務框架中,則主要承擔了服務呼叫過程中對於服務呼叫安全管控的規則、服務路由權重、服務 QPS 閥值等配置規則的儲存,所有的資訊均是持久化儲存到了後端的 MySQL 伺服器中,在生產環境中,會有多臺 Diamond 伺服器提供負載均衡的服務。

使用 Diamond 伺服器進行服務相關設定的典型場景如下:

  • 通過設定白名單(服務呼叫者所在服務節點 IP 地址)的方式設定某些服務或服務中的方法只能讓特定 IP 地址的伺服器呼叫;
  • 通過使用者認證的方式控制服務是否能夠呼叫;
  • 按照不同的伺服器權重設定服務呼叫者對多個服務提供者服務節點的訪問;
  • 設定某些服務的 QPS 能力上限值,一旦該服務的 QPS 達到該閥值,則拒絕服務的繼續呼叫,這也是實現服務限流的技術實現,在平臺進行大促或秒殺場景時,保障平臺的穩定的重要屏障。

通過這樣規則的設定,Diamond 除了將這些規則儲存在自身的資料庫中外,會自動將這些規則推送到相關的服務節點上(實際實現上是服務節點會定時從 Diamond 伺服器上同步相關配置資訊),使這些規則能立即在服務執行環境中生效。

如圖 3-5 所示是阿里巴巴 HSF 服務框架的工作原理,按照服務註冊釋出、服務訂閱、服務規則推送、最終服務提供者和服務呼叫者間的服務互動的順序說明了 HSF 服務框架中每個元件在整個框架中所扮演的角色。

服務框架

圖 3-5 HSF 服務框架工作原理示意圖

1)服務節點對配置伺服器列表的獲取。

服務呼叫者和服務提供者在隨著 Tomcat 容器啟動後,會以域名(比如“xxx.tbsite.net”)的方式獲取到可用的地址伺服器,通過向地址伺服器分別傳送獲取配置伺服器和 Diamond 伺服器服務 IP 列表請求的方式,在容器啟動完成後,就已經在該服務節點上獲取到了配置伺服器和 Diamond 伺服器的 IP 列表資訊。整個過程如圖 3-5 中的步驟①②。

2)服務的註冊釋出。

作為服務提供者,當獲取到配置伺服器的伺服器列表後,則向配置伺服器傳送當前應用中包含的服務提供者相關資訊(這些資訊均是從應用的配置檔案中獲取到,比如服務的介面類全名、服務版本、所屬服務組等資訊),聯同當前伺服器的 IP 地址、服務埠等資訊進行服務註冊釋出,如圖 3-5 中的步驟③。這個步驟在每一個有服務提供的應用啟動時都會自動執行,比如現在有 5 個提供同一服務的應用啟動後,此時在配置伺服器上就已經儲存了提供這一服務的 5 個伺服器相關資訊。

3)服務的訂閱。

當作為服務呼叫者的應用啟動時,同樣在完成配置伺服器列表的獲取後,就進行與配置伺服器的互動,傳送服務消費者相關資訊(同樣包含了服務的介面全名,服務版本、所屬服務組)到配置伺服器進行服務的訂閱,此時在配置伺服器上會通過服務介面全名+服務版本作為匹配條件在當前配置伺服器的記憶體中進行搜尋,一旦獲取到對應的服務註冊資訊,則將對應的服務提供者的伺服器組 IP 地址及埠返回給服務呼叫者所在的應用節點上,此時也就完成了服務呼叫者端對於它所需要呼叫的服務提供者伺服器列表資訊,用於在服務真正互動時使用。服務訂閱過程如圖 3-5 中的步驟④⑤。

4)服務規則的推送(如果需要)。

如果沒有上文提到對於服務安全管控、流量控制等需求的時候,對於 Diamond 伺服器的使用並不是必需的,在有這樣的需求場景時,可通過 Diamond 提供的規則設定介面,可以對指定服務的服務提供者和呼叫者設定相關的規則,一旦儲存規則後,則此規則配置將會在 5 秒內推送到與所設定服務相關的服務節點上。如圖 3-5 中的步驟⑥。

5)服務互動。

在應用進行業務請求處理過程中,出現了服務呼叫者對服務提供者的呼叫時,服務呼叫者會從已經儲存在該應用節點上的服務提供者伺服器列表中選擇(阿里巴巴內部使用隨機模式)其中一臺進行服務請求的傳送,服務互動期間完全是服務呼叫者和服務提供者間兩臺伺服器間的,無需通過中間伺服器的中轉,這就是相比於“中心化” ESB 模式,所有服務互動都需要“中心” ESB 進行服務路由,而當前這種架構稱為“去中心化”的主要原因。如圖 3-5 中的步驟⑦。

阿里巴巴的分散式服務框架核心是以服務化的方式構建整個應用體系的同時,要保證在高併發的情況下,服務具備高效互動、高可用性和擴充套件能力。接下來對於 HSF 框架如何給服務提供以上能力具體加以說明。

1、HSF 框架採用 Netty + Hession 資料序列化協議實現服務互動

HSF 框架中採用如今流行的網路通訊框架 Netty 加上 Hession 資料序列化協議實現 HSF 服務間的互動,主要考慮點是在大併發量時,服務互動效能達到最佳。這類 RPC 協議採用多路複用的 TCP 長連線方式,在服務提供者和呼叫者間有多個服務請求同時呼叫時會共用同一個長連線,即一個連線交替傳輸不同請求的位元組塊。它既避免了反覆建立連線開銷,也避免了連線的等待閒置從而減少了系統連線總數,同時還避免了 TCP 順序傳輸中的線頭阻塞(head-of-line blocking)問題。

Hessian 是 HSF 框架中預設使用的資料序列化協議,在資料量較小時效能表現出眾,Hessian 的優點是精簡高效,同時可以跨語言使用,目前支援 Java, C++,  .net, Python, ruby 等語言。另外 Hessian 可以充分利用 Web 容器的成熟功能,在處理大量使用者訪問時很有優勢,在資源分配、執行緒排隊、異常處理等方面都可以由 Web 容器保證。

HSF 框架同時也支援切換使用 Java 序列化,Hession 相比 JDK 標準的序列化方式(即基於 Serializable 介面的標準序列化),在典型場景中,其序列化時間開銷可能縮短 20 倍。雖然 Hessian 不是最快的序列化協議,但它對於複雜業務物件的序列化正確率、準確性相較於最穩定的 Java 序列化並不遜色太多。

業界還有一些比 Hessian 更快的序列化協議,但它們相對於 Hessian 在複雜場景下的處理能力還是會差一些,所以 Hessian 是在效能和穩定性同時考慮下最優的序列化協議。

阿里巴巴當時在對多種通訊協議和資料序列化元件等測試中,Netty + Hession 的組合在網際網路高併發量的場景下,特別是在 TPS 上達到 10w 以上時,效能和效率遠比 REST 或者 Web Service 高。

2、HSF 框架的容錯機制

因為要保證服務的高可用性,所以在生產環境部署中一定會有多個應用例項作為服務提供者提供某一相同服務。

基於之前所提到的服務框架的執行原理的說明,在進行服務呼叫時,服務呼叫者端已經儲存了它所需要呼叫的服務提供者的伺服器列表資訊(如圖 3-6 中為例,則儲存了三臺服務提供者所在伺服器的列表)。

當採用隨機方式獲取其中一臺進行服務互動時(如圖 3-6 步驟①),不管是第一臺伺服器已經某種故障造成了服務請求無法響應,還是該伺服器已經接收了服務請求,在進行服務請求處理過程中出現了伺服器故障(比如宕機、網路問題),造成該伺服器沒有在規定的時間(一般服務呼叫會設定到期時間)返回服務處理的結果,服務呼叫者端則會獲取到服務呼叫失敗的反饋(如圖 3-6 步驟②)。

在 HSF 服務呼叫的程式碼中會立即從剩下的服務提供者伺服器列表中選擇另外一個伺服器再次進行服務請求(如圖 3-6 步驟③),這一次這個服務提供者例項正常提供了此次服務的請求(如圖 3-6 步驟④),從而保證了在個別服務提供者出現故障時,完全不會影響該服務正常提供服務。

高可用

圖 3-6 HSF 服務框架實現服務高可用性原理示意圖

同時,因為配置伺服器是採用長連線的方式與服務節點進行網路通訊,一旦發現有服務提供者例項出現故障,配置伺服器在秒級就會感知到(如圖 3-6 步驟⑤),此時會將出問題這臺服務提供者的資訊從該服務的伺服器列表中刪除,並將更新後的伺服器列表採用推送的方式同步給與該服務相關的所有服務呼叫者端(如圖 3-6 步驟⑥),這樣當下次服務呼叫者再進行此服務的呼叫時,就不會因為隨機的方式再次對已經停止服務提供的伺服器發起服務的呼叫。

3、HSF 框架的線性擴充套件支援

作為 HSF 框架設計之初,最為重要的一個特性就是服務能力的可擴充套件性。也就是真正的做到某個服務的業務處理能力能隨著伺服器資源的增加得到線性的增長。

其實在傳統架構中一直也會強調平臺的擴充套件能力,但均會程度不一的出現服務節點數量到達一定量後,出現阻礙平臺服務能力擴充套件的問題,有的是出現網路傳輸的瓶頸、也有服務節點接入數量上的限制,前文所描述的 ESB 架構帶來的“雪崩”效應也均是這類架構給服務能力的擴充套件帶來影響的原因所在。

如圖 3-7 中所描述的場景,當服務面對較大的服務呼叫壓力或將要面臨如天貓雙11大促、秒殺等活動前,已有的服務提供者各伺服器水位(CPU、記憶體、IO等)處於比較高的情況或現有服務能力滿足不了業務訪問量的要求時,則需要通過增加服務節點數量的方式提升該服務的服務處理能力。

圖 3-7 HSF 服務框架對服務能力線性擴充套件支援1

此時,只需要通過增加該服務的服務提供者例項(如圖 3-8 所示,增加了一個服務),基於 HSF 框架的執行機制,新增加的服務提供者例項一旦應用啟動完成後,可在幾秒內開始進行服務請求的處理(主要完成服務註冊釋出、更新後服務列表推送到服務呼叫者端),從而達到分擔其他伺服器例項壓力的作用,實現服務能力整體水位恢復到正常的狀態(如圖 3-9)。

圖 3-8 HSF服務框架對服務能力線性擴充套件支援2

圖 3-9 HSF 服務框架對服務能力線性擴充套件支援3

正是基於 HSF 框架這一特性,從而真正實現了只要增加服務例項就能實現該服務能力擴充套件的目標,目前在阿里巴巴共享服務事業部中多個服務中心在天貓雙 11 那天各自所部署的服務例項節點數量均超過 2000,即同一個服務由超過 2000 個服務例項同時提供負載均衡的服務。

作者:鍾華(花名:古謙) 阿里巴巴中介軟體首席架構師,15 年中介軟體領域行業經驗。

文章來自微信公眾號:高可用架構