轉自 https://blog.csdn.net/panyongcsd/article/details/58617810
公司(VIP)從2015年開始在內部推動Venus框架的使用,這是一款基於Apache Thrift遠程調用框架二次開發的高性能、高可擴展的、服務治理的RPC框架。服務端使用IDL進行服務的定義,客戶端集成服務的SDK即可調用服務端的服務,開發簡單,大部分的公共功能都在Proxy代理層工作,減輕了開發者的負擔,使其只需要關注業務部分。下面是對該框架的基本原理的簡單介紹。
參考文獻:
1. Apache Thrift - 可伸縮的跨語言服務開發框架
2. 公司內部的Venux文檔(內網文檔,無法分享)
一、Thrift簡介
Thrift采用接口描述語言定義並創建服務,支持可擴展的跨語言服務開發,使用代碼生成引擎可以在多種語言之中創建高效、無縫的服務,采用二進制格式進行數據的傳輸,相對於xml和json體積更小,對於高並發、大數據量的環境更有優勢。
1. Hello World示例
Hello.thrift
namespace java service.demo service Hello{ string helloString(1:string para) i32 helloInt(1:i32 para) bool helloBoolean(1:bool para) void helloVoid() string helloNull() }
這段IDL定義了服務的名稱和五個方法,Thrift是對IDL的一種具體實現,使用Thrift的工具編譯該idl文件,就會生成相應的Hello.java文件。該文件包含了在Hello.thrift文件中描述的服務Hello的接口定義,即Hello.Iface接口,以及服務調用的底層通信細節,包括客戶端的餓調用邏輯Hello.Client以及服務端的處理邏輯Hello.Processor,用於構建客戶端和服務端的功能。
創建HelloServiceImpl.java文件並實現Hello.java文件中的Hello.Iface接口,代碼:
package service.demo; import org.apache.thrift.TException; public class HelloServiceImpl implements Hello.Iface { @Override public boolean helloBoolean(boolean para) throws TException { return para; } @Override public int helloInt(int para) throws TException { try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } return para; } @Override public String helloNull() throws TException { return null; } @Override public String helloString(String para) throws TException { return para; } @Override public void helloVoid() throws TException { System.out.println("Hello World"); } }
- Thrift架構
架構圖如下:
圖中黃色部分是用戶的業務代碼,褐色部分是編譯工具生成的代碼框架,紫色部分和藍色部分是我們所選擇的傳輸層和傳輸協議。
Thrift服務器包含用於綁定協議和傳輸層的基礎架構,它提供阻塞、非阻塞、單線程和多線程的模式運行在服務器上。 - 傳輸協議
Thrift可以讓用戶選擇客戶端和服務端之間的傳輸通信協議的類別,分為文本(text)和二進制(binary)。
- TBinaryProtocol:二進制編碼格式進行數據傳輸
- TCompactProtocol:高效率的密集的二進制編碼協議
- TJSONProtocol:使用Json的數據編碼協議
- TSimpleJSONProtocol:只提供Json讀寫的協議,適用於腳本語言解析
- 傳輸層
- TSocket:使用阻塞式IO進行傳輸
- TFramedTransport:非阻塞方式,按塊的大小進行傳輸,類似NIO;服務器必須為非阻塞的服務類型
- TNonblockingTransport:非阻塞模式,用於構建異步客戶端
- 服務端類型
- TSimpleServer:單線程服務器,阻塞IO
- TThreadPoolServer:多線程服務器,阻塞式IO
- TNonblockingServer:多線程服務器,非阻塞IO
二、Venus的配置中心
配置中心實現了集中配置、主動推送、規范配置、配置可讀等優點。
三、OSP詳解
開放服務平台(venus-osp)是Venus體系的核心組成部分之一, 主要目標是提供服務化的核心遠程調用機制以及基礎服務治理功能。契約化的服務接口保證系統間的解耦清晰、干凈;基於Thrift的通信和協議層確保系統的高性能;服務可以自動注冊並被發現,易於部署;配合配置中心,服務配置可以動態更新;客戶端與治理邏輯的分離使服務接入得到極大簡化;除此之外,OSP提供了豐富的服務治理能力,如路由、負載均衡、服務保護和優雅降級等。
1. 遠程調用機制
OSP是一套高性能、高可擴展的遠程過程調用(RPC)框架,基於Apache Thrift作為基本框架,采用Thrift的 工作模式。
每個客戶端機器上都運行這一個proxy進程,該進程會將客戶端的調用請求進行轉發,優先轉發到同機器的服務層、其次是同機房的服務、如果本機的proxy出現問題,會使用中央代理集群進行備份替換;
客戶端在請求的時候和proxy保持長連接,proxy和服務容器保持長連接,從而獲得服務容器中的服務的動態信息,如機器的健康狀況、配置信息、新增機器等。
2. 服務協議(OSP Protocol)
OSP采用了基於二進制的通訊協議,以消息為基本通訊單元;每條消息包含消息頭和消息體。協議設計上以無狀態為原則,每條消息包含調用所需的所有信息,一次調用通過一次消息交換(請求/響應)完成。
3. 服務提供方(服務端)
- 服務端包含服務容器和服務本身。服務容器集中管理共享功能;服務本身以業務邏輯為主;
- OSP服務端容錯基於無狀態服務的理念,服務實例之間互不感知,通過代理層的錯誤感知和負載均衡等功能自動摘除有問題的服務器;
- 每個服務啟動時,首先從配置中心獲取配置,然后將自己的信息(ID、地址和端口)注冊到服務注冊中心;服務代理層(Proxy)從注冊中心獲取當前服務提供方的所有實例,通過設定的負載均衡策略對服務進行調用。
4. 服務代理層(OSP-Proxy)
Proxy集中了絕大部分的服務治理智能,可以說是遠程調用的大腦。
- Proxy部署在每台服務器上,已進程的方式運行,客戶端將請求發送到Proxy進程,Proxy根據服務治理邏輯(負載均衡、路由等)對請求進行處理(轉發、降級或拒絕),這樣使服務治理的實現保持對客戶端和服務端的完全透明,且動態可控。
- 出於容錯考慮,每個IDC(機房)都會部署一個Proxy集群作為備用,當本機Proxy出現故障時,自動切換到備用Proxy集群。
5. 服務治理
這里的所謂服務治理主要集中在對負載均衡,路由選擇以及自我保護等領域所提供的功能以及靈活性。
- 負載均衡:OSP的負載均衡功能由osp-proxy提供,目前支持Least Active First, RR,Random等多種負載均衡策略;通過與配置中心集成,策略可以動態變更;另外,在支持基本服務端健康度檢測(如ping)的基礎上,利用對豐富的服務信息的統計(調用流量、延遲、錯誤率等),可以提供更加智能的健康檢測機制。
- 路由選擇:服務路由決定一個服務請求是否應該得到處理,以及由哪一個服務實例處理。這部分是各種服務治理政策的執行地,是一個極為重要的模塊。大量的使用場景都可以結合服務路由來實現,如服務的上線/下線,在線測試,機房選擇,A/B測試,灰度發布,流量控制,權限控制以及優雅降級等。
6. 服務管理
- 注冊:OSP通過服務容器加載啟動,服務容器需要從配置中心獲取服務的配置信息,服務容器根據獲取的參數,對服務進行初始化操作。服務啟動成功后,容器向服務注冊中心(Service Registry)進行注冊,系統記錄該服務的一個實例已經運行。服務容器與服務注冊中心保持長連接,當服務卸載或者服務容器故障退出時,服務注冊中心可以自動的刪除服務實例,維護最新有效的服務實例列表。
- 發現:當代理層需要調用一個服務時,代理層查詢服務注冊中心,獲取所需服務的全部服務實例,並結合服務路由策略(決定可以為當前服務請求提供服務的實例)及負載均衡策略(選擇那一個服務實例進行服務),選擇一個服務實例。代理層維護到服務注冊中心的長連接,這樣如果有新的服務實例或者老的服務實例失效時,代理層可以及時獲得最新的服務實例列表。與服務端不同,當代理層失去長連接后,仍然可以通過之前獲得的實例列表進行服務調用。
- 服務路由策略:OSP Proxy查詢服務注冊中心,獲取所需服務的全部服務實例列表,OSP Proxy選擇被調用的服務實列策略如下:
- 本地主機服務實例優先,OSP Proxy優先先擇與其部署在同一個主機上的服務實例;
- 同機房服務實例優先,OSP Proxy優先先擇與其部署在同機房主機上的服務實例,同機房的判斷條件:主機ipv4地址前兩段相同;
- 多個務服實例采用LeastActive(最少當前連接數,策略表示服務請求優先選擇最少操作的服務器進行請求處理)選擇服務實例進行。