當前位置:
首頁 > 科技 > 解析微服務架構組件,看這一篇文章就夠

解析微服務架構組件,看這一篇文章就夠


1. 如何發布和引用服務

服務描述:服務調用首先解決的問題就是服務如何對外描述。 常用的服務描述方式包括 RESTful API、XML 配置以及 IDL 文件三種。


RESTful API

主要被用作 HTTP 或者 HTTPS 協議的介面定義,即使在非微服務架構體系下,也被廣泛採用

優勢:HTTP 協議本身是一個公開的協議,對於服務消費者來說幾乎沒有學習成本,所以比較適合用作跨業務平台之間的服務協議。

劣勢:性能相對比較低


XML 配置

一般是私有 RPC 框架會選擇 XML 配置這種方式來描述介面,因為私有 RPC 協議的性能比 HTTP 協議高,所以在對性能要求比較高的場景下,採用 XML 配置比較合適。這種方式的服務發布和引用主要分三個步驟:

服務提供者定義介面,並實現介面

服務提供者進程啟動時,通過載入 server.xml 配置文件將介面暴露出去。

服務消費者進程啟動時,通過載入 client.xml 配置文件引入要調用的介面。

優勢:

私有 RPC 協議的性能比 HTTP 協議高,所以在對性能要求比較高的場景下,採用 XML 配置方式比較合適 劣勢:

對業務代碼侵入性比較高

XML 配置有變更的時候,服務消費者和服務提供者都要更新(建議:公司內部聯繫比較緊密的業務之間採用)


IDL 文件

IDL 就是介面描述語言(interface description language)的縮寫,通過一種中立的方式來描介面,使得在不同的平台上運行的對象和不同語言編寫的程序可以相互通信交流。常用的 IDL:一個是 Facebook 開源的 Thrift 協議,另一個是 Google 開源的 gRPC 協議。無論是 Thrift 協議還是 gRPC 協議,他們的工作原來都是類似的。

優勢:用作跨語言平台的服務之間的調用

劣勢:在描述介面定義時,IDL 文件需要對介面返回值進行詳細定義。如果介面返回值的欄位比較多,並且經常變化時,採用 IDL 文件方式的介面定義就不太合適了。

一方面會造成 IDL 文件過大難以維護

另一方面只要 IDL 文件中定義的介面返回值有變更,都需要同步所有的服務消費者都更新,管理成本太高了。


總結

具體採用哪種服務描述方式是根據實際情況決定,通常情況下, 如果只是企業內部之間的服務調用,並且都是 Java 語言的話,選擇 XML 配置方式是最簡單的。如果企業內部存在多個服務,並且服務採用的是不同語言平台,建議使用 IDL 文件方式進行描述服務。如果還存在對外開放服務調用的情形的話,使用 RESTful API 方式則更加通用。


2. 如何註冊和發現服務

註冊中心原理

在微服務架構下, 主要有三種角色:服務提供者(RPC Server)、服務消費者(RPC Client)和服務註冊中心(Registry),三者的交互關係如圖

RPC Server 提供服務,在啟動時,根據服務發布文件 server.xml 中配置的信息,向 Registry 訂閱服務,把 Registry 返回的服務節點列表緩存在本地內存中,並於 RPC Server 建立連接。

RPC Client 調用服務,在啟動時,根據服務引用文件 client.xml 中配置的信息,向 Registry 訂閱服務,把 Registry 返回的服務節點列表緩存在本地內存中,並於 RPC Client 建立連接。

當 RPC Server 節點發生變更時,Registry 會同步變更,RPC Client 感知後會刷新本地內存中緩存的服務節點列表。

RPC Client 從本地緩存的服務節點列表中,基於負載均衡演算法選擇一台 RPC Server 發起調用。


註冊中心實現方式

註冊中心API

服務註冊介面:服務提供者通過調用註冊介面來完成服務註冊

服務反註冊介面:服務提供者通過調用服務反註冊介面來完成服務註銷

心跳彙報介面:服務提供者通過調用心跳彙報介面完成節點存貨狀態上報

服務訂閱介面:服務消費者調用服務訂閱介面完成服務訂閱,獲取可用的服務提供者節點列表

服務變更查詢介面:服務消費者通過調用服務變更查詢介面,獲取最新的可用服務節點列表

服務查詢介面:查詢註冊中心當前住了哪些服務信息

服務修改介面:修改註冊中心某一服務的信息

集群部署

註冊中心一般都是採用集群部署來保證高可用性,並通過分散式一致性協議來確保集群中不同節點之間的數據保持一致。

Zookeeper 的工作原理:

每個 Server 在內存中存儲了一份數據,Client 的讀請求可以請求任意一個 Server

Zookeeper 啟動時,將從實例中選舉一個 leader(Paxos 協議)

Leader 負責處理數據更新等操作(ZAB 協議)

一個更新操作方式,Zookeeper 保證了高可用性以及數據一致性

目錄存儲

ZooKeeper作為註冊中心存儲服務信息一般採用層次化的目錄結構:

每個目錄在 ZooKeeper 中叫作 znode,並且其有一個唯一的路徑標識

znode 可以包含數據和子 znode。

znode 中的數據可以有多個版本,比如某一個 znode 下存有多個數據版本,那麼查詢這個路徑下的數據需帶上版本信息。

服務健康狀態檢測

註冊中心除了要支持最基本的服務註冊和服務訂閱功能以外,還必須具備對服務提供者節點的健康狀態檢測功能,這樣才能保證註冊中心裡保存的服務節點都是可用的。

基於 ZooKeeper 客戶端和服務端的長連接和會話超時控制機制,來實現服務健康狀態檢測的。

在 ZooKeeper 中,客戶端和服務端建立連接後,會話也也隨之建立,並生成一個全局唯一的 Session ID。服務端和客戶端維持的是一個長連接,在 SESSION_TIMEOUT 周期內,服務端會檢測與客戶端的鏈路是否正常,具體方式是通過客戶端定時向服務端發送心跳消息(ping 消息),伺服器重置下次 SESSION_TIMEOUT 時間。如果超過 Session 就已經結束了,ZooKeeper 就會認為這個 Session 就已經結束了,ZooKeeper 就會認為這個服務節點已經不可用,將會從註冊中心中刪除其信息。

服務狀態變更通知

一旦註冊中心探測到有伺服器提供者節點新加入或者被剔除,就必須立刻通知所有訂閱該服務的服務消費者,刷新本地緩存的服務節點信息,確保服務調用不會請求不可用的服務提供者節點。

基於 Zookeeper 的 Watcher 機制,來實現服務狀態變更通知給服務消費者的。服務消費者在調用 Zookeeper 的 getData 方式訂閱服務時,還可以通過監聽器 Watcher 的 process 方法獲取服務的變更,然後調用 getData 方法來獲取變更後的數據,刷新本地混存的服務節點信息。

白名單機制

註冊中心可以提供一個白名單機制,只有添加到註冊中心白名單內的 RPC Server,才能夠調用註冊中心的註冊介面,這樣的話可以避免測試環境中的節點意外跑到線上環境中去。


總結

註冊中心可以說是實現服務話的關鍵,因為服務話之後,服務提供者和服務消費者不在同一個進程中運行,實現了解耦,這就需要一個紐帶去連接服務提供者和服務消費者,而註冊中心就正好承擔了這一角色。此外,服務提供者可以任意伸縮即增加節點或者減少節點,通過服務健康狀態檢測,註冊中心可以保持最新的服務節點信息,並將變化通知給訂閱服務的服務消費者。

註冊中心一般採用分散式集群部署,來保證高可用性,並且為了實現異地多活,有的註冊中心還採用多 IDC 部署,這就對數據一致性產生了很高的要求,這些都是註冊中心在實現時必須要解決的問題。


3. 如何實現RPC遠程服務調用

客戶端和服務端如何建立網路連接

HTTP 通信

HTTP 通信是基於應用層HTTP 協議的,而 HTTP 協議又是基於傳輸層 TCP 協議的。一次 HTTP 通信過程就是發起一次 HTTP 調用,而一次 HTTP 調用就會建立一個 TCP 連接,經歷一次下圖所示的 「三次握手」的過程來建立連接。

完成請求後,再經歷一次「四次揮手」的過程來斷開連接。

Socket 通信

Socket 通信是基於 TCP/IP 協議的封裝,建立一次Socket 連接至少需要一對套接字,其中一個運行於客戶端,稱為 ClientSocket ;另一個運行於伺服器端,稱為 ServerSocket 。

伺服器監聽:ServerSocket 通過點用 bind() 函數綁定某個具體埠,然後調用 listen() 函數實時監控網路狀態,等待客戶端的連接請求。

客戶端請求:ClientSocket 調用 connect() 函數向 ServerSocket 綁定的地址和埠發起連接請求。

服務端連接確認:當 ServerSocket 監聽都或者接收到 ClientSocket 的連接請求時,調用 accept() 函數響應 ClientSocket 的請求,同客戶端建立連接。

數據傳輸:當 ClientSocket 和 ServerSocket 建立連接後,ClientSocket 調用 send() 函數,ServerSocket 調用 receive() 函數,ServerSocket 處理完請求後,調用 send() 函數,ClientSocket 調用 receive() 函數,就可以得到返回結果。

當客戶端和服務端建立網路連接後,就可以起發起請求了。但網路不一定總是可靠的,經常會遇到網路閃斷、連接超時、服務端宕機等各種異常,通常的處理手段有兩種:

鏈路存活檢測:客戶端需要定時地發送心跳檢測小心(一般通過 ping 請求) 給服務端,如果服務端連續 n 次心跳檢測或者超過規定的時間沒有回復消息,則認為此時鏈路已經失效,這個時候客戶端就需要重新與服務端建立連接。

斷連重試:通常有多種情況會導致連接斷開,比如客戶端主動關閉、服務端宕機或者網路故障等。這個時候客戶端就需要與服務端重新建立連接,但一般不能立刻完成重連,而是要等待固定的間隔後再發起重連,避免服務端的連接回收不及時,而客戶端瞬間重連的請求太多而把服務端的連接數佔滿。


服務端如何處理請求

同步阻塞方式(BIO)

客戶端每發一次請求,服務端就生成一個線程去處理。當客戶端同時發起的請求很多事,服務端需要創建很多的線程去處理每一個請求,如果達到了系統最大的線程數瓶頸,新來的請求就沒法處理了。

BIO 適用於連接數比較小的業務場景,這樣的話不至於系統中沒有可用線程去處理請求。這種方式寫的程序也比較簡單直觀,易於理解。

同步非阻塞(NIO)

客戶端每發一次請求,服務端並不是每次都創建一個新線程來處理,而是通過 I/O 多路復用技術進行處理。就是把國歌 I/O 的阻塞復用到聽一個 select 的阻塞上,從而使系統在單線程的情況下可以同時處理多個客戶端請求。這種方式的優勢是開銷小,不用為每個請求創建一個線程,可以節省系統開銷。

NIO 適用於連接數比較多並且請求消耗比較輕的業務場景,比如聊天伺服器。這種方式相比 BIO,相對來說編程比較複雜。

非同步非阻塞(AIO)

客戶端只需要發起一個 I/O 操作然後立即返回,等 I/O 操作真正完成以後,客戶端會得到 I/O 操作完成的通知,此時客戶端只需要對數據進行處理就好了,不需要進行實際的 I/O 讀寫操作,因為真正的 I/O 讀取或者寫入操作已經由內核完成了。這種方式的優勢是客戶端無需等待,不存在阻塞等待問題。

AIO 適用於連接數比較多而且請求消耗比較重的業務場景,比如涉及 I/O 操作的相冊伺服器。這種方式相比另外兩種,編程難難度最大,程序也不易於理解。

建議

最為穩妥的方式是使用成熟的開源方案,比如 Netty、MINA 等,它們都是經過業界大規模應用後,被充分論證是很可靠的方案。


數據傳輸採用什麼協議

無論是開放的還是私有的協議,都必須定義一個「契約」,以便服務消費和服務提供者之間能夠達成共識。服務消費者按照契約,對傳輸的數據進行編碼,然後通過網路傳輸過去;服務提供者從網路上接收到數據後,按照契約,對傳輸的數據進行解碼,然後處理請求,再把處理後的結果進行編碼,通過網路傳輸返回給服務消費者;服務消費者再對返回的結果進行解碼,最終得到服務提供者處理後的返回值。


HTTP 協議

消息頭

Server 代表是服務端伺服器類型

Content-Length 代表返回數據的長度

Content-Type 代表返回數據的類型

消息體

具體的返回結果


數據該如何序列化和反序列化

一般數據在網路中進行傳輸,都要先在發送方一段對數據進行編碼,經過網路傳輸到達另一段後,再對數據進行解碼,這個過程就是序列化和反序列化

常用的序列化方式分為兩類:文本類如 XML/JSON 等,二進位類如 PB/Thrift 等,而具體採用哪種序列化方式,主要取決於三個方面的因素。

支持數據結構類型的豐富度。數據結構種類支持的越多越好,這樣的話對於使用者來說在編程時更加友好,有些序列化框架如 Hessian 2.0 還支持複雜的數據結構比如 Map、List等。

跨語言支持。

性能。主要看兩點,一個是序列化後的壓縮比,一個是序列化的速度。以常用的 PB 序列化和 JSON 序列化協議為例來對比分析,PB 序列化的壓縮比和速度都要比 JSON 序列化高很多,所以對性能和存儲空間要求比較高的系統選用 PB 序列化更合;而 JSON 序列化雖然性能要差一些,但可讀性更好,所以對性能和存儲空間要求比較高的系統選用 PB 序列化更合適對外部提供服務。


總結

通信框架:它主要解決客戶端和服務端如何建立連接、管理連接以及服務端如何處理請求的問題。

通信協議:它主要解決客戶端和服務端採用哪些數據傳輸協議的問題。

序列化和反序列化:它主要解決客戶端和服務端採用哪種數據編碼的問題。

這三部分就組成了一個完成的RPC 調用框架,通信框架提供了基礎的通信能力,通信協議描述了通信契約,而序列化和反序列化則用於數據的編/解碼。一個通信框架可以適配多種通信協議,也可以採用多種序列化和反序列化的格式,比如服務話框架 不僅支持 Dubbo 協議,還支持 RMI 協議、HTTP 協議等,而且還支持多種序列化和反序列化格式,比如 JSON、Hession 2.0 以及 Java 序列化等。


4. 如何監控微服務調用

在談論監控微服務監控調用前,首先要搞清楚三個問題:監控的對象是什麼?具體監控哪些指標?從哪些維度進行監控?


監控對象

用戶端監控:通常是指業務直接對用戶提供的功能的監控。

介面監控:通常是指業務提供的功能所以來的具體 RPC 介面監控。

資源監控:通常是指某個介面依賴的資源的監控。(eg:Redis 來存儲關注列表,對 Redis 的監控就屬於資源監控。)

基礎監控:通常是指對伺服器本身的健康狀況的監控。(eg: CPU、MEM、I/O、網卡帶寬等)


監控指標

請求量

實時請求量(QPS Queries Per Second):即每秒查詢次數來衡量,反映了服務調用的實時變化情況

統計請求量(PV Page View):即一段時間內用戶的訪問量來衡量,eg:一天的 PV 代表了服務一天的請求量,通常用來統計報表

響應時間:大多數情況下,可以用一段時間內所有調用的平均耗時來反應請求的響應時間。但它只代表了請求的平均快慢情況,有時候我們更關心慢請求的數量。為此需要把響應時間劃分為多個區間,比如0~10ms、10ms~50ms、50ms~100ms、100ms~500ms、500ms 以上這五個區間,其中 500ms 以上這個區間內的請求數就代表了慢請求量,正常情況下,這個區間內的請求數應該接近於 0;在出現問題時,這個區間內的請求數應該接近於 0;在出現問題時,這個區間內的請求數會大幅增加,可能平均耗時並不能反映出這一變化。除此之外,還可以從P90、P95、P99、P999 角度來監控請求的響應時間在 500ms 以內,它代表了請求的服務質量,即 SLA。

錯誤率:通常用一段時間內調用失敗的次數占調用總次數的比率來衡量,比如對於介面的錯誤率一般用介面返回錯誤碼為 503 的比率來表示。


監控維度

全局維度:從整體角度監控對象的請求量、平均耗時以及錯誤率,全局維度的監控一般是為了讓你對監控對象的調用情況有個整體了解。

分機房維度:為了業務高可用,服務部署不止一個機房,因為不同機房地域的不同,同一個監控對象的各種指標可能會相差很大。

單機維度:同一個機房內部,可能由於採購年份和批次不的不同,各種指標也不一樣。

時間維度:同一個監控對象,在每天的同一時刻各種指標通常也不會一樣,這種差異要麼是由業務變更導致,要麼是運營活動導致。為了了解監控對象各種指標的變化,通常需要與一天前、一周前、一個月前,甚至三個月前比較。

核心維度:業務上一般會依據重要性成都對監控對象進行分級,最簡單的是分成核心業務和非核心業務。核心業務和非核心業務在部署上必須隔離,分開監控,這樣才能對核心業務做重點保障。

對於一個微服務來說,必須要明確監控哪些對象、哪些指標,並且還要從不同的維度進行監控,才能掌握微服務的調用情況。


監控系統原理

數據採集:收集到每一次調用的詳細信息,包括調用的響應時間、調用是否成功、調用的發起者和接收者分別是誰,這個過程叫做數據採集。

數據傳輸:採集到數據之後,要把數據通過一定的方式傳輸給數據處理中心進行處理,這個過程叫做數據出傳輸。

數據處理:數據傳輸過來後,數據處理中心再按照服務的維度進行聚合,計算出不同服務的請求量、響應時間以及錯誤率等信息並存儲起來,這個過程叫做數據處理。

數據展示:通過介面或者 DashBoard 的形式對外展示服務的調用情況,這個過程叫做數據展示。


數據採集

服務主動上報

代理收集:這種處理方式通過服務調用後把調用的詳細信息記錄到本地日誌文件中,然後再通過代理去解析本地日誌文件,然後再上報服務的調用信息。

不管是哪種方式,首先要考慮的問題就是採樣率,也就是採集數據的頻率。一般來說,採樣率越高,監控的實時性就越高,精確度也越高。但採樣對系統本身的性能也會有一定的影響,尤其是採集後的數據需要寫到本地磁碟的時候,過高的採樣率會導致系統寫入的 I/O 過高,進而會影響到正常的服務調用。所以合理的採樣率是數據採集的關鍵,最好是可以動態控制採樣率,在系統比較空閑的時候加大採樣率,追求監控的實時性與精確度;在系統負載比較高的時候減少採樣率,追求監控的可用性與系統的穩定性。


數據傳輸

UDP傳輸:這種處理方式是數據處理單元提供伺服器的請求地址,數據採集後通過 UDP 協議與伺服器建立連接,然後把數據發送過去。

Kafka傳輸:這種處理方式是數據採集後發送都指定的 Topic,然後數據處理單元再訂閱對應的 Topic,就可以從 Kafka 消息隊列中讀取對應的數據。

無論哪種傳輸方式,數據格式十分重要,尤其是對帶寬敏感以及解析性能要求比較高的場景,一般數據傳輸時採用的數據格式有兩種:

二進位協議,最常用的就是 PB 對象

文本協議,最常用的就是 JSON 字元串


數據處理

介面維度聚合:把實時收到的數據按照調用的節點維度聚合在一起,這樣就可以得到每個介面的實時請求、平均耗時等信息。

機器維度聚合:把實時收到的數據按照調用的節點維度聚合在一起,這樣就可以從單機維度去查看每個介面的實時請求量、平均耗時等信息。

聚合後的數據需要持久化到資料庫中存儲,所選用的資料庫一般分為兩種:

索引資料庫:比如 Elasticsearcher,以倒排索引的數據結構存書,需要查詢的時候,根據索引來查詢。

時序資料庫:比如 OpenTSDB,以時序序列數據的方式存儲,查詢的時候按照時序如 1min、5min 等維度查詢


數據展示

曲線圖:監控變化趨勢。

餅狀圖:監控佔比分布。

格子圖:主要坐一些細粒度的監控。


總結

服務監控子啊微服務改造過程中的重要性不言而喻,沒有強大的監控能力,改造成微服務架構後,就無法掌控各個不同服務的情況,在遇到調用失敗時,如果不能快速發現系統的問題,對於業務來說就是一場災難。

搭建一個服務監控系統,設計數據採集、數據傳輸、數據處理、數據展示等多個環節,每個環節都需要根據自己的業務特點選擇合適的解決方案


5. 如何追蹤微服務調用

跟蹤記錄一次用戶請求都發起了哪些調用,經過哪些服務處理,並且記錄每一次調用所涉及的詳細信息,這時候如果發生調用失敗,就可以通過這個日誌快速定位是在哪個環節出了問題。


服務追蹤的作用

優化系統瓶頸

通過記錄調用經過的每一條鏈路上的耗時,可以快速定位整個系統的瓶頸點在哪裡。可能出現的原因如下:

運營商網路延遲

網關係統異常

某個服務異常

緩存或者資料庫異常

通過服務追蹤,可以從全局視角上去觀察,找出整個系統的瓶頸點所在,然後做出針對性的優化

優化鏈路調用

通過服務追蹤可以分析調用所經過的路徑,然後評估是否合理

一般業務都會在多個數據中心都部署服務,以實現異地容災,這個時候經常會出現一種狀況就是服務 A 調用了另外一個數據中心的服務 B,而沒有調用同處於一個數據中心的舒服務 B。跨數據中心的調用視距離遠近都會有一定的網路延遲,像北京和廣州這種幾千公里距離的網路延遲可能達到了30ms以上,這對於有些業務幾乎是不可接受的。通過對調用鏈路進行分析,可以找出跨數據中的服務調用,從而進行優化,盡量規避這總情況出現。

生成網路拓撲

通過服務追蹤系統中記錄的鏈路信息,可以生成一張系統的網路調用拓撲圖,它可以反映系統都依賴了哪些服務,以及服務之間的調用關係是什麼樣的,可以一目了然。除此之外,在網路拓撲圖上還可以把服務調用的詳細信息也標出來,也能起到服務監控的作用。

透明傳輸數據

除了服務追蹤,業務上經常有一種需求,期望能把一些用戶數據,從調用的開始一直往下傳遞,以便系統中的各個服務都能獲取到這個信息。比如業務想做一些 A/B 測試,這時候就想通過服務追蹤系統,把 A/B 測試的開關邏輯一直往下傳遞,經過的每一層服務都能獲取到這個開關值,就能夠統一進行 A/B 測試。

服務追蹤原理

服務追蹤鼻祖:Google 發布的一篇的論文Dapper, [a Large-Scale Distributed Systems Tracing Infrastructure

核心理念:通過一個全局唯一的 ID 將分布在各個服務節點上的同一次請求串聯起來,從而還原原有的調用關係,可以追蹤系統問題、分析調用數據並統計各種系統指標

可以說後面的誕生各種服務追蹤系統都是基於 Dapper 衍生出來的,比較有名的有 Twitter 的Zipkin、阿里的鷹眼、美團的MTrace等。

講解下服務追蹤系統中幾個最基本概念

traceId:用於標識某一次具體的請求ID。

spanId:用於標識一次 RPC 調用在分散式請求中的位置。

annotation:用於業務自定義埋點數據,可以是業務感興趣的上上傳到後端的數據,比如一次請求的用戶 UID。

traceId 是用於串聯某一次請求在系統中經過的所有路徑,spanId 是用於區分系統不同服務之間調用的先後關係,而annotation 是用於業務自定義一些自己感興趣的數據,在上傳 traceId 和 spanId 這些基本信息之外,添加一些自己感興趣的信息。


服務追蹤系統實現

上面是服務追蹤系統架構圖,一個服務追蹤系統可以分三層:

數據採集層:負責數據埋點並上報

數據處理層:負責數據的存儲與計算

數據展示層:負責數據的圖形化展示


數據採集層

作用:在系統的各個不同的模塊中盡心埋點,採集數據並上報給數據處理層進行處理。

CS(Client Send)階段 : 客戶端發起請求,並生成調用的上下文。

SR(Server Recieve)階段 : 服務端接收請求,並生成上下文。

SS(Server Send)階段 : 服務端返回請求,這個階段會將服務端上下文數據上報,下面這張圖可以說明上報的數據有:traceId=123456,spanId=0.1,appKey=B,method=B.method,start=103,duration=38.

CR(Client Recieve)階段 : 客戶端接收返回結果,這個階段會將客戶端上下文數據上報,上報的數據有:traceid=123456,spanId=0.1,appKey=A,method=B.method,start=103,duration=38。


數據處理層

作用:把數據上報的數據按需計算,然後落地存儲供查詢使用

實時數據處理:要求計算效率比較高,一般要對收集的鏈路數據能夠在秒級別完成聚合計算,以供實時查詢

針對實時數據處理,一般使用 Storm 或者 Spack Streaming 來對鏈路數據進行實時聚合加工,存儲一拜是用 OLTP 數據倉庫,比如 HBase,使用 traceId 作為 RowKey,能天然地把一條調用鏈聚合在一起,提高查詢效率。

離線數據處理:要求計算效率相對沒那麼高,一般能在小時級別完成鏈路數據的聚合計算即可,一般用作匯總統計。

針對離線數據處理,一般通過運行 MapReduce 或者 Spark 批處理程序來對鏈路數據進行離線計算,存儲一般使用 Hive


數據展示

作用:將處理後的鏈路信息以圖形化的方式展示給用戶和做故障定位

調用鏈路圖(eg:Zipkin)

服務整體情況:服務總耗時、服務調用的網路深度、每一層經過的系統,以及多少次調用。下圖展示的一次調用,總耗時 209.323ms,經過了 5 個不同系統模塊,調用深度為 7 層,共發生了 2

調用拓撲圖(Pinpoint)

調用拓撲圖是一種全局視野,在實際項目中,主要用作全局監控,用戶發現系統異常的點,從而快速做出決策。比如,某一個服務突然出現異常,那麼在調用鏈路拓撲圖中可以看出對這個服務的調用耗時都變高了,可以用紅色的圖樣標出來,用作監控報警。


總結

服務追蹤能夠幫助查詢一次用戶請求在系統中的具體執行路徑,以及每一條路徑下的上下游的詳細情況,對於追查問題十分有用。

實現一個服務追蹤系統,設計數據採集、數據處理和數據展示三個流程,有多種實現方式,具體採取某一種要根據自己的業務情況來選擇。


6. 微服務治理的手段有哪些

一次服務調用,服務提供者、註冊中心、網路這三者都可能會有問題,此時服務消費者應該如何處理才能確保調用成功呢?這就是服務治理要解決的問題。


節點管理

服務調用失敗一般是由兩類原因引起的

服務提供者自身出現問題,比如伺服器宕機、進程意外退出等

網路問題,如服務提供者、註冊中心、服務消費者這三者任意兩者之間的網路問題

無論是服務哪種原因,都有兩種節點管理手段:

註冊中心主動摘除機制

這種機制要求服務提供者定時的主動向註冊中心彙報心跳,註冊中心根據服務提供者節點最近一次彙報心跳的時間與上一次彙報心跳時間做比較,如果超出一定時間,就認為服務提供者出現問題,繼而把節點從服務列表中摘除,並把最近的可用服務節點列表推送給服務消費者。

服務消費者摘除機制

雖然註冊中心主動摘除機制可以解決服務提供者節點異常的問題,但如果是因為註冊中心與服務提供者之間的網路出現異常,最壞的情況是註冊中心會把服務節點全部摘除,導致服務消費者沒有可能的服務節點調用,但其實這時候提供者本身是正常的。所以,將存活探測機制用在服務消費者這一端更合理,如果服務消費者調用服務提供者節點失敗,就將這個節點從內存保存的可用夫提供者節點列表一處。

負載均衡演算法

常用的負載均衡演算法主要包括以下幾種:

隨機演算法(均勻)

輪詢演算法(按照固定的權重,對可用服務節點進行輪詢)

最少活躍調用演算法(性能理論最優)

一致性 Hash 演算法(相同參數的請求總是發到同一服務節點)


服務路由

對於服務消費者而言,在內存中的可用服務節點列表中選擇哪個節點不僅由負載均衡演算法決定,還由路由規則決定。

所謂的路由規則,就是通過一定的規則如條件表達式或者正則表達式來限定服務節點的選擇範圍。

為什麼要指定路由規則呢?主要有兩個原因:

業務存在灰度發布的需求

比如,服務提供者做了功能變更,但希望先只讓部分人群使用,然後根據這部分人群的使用反饋,再來決定是否全量發布。

多機房就近訪問的需求

跨數據中心的調用視距離遠近都會有一定的網路延遲,像北京和廣州這種幾千公里距離的網路延遲可能達到了30ms以上,這對於有些業務幾乎是不可接受的,所以就要一次服務調用盡量選擇同一個 IDC 內部節點,從而減少網路耗時開銷,提高性能。這時一般可以通過 IP 段規則來控制訪問,在選擇服務節點時,優先選擇同一 IP 段的節點。

那麼路由規則該如何配置?

靜態配置:服務消費者本地存放調用的路由規則,如果改變,需重新上線才能生效

動態配置:路由規則存放在配置中心,服務消費者定期去請求註冊中心來保持同步,要想改變消費者的路由配置,可以通過修改註冊中心的配置,服務消費者在下一個同步周期之後,就會請求註冊中心更新配置,從而實現動態變更


服務容錯

常用的手段主要有以下幾種:

FailOver:失敗自動切換(調用失敗或者超時,可以設置重試次數)

FailBack:失敗通知(調用失敗或者超時,不立即發起重試,而是根據失敗的詳細信息,來決定後續的執行策略)

FailCache:失敗緩存(調用失敗或者超時,不立即發起重試,而是隔一段時間後再次嘗試發起調用)

FailFirst:快速失敗(調用一次失敗後,不再充實,一般非核心業務的調用,會採取快速失敗策略,調用失敗後一般就記錄下失敗日誌就返回了)

一般對於冪等的調用可以選擇 FailOver 或者 FailCache,非冪等的調用可以選擇 Failback 或者 FailFast


總結

節點管理是從服務節點健康狀態角度來考慮,負載均衡和服務路由是從服務節點訪問優先順序角度來考慮,而服務容錯是從調用的健康狀態來考慮,可謂殊途同歸。

在實際的微服務架構中,上面的服務治理手段一般都會在服務框架中默認即成,比如 阿里的 Dubbo、微博開源的服務架構 Motan等。

溫馨提示:

求知若渴, 虛心若愚


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 架構師技術聯盟 的精彩文章:

如何快速成為優秀架構師?
數據中心,一種名為機櫃的設備是如何存在的?

TAG:架構師技術聯盟 |