淺談微服務的發展以及可觀測性

陶然陶然發表於2022-05-20

  近年來,“雲原生”頻繁出現在人們的視野中。隨著雲原生成為下一代雲端計算的技術“核心”,業界正在從關注“雲原生概念”轉變到關注“雲原生落地實踐”。雲原生技術發展勢不可擋,依然會是未來雲端計算領域的熱門話題。

  我們知道,現代”雲原生”是一套符合雲端計算發展趨勢的應用設計理念方法論,其關鍵技術中包含了微服務架構、容器、容器化編排、服務網格等技術。那麼當我們把大型系統拆解成一個個獨立部署的模組,進行容器化部署,得益於此團隊可以更加快速、持續、規模快的進行開發和交付系統。但事物都有兩面性,我們從方案或者技術“好”的一面中“獲利”的同時,必須同時規避解決“壞”的一面帶來的風險和後果,其中比較大一項就是微服務化後系統複雜性的成倍上升而帶來運維和問題排查難度陡增的巨大挑戰。

   01微服務架構演進歷史

  在真正進入微服務可觀測性這個話題之前,我們有必要了解下微服務架構的演進歷史。從整體上看,整體架構的演變過程大致經歷了單體應用架構、垂直應用架構、分散式SOA架構、微服務架構的演變。我們以一個電商系統舉例(以下圖片均來自網上),主要比較下各個架構之間在運維方面的區別。

  舉例的電商系統大致分為三個主體模組:主體業務模組(使用者管理、商品管理、訂單管理)、內容管理模組(CMS管理)、系統管理模組(後臺管理)。

  單體應用架構

  如圖所示,單體應用架構把所有模組都揉進了一個應用內,所有模組均耦合在一起。系統的健康狀況通常“所見即所得”(整體功能可用便表示應用處於健康狀態),監測和告警指標通常由JVM的一些引數進行反饋,應用日誌產生和收集比較統一集中,排查問題的鏈路通常比較短(大多問題可由日誌直接定位到應用內的某行程式碼進而分析原因),維護和監控起來難度不大。但通常一個子模組的問題會導致整體專案出現不可用,無法水平擴充套件,過於臃腫無法適配大型專案和應用。之後便逐漸演變為垂直應用架構。

  垂直應用架構

  相比較於單體應用架構,我們對整體系統進行了拆分,優點是可以根據實際情況對某個子系統進行水平擴充套件,一個系統發生故障可以避免對其他系統產生影響。缺點是拆分後系統比較獨立無法相互呼叫(不同於微服務,只是獨立拆分)也導致了重複業務的開發,如圖中箭頭所示的訂單管理、商品管理、使用者管理部分,後期維護成本較高。運維方面,難度提升的地方主要在於日誌的管理和問題發生點的增加,例如一個問題的發生可能同時由CMS和後臺管理系統導致,需要同時解決兩個系統的故障。但業務規模的擴大,會導致重複程式碼和重複修復工作的激增,我們需要將該部分的邏輯進行抽取,繼而慢慢過渡到分散式SOA架構。

  分散式SOA架構

  分散式SOA架構也可認為是微服務架構的雛形,其中展示層對應我們通常所說的消費者或者Controller層,負責控制頁面操作需要呼叫服務層的哪些服務(例如:下單操作使用到使用者、訂單、商品三個服務,而這三個服務又是抽象在服務層獨立存在的),而服務層是具體的業務邏輯實現供表現層呼叫,上圖的服務層模組應該包括使用者管理、商品管理、訂單管理、CMS管理、後臺管理等所有模組,並且基於SOA的分散式通常還會包含一個註冊中心(例如:圖中的ESB匯流排或者類似DUBBO這樣的框架)。

  作為微服務架構的雛形,在解決了水平擴充套件問題的同時,註冊中心的加入既解決了服務之間的註冊發現和呼叫,也使公共模組和邏輯服務得到了抽取獨立。但同時也開始讓運維監測壓力有了比較大的增加,效能和告警關注的服務變多,同時還需要關注註冊中心的健康,日誌分佈更加散亂,業務發生故障時,排查鏈路變得冗長,對於複雜業務問題我們通常需要同時獲取從展示層、註冊中心到服務層的日誌,並分析其關係才能比較好的定位出問題,這無論對運維還是應用效能提升都是一個挑戰。並且服務之間的依賴與呼叫關係複雜,服務提供方與呼叫方介面耦合,業務切分不夠細的問題也讓微服務架構登上舞臺。

  微服務架構

  現在我們所屬的微服務架構通常由一個閘道器以及各個功能獨立的微小服務構成,服務之間的可以相互呼叫,它們的可用性可由容器和容器編排的能力提供。服務劃分的更細、職責更加明確,服務之間可使用RPC、REST進行相互呼叫,同時為前端提供HTTP介面。

  由於服務的徹底拆分,服務的開發可以分發給各個小團隊進行獨立開發、部署和升級。並且每個微服務可以根據業務實際執行情況進行水平擴容,但同時微服務過多,服務治理成本變得更高,同時還要考慮分散式事務、容錯等技術。從運維方面看,服務日誌變得更加分散,怎麼對全域性的微服務進行監控和告警難度更大了,最後出現業務問題進行排查時,鏈路變得非常冗長,若沒有一個全域性追蹤id,只透過日誌的時間戳,無論是業務效能最佳化還是故障排除都會變得十分困難。即業界不斷在討論研究的問題,微服務的可觀測性。

   02什麼是微服務的可觀測性

  從上一節的架構的演變過程中,我們可以看出隨著服務越拆越細,越拆越獨立,運維的難度以及系統的複雜度都成倍的提升,我們不得不面對以下幾個問題:

  隨著模組之間的呼叫關係由程式內函式的呼叫變為程式間透過網路的呼叫,如何檢測和保證網路的可靠。

  呼叫鏈路的時間越來越長,流量的走向變得越發不可控,如何高效的排查問題或者提升應用的效能。

  現代微服務的實踐和部署往往結合Kubernetes、Docker、Service Mesh等雲原生技術,開發團隊更加難感知其下的基礎設施的狀態了。

  傳統對於系統的監控,我們往往關注諸如CPU、記憶體、網路、應用介面的請求量、介面的響應量等,但這對於微服務系統來說,並不能幫助我們掌握整體系統的執行情況。這就像一條輪胎、一個水箱、一箱油,這些事物分開獨立放置時我們能夠比較簡單的判定其狀態,但當這些東西被組合進一個“系統”,例如一輛汽車後,如何在汽車執行過程中,觀測到其狀態,就變成了影響汽車穩定性的重要一環,這對微服務系統來說同樣適用。

  微服務的可觀測性即是要解決資料流在客戶端輸入後,透明的知曉其在各個服務間進行採集、傳輸、儲存的狀態,進而解決預測系統執行過程中出現故障的問題。

  為了保證這些資料流的狀態被感知,業界普遍認為有幾類資料可作為可觀測性的支柱:Metrics、Logging、Tracing。

  其中Metrics是在一段時間內組成單個邏輯測量、計數器或直方圖的原子,例如,服務呼叫的QPS、響應時間、錯誤請求發生率,目的是為了建立集中式度量系統,側重於技術指標的收集與觀測;Logging用於記錄離散的事件,例如,應用程式的除錯資訊或錯誤資訊,目的是搭建集中式日誌系統,側重於統一採集、儲存與檢索各個微服務的日誌;Tracing處理請求範圍內的資訊,例如,一次遠端方法呼叫的執行過程和耗時,目的是形成分散式追蹤系統,側重於串聯請求在微服務間的呼叫情況、繼而進行追蹤與APM分析。

  透過以上資訊,我們可以對已有的系統進行分類。例如,ZipKin、Jaeger專注於Tracing領域,Prometheus專注於Metrics領域,ELK、Loki專注於Logging領域。但是各個系統也都在不斷的整合其他領域的特性到自身系統中來,例如,Jaeger遵循的一些OpenTracing規範,但CNCF已經開始把OpenTracing和OpenCensus合併成 OpenTelemetry 專案,以後的會有更多即包含了一定Tracing能力同時又有Metrics的系統出現,Prometheus雖然一開始專注於指標的收集和管理,但也在開始整合一些Tracing的能力。

  現在業界對於微服務可觀測性的一種解決方案既是,首先使用loki + Grafana進行分佈日誌的統一收集與管理,使用Prometheus和Grafana對 Metrics 進行儲存和展示,最後再使用諸如類似Jaeger的追蹤系統做分散式追蹤的儲存和展示。基於此,我們可以大致獲得如下的一個問題分析鏈路:

  首先,我們透過Email或者某種方式收到一個告警資訊,接著去Grafana的圖表中看檢視某一段時間的指標異常情況,再下鑽就可以在Prometheus中檢視到某一個異常指標的詳細情況,就可以獲得對應某個異常發生的時間或節點,根據時間和節點以及服務標籤從Loki中撈取日誌資訊中的request id或者一個全域性的trace id,然後再根據這個trace id去類似Jaeger這種滿足OpenTelemetry 規範的系統中查詢呼叫鏈,獲得某個服務的異常或者效能響應詳情,最終排除出問題記錄issue。這是一個比較常規的微服務問題排查方法,雖然一定程度上解決了可觀測性的問題,但是仍然比較冗長。業界也已經出現了類似exemplar這樣的元件,能夠串聯各個割裂的元件,或者各個廠商也在嘗試推出類似Erda Cloud這樣的一站式解決方法,使上文提到的Logging、Tracing、Metrics不斷的向中心圓靠攏。

   03總結

  微服務架構和雲原生的發展使我們能夠更加從容的面對大資料時代大型系統的開發,同時系統運維排查過程中問題鏈路追蹤、應用日誌的管理、故障的監控告警等也變得越發複雜,業界起初出現了針對各個問題的對應的獨立解決方案,但慢慢也趨於集中提供能夠串聯和一站式的平臺系統。微服務的可觀測性問題一直都是困擾著整體應用穩定性的一環,在之後的文章中,我們也期待與大家分享更多相關技術細節和實戰文章。

來自 “ 移動Labs ”, 原文作者:陳亦帥;原文連結:https://mp.weixin.qq.com/s/MzV52fjJLqnT3olKDBWB4A,如有侵權,請聯絡管理員刪除。

相關文章