服務描述:服務調用首先解決的問題就是服務如何對外描述。 經常使用的服務描述方式包括 RESTful API、XML 配置以及 IDL 文件三種。node
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 方式則更加通用。
註冊中心原理
在微服務架構下, 主要有三種角色:服務提供者(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_TIMEOUT,ZooKeeper 就會認爲這個 Session 就已經結束了,ZooKeeper 就會認爲這個服務節點已經不可用,將會從註冊中心中刪除其信息。
服務狀態變動通知
一旦註冊中心探測到有服務器提供者節點新加入或者被剔除,就必須馬上通知全部訂閱該服務的服務消費者,刷新本地緩存的服務節點信息,確保服務調用不會請求不可用的服務提供者節點。
基於 Zookeeper 的 Watcher 機制,來實現服務狀態變動通知給服務消費者的。服務消費者在調用 Zookeeper 的 getData 方式訂閱服務時,還能夠經過監聽器 Watcher 的 process 方法獲取服務的變動,而後調用 getData 方法來獲取變動後的數據,刷新本地混存的服務節點信息。
白名單機制
註冊中心能夠提供一個白名單機制,只有添加到註冊中心白名單內的 RPC Server,纔可以調用註冊中心的註冊接口,這樣的話能夠避免測試環境中的節點意外跑到線上環境中去。
註冊中心能夠說是實現服務話的關鍵,由於服務話以後,服務提供者和服務消費者不在同一個進程中運行,實現瞭解耦,這就須要一個紐帶去鏈接服務提供者和服務消費者,而註冊中心就正好承擔了這一角色。此外,服務提供者能夠任意伸縮即增長節點或者減小節點,經過服務健康狀態檢測,註冊中心能夠保持最新的服務節點信息,並將變化通知給訂閱服務的服務消費者。
註冊中心通常採用分佈式集羣部署,來保證高可用性,而且爲了實現異地多活,有的註冊中心還採用多 IDC 部署,這就對數據一致性產生了很高的要求,這些都是註冊中心在實現時必需要解決的問題。
客戶端和服務端如何創建網絡鏈接
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 序列化等。
在談論監控微服務監控調用前,首先要搞清楚三個問題:監控的對象是什麼?具體監控哪些指標?從哪些維度進行監控?
監控對象
用戶端監控:一般是指業務直接對用戶提供的功能的監控。
接口監控:一般是指業務提供的功能因此來的具體 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、P9五、P9九、P999 角度來監控請求的響應時間在 500ms 之內,它表明了請求的服務質量,即 SLA。
錯誤率:一般用一段時間內調用失敗的次數佔調用總次數的比率來衡量,好比對於接口的錯誤率通常用接口返回錯誤碼爲 503 的比率來表示。
監控維度
全局維度:從總體角度監控對象的請求量、平均耗時以及錯誤率,全局維度的監控通常是爲了讓你對監控對象的調用狀況有個總體瞭解。
分機房維度:爲了業務高可用,服務部署不止一個機房,由於不一樣機房地域的不一樣,同一個監控對象的各類指標可能會相差很大。
單機維度:同一個機房內部,可能因爲採購年份和批次不的不一樣,各類指標也不同。
時間維度:同一個監控對象,在天天的同一時刻各類指標一般也不會同樣,這種差別要麼是由業務變動致使,要麼是運營活動致使。爲了瞭解監控對象各類指標的變化,一般須要與一天前、一週前、一個月前,甚至三個月前比較。
核心維度:業務上通常會依據重要性成都對監控對象進行分級,最簡單的是分紅核心業務和非核心業務。核心業務和非核心業務在部署上必須隔離,分開監控,這樣才能對核心業務作重點保障。
對於一個微服務來講,必需要明確監控哪些對象、哪些指標,而且還要從不一樣的維度進行監控,才能掌握微服務的調用狀況。
監控系統原理
數據採集:收集到每一次調用的詳細信息,包括調用的響應時間、調用是否成功、調用的發起者和接收者分別是誰,這個過程叫作數據採集。
數據傳輸:採集到數據以後,要把數據經過必定的方式傳輸給數據處理中心進行處理,這個過程叫作數據出傳輸。
數據處理:數據傳輸過來後,數據處理中心再按照服務的維度進行聚合,計算出不一樣服務的請求量、響應時間以及錯誤率等信息並存儲起來,這個過程叫作數據處理。
數據展現:經過接口或者 DashBoard 的形式對外展現服務的調用狀況,這個過程叫作數據展現。
數據採集
服務主動上報
代理收集:這種處理方式經過服務調用後把調用的詳細信息記錄到本地日誌文件中,而後再經過代理去解析本地日誌文件,而後再上報服務的調用信息。
無論是哪一種方式,首先要考慮的問題就是採樣率,也就是採集數據的頻率。通常來講,採樣率越高,監控的實時性就越高,精確度也越高。但採樣對系統自己的性能也會有必定的影響,尤爲是採集後的數據須要寫到本地磁盤的時候,太高的採樣率會致使系統寫入的 I/O 太高,進而會影響到正常的服務調用。因此合理的採樣率是數據採集的關鍵,最好是能夠動態控制採樣率,在系統比較空閒的時候加大采樣率,追求監控的實時性與精確度;在系統負載比較高的時候減小採樣率,追求監控的可用性與系統的穩定性。
數據傳輸
UDP傳輸:這種處理方式是數據處理單元提供服務器的請求地址,數據採集後經過 UDP 協議與服務器創建鏈接,而後把數據發送過去。
Kafka傳輸:這種處理方式是數據採集後發送都指定的 Topic,而後數據處理單元再訂閱對應的 Topic,就能夠從 Kafka 消息隊列中讀取對應的數據。
不管哪一種傳輸方式,數據格式十分重要,尤爲是對帶寬敏感以及解析性能要求比較高的場景,通常數據傳輸時採用的數據格式有兩種:
二進制協議,最經常使用的就是 PB 對象
文本協議,最經常使用的就是 JSON 字符串
數據處理
接口維度聚合:把實時收到的數據按照調用的節點維度聚合在一塊兒,這樣就能夠獲得每一個接口的實時請求、平均耗時等信息。
機器維度聚合:把實時收到的數據按照調用的節點維度聚合在一塊兒,這樣就能夠從單機維度去查看每一個接口的實時請求量、平均耗時等信息。
聚合後的數據須要持久化到數據庫中存儲,所選用的數據庫通常分爲兩種:
索引數據庫:好比 Elasticsearcher,以倒排索引的數據結構存書,須要查詢的時候,根據索引來查詢。
時序數據庫:好比 OpenTSDB,以時序序列數據的方式存儲,查詢的時候按照時序如 1min、5min 等維度查詢
數據展現
曲線圖:監控變化趨勢。
餅狀圖:監控佔比分佈。
格子圖:主要坐一些細粒度的監控。
總結
服務監控子啊微服務改造過程當中的重要性不言而喻,沒有強大的監控能力,改形成微服務架構後,就沒法掌控各個不一樣服務的狀況,在遇到調用失敗時,若是不能快速發現系統的問題,對於業務來講就是一場災難。
搭建一個服務監控系統,設計數據採集、數據傳輸、數據處理、數據展現等多個環節,每一個環節都須要根據本身的業務特色選擇合適的解決方案
若是想免費學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java進階羣:478030634,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。
跟蹤記錄一次用戶請求都發起了哪些調用,通過哪些服務處理,而且記錄每一次調用所涉及的詳細信息,這時候若是發生調用失敗,就能夠經過這個日誌快速定位是在哪一個環節出了問題。
服務追蹤的做用
優化系統瓶頸
經過記錄調用通過的每一條鏈路上的耗時,能夠快速定位整個系統的瓶頸點在哪裏。可能出現的緣由以下:
運營商網絡延遲
網關係統異常
某個服務異常
緩存或者數據庫異常
經過服務追蹤,能夠從全局視角上去觀察,找出整個系統的瓶頸點所在,而後作出針對性的優化
優化鏈路調用
經過服務追蹤能夠分析調用所通過的路徑,而後評估是否合理
通常業務都會在多個數據中心都部署服務,以實現異地容災,這個時候常常會出現一種情況就是服務 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)
調用拓撲圖是一種全局視野,在實際項目中,主要用做全局監控,用戶發現系統異常的點,從而快速作出決策。好比,某一個服務忽然出現異常,那麼在調用鏈路拓撲圖中能夠看出對這個服務的調用耗時都變高了,能夠用紅色的圖樣標出來,用做監控報警。
總結
服務追蹤可以幫助查詢一次用戶請求在系統中的具體執行路徑,以及每一條路徑下的上下游的詳細狀況,對於追查問題十分有用。
實現一個服務追蹤系統,設計數據採集、數據處理和數據展現三個流程,有多種實現方式,具體採起某一種要根據本身的業務狀況來選擇。
一次服務調用,服務提供者、註冊中心、網絡這三者均可能會有問題,此時服務消費者應該如何處理才能確保調用成功呢?這就是服務治理要解決的問題。
節點管理
服務調用失敗通常是由兩類緣由引發的
服務提供者自身出現問題,好比服務器宕機、進程意外退出等
網絡問題,如服務提供者、註冊中心、服務消費者這三者任意二者之間的網絡問題
不管是服務哪一種緣由,都有兩種節點管理手段:
註冊中心主動摘除機制
這種機制要求服務提供者定時的主動向註冊中心彙報心跳,註冊中心根據服務提供者節點最近一次彙報心跳的時間與上一次彙報心跳時間作比較,若是超出必定時間,就認爲服務提供者出現問題,繼而把節點從服務列表中摘除,並把最近的可用服務節點列表推送給服務消費者。
服務消費者摘除機制
雖然註冊中心主動摘除機制能夠解決服務提供者節點異常的問題,但若是是由於註冊中心與服務提供者之間的網絡出現異常,最壞的狀況是註冊中心會把服務節點所有摘除,致使服務消費者沒有可能的服務節點調用,但其實這時候提供者自己是正常的。因此,將存活探測機制用在服務消費者這一端更合理,若是服務消費者調用服務提供者節點失敗,就將這個節點從內存保存的可用夫提供者節點列表一處。
負載均衡算法
經常使用的負載均衡算法主要包括如下幾種:
隨機算法(均勻)
輪詢算法(按照固定的權重,對可用服務節點進行輪詢)
最少活躍調用算法(性能理論最優)
一致性 Hash 算法(相同參數的請求老是發到同一服務節點)
服務路由
對於服務消費者而言,在內存中的可用服務節點列表中選擇哪一個節點不只由負載均衡算法決定,還由路由規則決定。
所謂的路由規則,就是經過必定的規則如條件表達式或者正則表達式來限定服務節點的選擇範圍。
爲何要指定路由規則呢?主要有兩個緣由:
業務存在灰度發佈的需求
好比,服務提供者作了功能變動,但但願先只讓部分人羣使用,而後根據這部分人羣的使用反饋,再來決定是否全量發佈。
多機房就近訪問的需求
跨數據中心的調用視距離遠近都會有必定的網絡延遲,像北京和廣州這種幾千千米距離的網絡延遲可能達到了30ms以上,這對於有些業務幾乎是不可接受的,因此就要一次服務調用盡可能選擇同一個 IDC 內部節點,從而減小網絡耗時開銷,提升性能。這時通常能夠經過 IP 段規則來控制訪問,在選擇服務節點時,優先選擇同一 IP 段的節點。
那麼路由規則該如何配置?
靜態配置:服務消費者本地存放調用的路由規則,若是改變,需從新上線才能生效
動態配置:路由規則存放在配置中心,服務消費者按期去請求註冊中心來保持同步,要想改變消費者的路由配置,能夠經過修改註冊中心的配置,服務消費者在下一個同步週期以後,就會請求註冊中心更新配置,從而實現動態變動
服務容錯
經常使用的手段主要有如下幾種:
FailOver:失敗自動切換(調用失敗或者超時,能夠設置重試次數)
FailBack:失敗通知(調用失敗或者超時,不當即發起重試,而是根據失敗的詳細信息,來決定後續的執行策略)
FailCache:失敗緩存(調用失敗或者超時,不當即發起重試,而是隔一段時間後再次嘗試發起調用)
FailFirst:快速失敗(調用一次失敗後,再也不充實,通常非核心業務的調用,會採起快速失敗策略,調用失敗後通常就記錄下失敗日誌就返回了)
通常對於冪等的調用能夠選擇 FailOver 或者 FailCache,非冪等的調用能夠選擇 Failback 或者 FailFast
若是想免費學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java進階羣:478030634,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。
總結
節點管理是從服務節點健康狀態角度來考慮,負載均衡和服務路由是從服務節點訪問優先級角度來考慮,而服務容錯是從調用的健康狀態來考慮,可謂異曲同工。
在實際的微服務架構中,上面的服務治理手段通常都會在服務框架中默認即成,好比 阿里的 Dubbo、微博開源的服務架構 Motan等。