由淺入深了解Thrift之微服務化應用架構

為什麼選擇微服務

一般情況下,業務應用我們都會採用模塊化的分層式架構,所有的業務邏輯代碼最終會在一個代碼庫中並統一部署,我們稱這種應用架構為單體應用。 單體應用的問題是,全部開發人員會共享一個代碼庫,不同模塊的邊界模糊,實現高內聚、松耦合極其困難。 肯定大家會碰到過這類場景,當嘗試去重構改進代碼時,改了一個地方好幾個其他模塊也需要同步改動, 當初劃分的模塊邊界輕易被穿透,有人給這種應用的架構起了一個很形象的名字叫 「洋蔥架構」。

Netflix是一家成功實踐微服務架構的互聯網公司,總結了一套行之有效的微服務方案。微服務架構強調 「微」,服務緊密圍繞業務領域,形成高度內聚的自治性。

更多的單體應用和微服務優劣勢請參看《微服務實戰(一):微服務架構的優勢與不足》。

微服務特徵

業務能力建模:高內聚、鬆散耦合,暴露介面而隱藏實現細節

服務協作模型:中心化和去中心化

服務交互方式:RPC/REST等

自動化文化與環境:自動化構建、自動化測試、自動化部署

服務發布:灰度發布

服務部署:部署獨立性、失敗隔離性、可監控性;一服務一主機模型需要虛擬化、容器化

服務配置:中心化配置服務

服務流控:降級、限流

服務恢復:多考慮故障如何快速恢復服務而非如何避免故障發生

當前業界比較成熟的微服務框架有Netflix的Karyon/Ribbon,Spring的Spring Boot/Cloud,阿里的Dubbo等。

Netflix的微服務框架

Netflix是一家成功實踐微服務架構的互聯網公司,幾年前,Netflix就把它的幾乎整個微服務框架棧開源貢獻給了社區,這些框架和組件包括:

  • Eureka: 服務註冊發現框架
  • Zuul: 服務網關
  • Karyon: 服務端框架
  • Ribbon: 客戶端框架
  • Hystrix: 服務容錯組件
  • Archaius: 服務配置組件
  • Servo: Metrics組件
  • Blitz4j: 日誌組件
  • 微服務框架

    1、服務註冊、服務發現、健康檢查

    如果我們採用進程內LB方案,那麼服務自註冊一般統一做在伺服器端框架中,健康檢查邏輯由具體業務服務定製,框架層提供調用健康檢查邏輯的機制,服務發現和負載均衡則集成在服務客戶端框架中。

    2、RPC/REST和序列化

    框架層要支持將業務邏輯以HTTP/REST或者RPC方式暴露出來,HTTP/REST是當前主流API暴露方式,在性能要求高的場合則可採用Binary/RPC方式。針對當前多樣化的設備類型(瀏覽器、普通PC、無線設備等),框架層要支持可定製的序列化機制,例如,對瀏覽器,框架支持輸出Ajax友好的JSON消息格式,而對無線設備上的Native App,框架支持輸出性能高的Binary消息格式。

    3、管理介面

    框架集成管理介面,一方面可以在線查看框架和服務內部狀態,同時還可以動態調整內部狀態,對調試、監控和管理能提供快速反饋。Spring Boot微框架的Actuator模塊就是一個強大的管理介面。對於框架層和服務的內部異常,如果框架層能夠統一處理並記錄日誌,對服務監控和快速問題定位有很大幫助。

    4、安全控制

    安全和訪問控制邏輯可以在框架層統一進行封裝,可做成插件形式,具體業務服務根據需要載入相關安全插件。

    5、配置管理

    除了支持普通配置文件方式的配置,框架層還可集成動態運行時配置,能夠在運行時針對不同環境動態調整服務的參數和配置。

    6、監控日誌

    框架一方面要記錄重要的框架層日誌、服務調用鏈數據,還要將日誌、調用鏈數據等介面暴露出來,讓業務層能根據需要記錄業務日誌數據。在運行環境中,所有日誌數據一般由日誌系統做進一步分析和處理。

    7、統一錯誤處理

    對於框架層和服務的內部異常,如果框架層能夠統一處理並記錄日誌,對服務監控和快速問題定位有很大幫助。

    8、流控和容錯

    框架集成限流容錯組件,能夠在運行時自動限流和容錯,保護服務,如果進一步和動態配置相結合,還可以實現動態限流和熔斷。

    負載均衡

    1、集中式的負載均衡方案

    在服務消費者和服務提供者之間有一個獨立的LB,LB通常是專門的硬體設備如F5,或者基於軟體如LVS,HAproxy等實現。LB上有所有服務的地址映射表,通常由運維配置註冊,當服務消費方調用某個目標服務時,它向LB發起請求,由LB以某種策略(比如Round-Robin)做負載均衡後將請求轉發到目標服務。LB一般具備健康檢查能力,能自動摘除不健康的服務實例。

    服務消費方如何發現LB呢?通常的做法是通過DNS,運維人員為服務配置一個DNS域名,這個域名指向LB。

    方案優缺點:

    1)、單點問題,所有服務調用流量都經過LB,當服務數量和調用量大的時候,LB容易成為瓶頸,且一旦LB發生故障對整個系統的影響是災難性的。

    2)、LB在服務消費方和服務提供方之間增加了一跳(hop),有一定性能開銷。

    2、進程內的負載均衡方案

    進程內LB方案將LB的功能以庫Library的形式集成到服務消費方進程裡頭,該方案也被稱為軟負載(Soft Load Balancing)或者客戶端負載方案。這一方案需要一個服務註冊表(Service Registry)配合支持服務自註冊和自發現,服務提供方啟動時,首先將服務地址註冊到服務註冊表(同時定期報心跳到服務註冊表以表明服務的存活狀態,相當於健康檢查),服務消費方要訪問某個服務時,它通過內置的LB組件向服務註冊表查詢(同時緩存並定期刷新)目標服務地址列表,然後以某種負載均衡策略選擇一個目標服務地址,最後向目標服務發起請求。這一方案對服務註冊表的可用性(Availability)要求很高,一般採用能滿足高可用分散式一致的組件(例如Zookeeper, Consul, Etcd等)來實現。

    方案優缺點:

    1)、是一種分散式方案,LB和服務發現能力被分散到每一個服務消費者的進程內部,同時服務消費方和服務提供方之間是直接調用,沒有額外開銷,性能比較好。

    但由於該方案以客戶庫(Client Library)的方式集成到服務調用方進程裡頭,

    2)、需要開發支持多種不同語言的客戶端,有一定的研發成本。

    3)、客戶庫Library跟隨服務調用方發布到生產環境中,後續如果要對客戶庫Library進行升級,會有很大的維護成本。

    阿里開源的服務框架Dubbo也是採用類似機制。

    3、主機獨立的負載均衡方案

    主機獨立LB進程方案,該方案是針對第二種方案的不足而提出的一種折中方案,原理和第二種方案基本類似,不同之處是,他將LB和服務發現功能從進程內移出來,變成主機上的一個獨立進程,主機上的一個或者多個服務要訪問目標服務時,他們都通過同一主機上的獨立LB進程做服務發現和負載均衡。

    方案優缺點:

    1)、是一種分散式方案,沒有單點問題,一個LB進程掛了隻影響該主機上的服務調用方,服務調用方和LB之間是進程內調用,性能好,同時,該方案還簡化了服務調用方,不需要為不同語言開發客戶庫,LB的升級不需要服務調用方改代碼。

    2)、不足是部署較複雜,環節多,出錯調試排查問題不方便。

    服務前端路由

    IDL+Nginx+AOP

    微服務除了內部相互之間調用和通信之外,最終要以某種方式暴露出去,才能讓外界系統(例如客戶的瀏覽器、移動設備等等)訪問到,這就涉及服務的前端路由,對應的組件是服務網關(Service Gateway)。

    服務網關service Gateway

    1、服務反向路由

    2、安全認證和防爬蟲

    3、限流和容錯

    4、監控

    5、日誌

    服務容錯

    當我們的業務逐漸複雜以後,服務之間的依賴關係也會有錯綜複雜,例如,一個前端請求一般會依賴於多個後端服務。由於,服務往往不是百分百可靠,服務可能會出錯或者產生延遲,如果一個應用不能對其依賴的故障進行容錯和隔離,那麼該應用本身就處在被拖垮的風險中。在一個高流量的網站中,某個單一後端一旦發生延遲,可能在數秒內導致所有應用資源(線程,隊列等)被耗盡,造成所謂的雪崩效應(Cascading Failure),嚴重時可致整個網站癱瘓。

    我們可以從不同的緯度避免和解決:

    服務設計:

    1、基礎服務

    2、複雜業務服務

    3、減少服務複雜的依賴,盡量保持簡單的依賴關係

    容錯設計:

    1、故障隔離、容錯

    2、降級、限流

    3、快速失敗(Fail Fast):直接拋出異常、可以返回空值或預設值

    (未完待續)

    推薦閱讀:

    手相中最重要的三根線,你了解多少?
    你必須了解的那些性事(圖)
    顧炎武的故事:一篇文章讓你全面了解顧炎武
    章子怡的老公汪峰你了解嗎?
    了解女人才能獲得女人的芳心

    TAG:架構 | 服務 | 了解 | Thrift |