公司用的架構,在此找了資料作為記錄復看所用: 什麼是Service Mesh? Service Mesh的概念最早是由Buoyant公司的CEO William Morgan在一篇文章里提出,他給出的服務網格的定義是: A service mesh is a dedicated infrastruc ...
公司用的架構,在此找了資料作為記錄復看所用:
什麼是Service Mesh?
Service Mesh的概念最早是由Buoyant公司的CEO William Morgan在一篇文章里提出,他給出的服務網格的定義是:
A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.
Service Mesh是一種新型的用於處理服務與服務之間通信的技術,尤其適用以雲原生應用形式部署的服務,能夠保證服務與服務之間調用的可靠性。在實際部署時,Service Mesh通常以輕量級的網路代理的方式跟應用的代碼部署在一起,從而以應用無感知的方式實現服務治理。
Service Mesh以輕量級的網路代理的方式與應用的代碼部署在一起,用於保證服務與服務之間調用的可靠性,這與傳統的微服務架構有著本質的區別,這麼做主要是出於兩個原因。
1.跨語言服務調用的需要。在大多數公司內通常都存在多個業務團隊,每個團隊業務所採用的開發語言一般都不相同,以微博的業務為例,移動服務端的業務主要採用的是PHP語言開發,API平臺的業務主要採用的是Java語言開發,移動服務端調用API平臺使用的是HTTP請求,如果要進行服務化,改成RPC調用,就需要一種既支持PHP語言又支持支持Java語言的的服務化框架。
2.雲原生應用服務治理的需要。在微服務越來越多開始容器化,並使用Kubernetes類似的容器平臺對服務進行管理,逐步朝雲原生應用的方向進化。而傳統的服務治理要求在業務代碼里集成服務框架的SDK,這顯然與雲原生應用的理念相悖,因此迫切需要一種對業務代碼無侵入的適合雲原生應用的服務治理方式。
在這種背景下,Buoyant公司開發的第一代Service Mesh產品Linkerd應運而生。從下圖中可以看到,服務A要調用服務B,經過Linkerd來代理轉發,服務A和服務B的業務代碼不需要關心服務框架功能的實現。為此Linkerd需要具備負載均衡、熔斷、超時重試、監控統計以及服務路由等功能。這樣的話,對於跨語言服務調用來說,即使服務消費者和服務提供者採用的語言不同,也不需要集成各自語言的SDK。
(圖片來源:https://linkerd.io/images/[email protected])
而對於雲原生應用來說,可以在每個服務部署的實例上,都同等的部署一個Linkerd實例。比如下麵這張圖,服務A要想調用服務B,首先調用本地的Linkerd實例,經過本地的Linked實例轉發給服務B所在節點上的Linkerd實例,最後再由服務B本地的Linkerd實例把請求轉發給服務B。這樣的話,所有的服務調用都得經過Linkerd進行代理轉發,所有的Linkerd組合起來就像一個網格一樣,這也是為什麼我們把這項技術稱為Service Mesh,也就是“服務網格”的原因。
(圖片來源:https://buoyant.io/wp-content/uploads/2017/04/linkerd-service-mesh-diagram-1024x587.png)
Service Mesh的實現原理
Service Mesh實現的關鍵就在於兩點:一個是上面提到的輕量級的網路代理也叫SideCar,它的作用就是轉發服務之間的調用;一個是基於SideCar的服務治理也被叫作Control Plane,它的作用是向SideCar發送各種指令,以完成各種服務治理功能。下麵我就來詳細講解這兩點是如何實現的。
1.SideCar
我們首先來看一下,在傳統的微服務架構下服務調用的原理。你可以看下麵這張圖,服務消費者這邊除了自身的業務邏輯實現外,還需要集成部分服務框架的邏輯,比如服務發現、負載均衡、熔斷降級、封裝調用等,而服務提供者這邊除了實現服務的業務邏輯外,也要集成部分服務框架的邏輯,比如線程池、限流降級、服務註冊等。
而在Service Mesh架構中,服務框架的功能都集中實現在SideCar里,併在每一個服務消費者和服務提供者的本地都部署一個SideCar,服務消費者和服務提供者只管自己的業務實現,服務消費者向本地的SideCar發起請求,本地的SideCar根據請求的路徑向註冊中心查詢,得到服務提供者的可用節點列表後,再根據負載均衡策略選擇一個服務提供者節點,並向這個節點上的SideCar轉發請求,服務提供者節點上的SideCar完成流量統計、限流等功能後,再把請求轉發給本地部署的服務提供者進程,從而完成一次服務請求。整個流程你可以參考下麵這張圖。
我們可以把服務消費者節點上的SideCar叫作正向代理,服務提供者節點上的SideCar叫作反向代理,那麼Service Mesh架構的關鍵點就在於服務消費者發出的請求如何通過正向代理轉發以及服務提供者收到的請求如何通過反向代理轉發。從我的經驗來看,主要有兩種實現方案。
- 基於iptables的網路攔截。這種方案請見下圖,節點A上服務消費者發出的TCP請求都會被攔截,然後發送給正向代理監聽的埠15001,正向代理處理完成後再把請求轉發到節點B的埠9080。節點B埠9080上的所有請求都會被攔截發送給反向代理監聽的埠15001,反向代理處理完後再轉發給本機上服務提供者監聽的埠9080。
- 採用協議轉換的方式。這種方案請見下圖,節點A上的服務消費者請求直接發給正向代理監聽的埠15001,正向代理處理完成後,再把請求轉發到節點B上反向代理監聽的埠15001,反向代理處理完成後再發送給本機上的服務提供者監聽的埠9080。
可見,這兩種方案最大的不同之處在於,一個是通過iptables網路攔截實現代理轉發的,一個是靠直接把請求發送給代理來轉發的。基於iptables網路攔截的方式,理論上會有一定的性能損耗,但它的優點是從網路層實現調用攔截,能做到完全的業務無感知,所以適合雲原生應用。而直接把請求發送給代理的方式,要求代理層加入業務邏輯,才能把請求轉發給對應的服務提供者監聽的埠。
2.Control Plane
既然SideCar能實現服務之間的調用攔截功能,那麼服務之間的所有流量都可以通過SideCar來轉發,這樣的話所有的SideCar就組成了一個服務網格,再通過一個統一的地方與各個SideCar交互,就能控制網格中流量的運轉了,這個統一的地方就在Sevice Mesh中就被稱為Control Plane。如下圖所示,Control Plane的主要作用包括以下幾個方面:
-
服務發現。服務提供者會通過SideCar註冊到Control Plane的註冊中心,這樣的話服務消費者把請求發送給SideCar後,SideCar就會查詢Control Plane的註冊中心來獲取服務提供者節點列表。
-
負載均衡。SideCar從Control Plane獲取到服務提供者節點列表信息後,就需要按照一定的負載均衡演算法從可用的節點列表中選取一個節點發起調用,可以通過Control Plane動態修改SideCar中的負載均衡配置。
-
請求路由。SideCar從Control Plane獲取的服務提供者節點列表,也可以通過Control Plane來動態改變,比如需要進行A/B測試、灰度發佈或者流量切換時,就可以動態地改變請求路由。
-
故障處理。服務之間的調用如果出現故障,就需要加以控制,通常的手段有超時重試、熔斷等,這些都可以在SideCar轉發請求時,通過Control Plane動態配置。
-
安全認證。可以通過Control Plane控制一個服務可以被誰訪問,以及訪問哪些信息。
-
監控上報。所有SideCar轉發的請求信息,都會發送到Control Plane,再由Control Plane發送給監控系統,比如Prometheus等。
-
日誌記錄。所有SideCar轉發的日誌信息,也會發送到Control Plane,再由Control Plane發送給日誌系統,比如Stackdriver等。
-
配額控制。可以在Control Plane里給服務的每個調用方配置最大調用次數,在SideCar轉發請求給某個服務時,會審計調用是否超出服務對應的次數限制。