微服務的全鏈路監控
1.什麼是全鏈路監控?
在分散式微服務架構中,系統為了接收並處理一個前端使用者請求,需要讓多個微服務應用協同工作,其中的每一個微服務應用都可以用不同的程式語言構建,由不同的團隊開發,並可以通過多個對等的應用例項實現水平擴充套件,甚至分佈在橫跨多個數據中心的數千臺伺服器上。單個使用者請求會引發不同應用之間產生一串順序性的呼叫關係,如果要對這些呼叫關係進行監控,瞭解每個應用如何呼叫,這就產生了全鏈路監控。
2.為什麼要進行全鏈路監控?
在微服務架構中,服務會被拆分成多個模組,這些模組可能由不同的開發團隊開發、維護,也可能使用不同的程式語言來實現、也有可能分佈在多臺伺服器上,由於服務的拆分,單個使用者的請求會經過多個微服務,相互之間形成複雜的呼叫關係,傳統的監控手段已經不能實現如此複雜的鏈路之間的監控了,因此,就需要一些可以幫助理解系統行為、用於分析效能問題的工具,以便發生故障的時候,能夠快速定位和解決問題。
3.全鏈路監控能解決哪些問題?
1. 請求鏈路追蹤,故障快速定位:可以通過呼叫鏈結合業務日誌快速定位錯誤資訊。
2. 視覺化: 各個階段耗時,進行效能分析。
3. 依賴優化:各個呼叫環節的可用性、梳理服務依賴關係以及優化。
4. 資料分析,優化鏈路:可以得到使用者的行為路徑,彙總分析應用在很多業務場景。
4.常見的全鏈路監控工具
4.1 zipkin
github:
https://github.com/openzipkin/zipkin
zipkin是一個分散式的追蹤系統,它能夠幫助你收集服務架構中解決問題需要的時間資料,功能包括收集和查詢這些資料。如果日誌檔案中有跟蹤ID,可以直接跳轉到它。否則,可以根據服務、操作名稱、標記和持續時間等屬性進行查詢。例如在服務中花費的時間百分比,以及哪些環節操作失敗。特點是輕量,使用部署簡單。
zipkin還提供了一個UI介面,它能夠顯示通過每個應用程式的跟蹤請求數。這有助於識別聚合行為,包括錯誤路徑或對不推薦使用的服務的呼叫。
應用程式需要“檢測”才能向Zipkin報告跟蹤資料。這通常意味著需要配置一個用於追蹤和檢測的庫。最流行的向Zipkin報告資料的方法是通過http或Kafka,儘管還有許多其他選項,如apache,activemq、gRPC和RabbitMQ。提供給UI儲存資料的方法很多,如儲存在記憶體中,或者使用受支援的後端(如apachecassandra或Elasticsearch)持久儲存。
4.2 skywalking
github:
https://github.com/apache/incubator-skywalking
skywalking是本土開源的呼叫鏈追蹤系統,包括監控、跟蹤、診斷功能,目前已加入Apache孵化器,專門為微服務、雲本地和基於容器(Docker、Kubernetes、Mesos)架構設計。
主要功能如下:
1)服務、服務例項、端點指標資料分析
2)根本原因分析,在執行時評測程式碼
3)服務拓撲圖分析
4)服務、服務例項和端點依賴性分析
5)檢測到慢速服務和終結點
6)效能優化
7)分散式跟蹤和上下文傳播
8)資料庫訪問度量。檢測慢速資料庫訪問語句(包括SQL語句)。
9)報警
10)瀏覽器效能監視
4.3 pinpoint
github:
https://github.com/naver/pinpoint
pinpoint是韓國人開源的基於位元組碼注入的呼叫鏈分析,以及應用監控分析工具。Pinpoint提供了一個解決方案,可以幫助分析系統的整體結構,以及通過跟蹤分散式應用程式中的事務來分析其中的元件是如何相互連線的。
功能如下:
1)一目瞭然地瞭解應用程式拓撲
2)實時監視應用程式
3)獲得每個事務的程式碼級可見性
4)安裝APM代理程式,無需更改一行程式碼
5)對效能的影響最小(資源使用量增加約3%)
Pinpoint的視覺化UI介面:
4.4jaeger
Jaeger 是受 Dapper 和 OpenZipkin 的啟發,由 Uber Technologies 建立的分散式追蹤平臺,現已捐贈給雲原生計算基金會。它可用於監視基於微服務的分散式系統:
- 分散式上下文傳播
- 分散式交易監控
- 根本原因分析
- 服務依賴分析
- 效能/延遲優化
Jaeger為何物?
Jaeger 是Uber推出的一款開源分散式追蹤系統,相容OpenTracing API。分散式追蹤系統用於記錄請求範圍內的資訊。例如,一次遠端方法呼叫的執行過程和耗時。是我們排查系統問題和系統性能的利器。
分散式追蹤系統種類繁多,但是核心步驟有三個:程式碼埋點,資料儲存和查詢展示。
以上幾句描述都是我copy的,所以大家想要對Jaeger有更加深入的瞭解,可以參閱這篇文章Jaeger 分散式追蹤系統模組分析,能讓你對Jaeger有一個簡單的認識。
當然我們還要記得APM的三大模組分別是集中式日誌系統,集中式度量系統和分散式全連結追蹤系統。
而Jaeger
屬於的就是追蹤系統,度量系統我們則會使用prometheus
,日誌系統一般則是elk
。
選用Jaeger的原因
一個是它相容OpenTracing API,寫起來簡單方便,一個是UI相較於Zipkin的更加直觀和豐富,還有一個則是sdk比較豐富,go語言編寫,上傳採用的是udp傳輸,效率高速度快。
相比Pinpoint的缺點,當然是UI差距了,基本上現在流行的追蹤系統UI上都遠遠遜於它
5.全鏈路監控工具對比分析
市面上的全鏈路監控理論模型大多都是借鑑Google Dapper論文,本文重點關注以下三種APM元件:
APM = ApplicationPerformance Management,中文即應用效能管理
APM三大模組:集中式日誌系統,集中式度量系統和分散式全連結追蹤系統
1)Zipkin:由Twitter公司開源,開放原始碼分散式的跟蹤系統,用於收集服務的定時資料,以解決微服務架構中的延遲問題,包括:資料的收集、儲存、查詢和展現。
2)Pinpoint:一款對Java編寫的大規模分散式系統的APM工具,由韓國人開源的分散式跟蹤元件。
3)Skywalking:國產的優秀APM元件,是一個對JAVA分散式應用程式叢集的業務執行情況進行追蹤、告警和分析的系統。
4)Jaeger: uber開發的受Zipkin與docker啟發,ui方面對比zipkin更加完善。
5.1 全面的呼叫鏈路資料分析
全面的呼叫鏈路資料分析,提供程式碼級別的可見性以便輕鬆定位失敗點和瓶頸。
1.zipkin
zipkin的鏈路監控粒度相對沒有那麼細,呼叫鏈中具體到介面級別,再進一步的呼叫資訊並未涉及。
2.skywalking
skywalking 支援20+的中介軟體、框架、類庫,比如:主流的dubbo、Okhttp,還有DB和訊息中介軟體。skywalking鏈路呼叫分析擷取的比較簡單,閘道器呼叫user服務,由於支援眾多的中介軟體,所以skywalking鏈路呼叫分析比zipkin完備些。
3.pinpoint
pinpoint應該是這三種APM元件中,資料分析最為完備的元件。提供程式碼級別的可見性以便輕鬆定位失敗點和瓶頸,上圖可以看到對於執行的sql語句,都進行了記錄。還可以配置報警規則等,設定每個應用對應的負責人,根據配置的規則報警,支援的中介軟體和框架也比較完備。
5.2 Pinpoint與Zipkin細化比較
5.2.1 pinpoint與zipkin差異性
1. Pinpoint 是一個完整的效能監控解決方案,有從探針、收集器、儲存到 Web 介面等全套體系,而Zipkin只側重收集器和儲存服務,雖然也有使用者介面,但其功能與Pinpoint不可同日而語。反而Zipkin提供有Query介面,更強大的使用者介面和系統整合能力,可以基於該介面二次開發實現。
2. Zipkin 官方提供有基於 Finagle 框架(Scala 語言)的介面,而其他框架的介面由社群貢獻,目前可以支援 Java、Scala、Node、Go、Python、Ruby 和 C# 等主流開發語言和框架;但是 Pinpoint 目前只有官方提供的 Java Agent 探針,其他的都在請求社群支援中。
3. Pinpoint 提供有 Java Agent 探針,通過位元組碼注入的方式實現呼叫攔截和資料收集,可以做到真正的程式碼無侵入,只需要在啟動伺服器的時候新增一些引數,就可以完成探針的部署,而 Zipkin的Java介面實現 Brave,只提供了基本的操作 API,如果需要與框架或者專案整合的話,就需要手動新增配置檔案或增加程式碼。
4. Pinpoint 的後端儲存基於 Hbase,而 Zipkin 基於 Cassandra。
5.2.2 pinpoint與zipkin相似性
pinpoint與zipkin都是基於Google Dapper的那篇論文,因此理論基礎大致相同。兩者都是將服務呼叫拆分成若干有級聯關係的Span,通過SpanId和ParentSpanId來進行呼叫關係的級聯,最後再將整個呼叫鏈流經的所有的Span匯聚成一個 Trace,報告給服務端的collector進行收集和儲存。
即便在這一點上,Pinpoint 所採用的概念也不完全與那篇論文一致。比如他採用 TransactionId 來取代 TraceId,而真正的 TraceId 是一個結構,裡面包含了 TransactionId, SpanId 和 ParentSpanId。而且 Pinpoint 在 Span 下面又增加了一個 SpanEvent 結構,用來記錄一個 Span 內部的呼叫細節(比如具體的方法呼叫等等),因此 Pinpoint 預設會比 Zipkin 記錄更多的跟蹤資料。但是理論上並沒有限定 Span 的粒度大小,所以一個服務呼叫可以是一個 Span,那麼每個服務中的方法呼叫也可以是個 Span,這樣的話,其實 Brave 也可以跟蹤到方法呼叫級別,只是具體實現並沒有這樣做而已。
互動:
1.span是什麼?
基本工作單元,一次鏈路呼叫(可以是RPC,DB等沒有特定的限制)建立一個span,通過一個64位ID標識它,uuid較為方便,span中還有其他的資料,例如描述資訊,時間戳,key-value對的(Annotation)tag資訊,parent_id等,其中parent-id可以表示span呼叫鏈路來源。
上圖說明了span在一次大的跟蹤過程中是什麼樣的。Dapper記錄了span名稱,以及每個span的ID和父ID,以重建在一次追蹤過程中不同span之間的關係。如果一個span沒有父ID被稱為root span。所有span都掛在一個特定的跟蹤上,也共用一個跟蹤id。
Span資料結構: type Span struct { TraceID int64 #用於標示一次完整的請求id Name string ID int64 #當前這次呼叫span_id ParentID int64 #上層服務的呼叫span_id 最上層服務parent_id為null Annotation []Annotation #用於標記的時間戳 Debug bool
2. Trace是什麼?
類似於 樹結構的Span集合,表示一次完整的跟蹤,從請求到伺服器開始,伺服器返回response結束,跟蹤每次rpc呼叫的耗時,存在唯一標識trace_id。比如:你執行的分散式大資料儲存一次Trace就由你的一次請求組成。
每種顏色的note標註了一個span,一條鏈路通過TraceId唯一標識,Span標識發起的請求資訊。樹節點是整個架構的基本單元,而每一個節點又是對span的引用。節點之間的連線表示的span和它的父span直接的關係。雖然span在日誌檔案中只是簡單的代表span的開始和結束時間,他們在整個樹形結構中卻是相對獨立的。
部署pinpoint服務
安裝docker: yum install -y docker-ce-19.03.7-3.el7 systemctl enable docker && systemctl start docker #檢視docker狀態,如果狀態是active(running),說明docker是正常執行狀態 systemctl status docker 修改docker配置檔案 cat > /etc/docker/daemon.json <<EOF { "registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com","http://qtid6917.mirror.aliyuncs.com"], "exec-opts":["native.cgroupdriver=systemd"], "log-driver":"json-file", "log-opts": { "max-size": "100m" }, "storage-driver":"overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } EOF 注: "registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com","http://qtid6917.mirror.aliyuncs.com"] 上面配置的是映象加速器 cat > /etc/docker/daemon.json <<EOF { "insecure-registries":["192.168.0.56"], "registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com","http://qtid6917.mirror.aliyuncs.com"], "exec-opts":["native.cgroupdriver=systemd"], "log-driver":"json-file", "log-opts": { "max-size": "100m" }, "storage-driver":"overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } EOF "insecure-registries":["192.168.40.132"] #配置的是harbor私有映象倉庫地址 重啟docker使配置生效 systemctl daemon-reload && systemctl restart docker && systemctl status docker 開啟機器的bridge模式 #臨時生效 echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables echo 1 >/proc/sys/net/bridge/bridge-nf-call-ip6tables #永久生效 echo """ vm.swappiness = 0 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 """ > /etc/sysctl.conf sysctl -p基礎環境配置
pinpoint service部署
github地址:
ttps://github.com/pinpoint-apm/pinpoint-docker.git
unzip pinpoint-docker-2.0.1.zip cd pinpoint-docker-2.0.1 修改docker-compose.yml檔案的version版本,如2.2,變成自己支援的版本 version: "3.6" 變成 version: "2.2" #拉取映象 yum install docker-compose -y docker-compose pull #啟動服務 docker-compose up -d #檢視對應的服務是否啟動 docker ps | grep pinpoint #找到pinpoint-web,可看到在宿主機繫結的埠是8079, 在瀏覽器訪問ip:8079即可訪問pinpoint的web ui介面
部署pinpoint agent
把microservic-test-dev1.zip上傳到k8s的master1節點,解壓:
unzip microservic-test-dev1.zip
下載地址:https://github.com/pinpoint-apm/pinpoint/releases/download/1.8.5/pinpoint-agent-1.8.5.tar.gz
將agent包一併傳入映象中 jar包啟動 通過agent代理
例如:
FROM java:8-jdk-alpine RUN apk add -U tzdata && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY ./target/eureka-service.jar ./ COPY pinpoint /pinpoint EXPOSE 8888 CMD java -jar -javaagent:/pinpoint/pinpoint-bootstrap-1.8.5.jar -Dpinpoint.agentId=${HOSTNAME} -Dpinpoint.applicationName=ms-eureka -Deureka.instance.hostname=${MY_POD_NAME}.eureka.ms /eureka-service.jar