微服務架構將原先業務鏈條中的各個環節(節點或過程),如用戶、產品、訂單、支付拆分實現成獨立的服務運行,必定程度上提升了系統的容錯能力,例如支付服務失敗時,用戶依然能夠經過產品及訂單服務,達到查看訂單和瀏覽產品的目的。隨着微服務應用開發框架(如springboot)和容器技術(如K8)愈來愈成熟,微服務的開發和運維趨於標準化。這些都是微服務的愈發流行的緣由。同時,隨着業務複雜度的提升,愈來愈多的微服務被開發和集成進來,服務管理的重要性不言而喻。本文以服務調用的鏈路管理爲題,淺談微服務治理中鏈路管理的主流技術如何實踐。java
鏈路管理,主要指記錄服務的調用鏈路,一般用來定位不合理的服務設計,如鏈路過長帶來的服務耗時問題、鏈路過長帶來的服務穩定性風險、循環依賴等。鏈路管理,須要考慮哪些方面的問題,如何實現?mysql
有了這個思路以後,咱們再來看目前主流的鏈路解決方案,Twitter的Zipkin,以及Apache的在孵化項目SKYwalking。固然還有些比較熱的方案,如韓國的開源項目Pinpoint和美團的CAT。這些方案從實現技術上大體可分爲兩個派系,攔截派,字節碼加強派。攔截派作法經過代理類攔截請求,將鏈路信息發送給服務器,Zipkin和CAT都屬於這種類型,不過CAT須要代碼侵入,即代碼中增長埋點,而Zipkin直接經過SpringCloud的Sleuth無縫對接SpringBoot的微服務。字節碼加強技術,經過JVMTI接口提供的javaagent(區別於JDK動態代理和CGLIB代理),利用字節碼操做技術(ASM),在類加載並實例化以前對class進行轉換,以後運行中將信息採集併發送給代理服務器(探針),如sk*walking的Agent服務。關於兩種方式的比較,小結以下:web
類型 | zipkin | SKYwalking |
---|---|---|
基本原理 | 攔截請求,發送(HTTP,mq)數據至zipkin服務 | java探針,字節碼加強 |
接入方式 | 基於linkerd或者sleuth方式,引入配置便可 | avaagent字節碼 |
支持OpenTracing | 是 | 是 |
顆粒度 | 接口級(類級別) | 方法級 |
存儲 | ES,mysql,Cassandra,內存 | ES,H2,TIDB |
agent到collector的協議 | http,MQ | http,gRPC |
Zipkin 分爲兩端,Zipkin 服務端和Zipkin 客戶端,客戶端也就是微服務的應用。客戶端配置服務端的 URL 地址,一旦發生服務間的調用的時候,會被配置在微服務裏面的 Sleuth 的監聽器監聽,並生成相應的 Trace 和 Span 信息發送給服務端。發送的方式主要有兩種,一種是 HTTP 報文的方式,另外一種是消息總線的方式如 RabbitMQ。spring
不論哪一種方式,咱們都須要:一個 Eureka 服務註冊中心,先看下Zipkin運行架構:sql
左側應用服務,同時也是Zipkin-clinet,Eureka-client, 中間是依賴,包括Zipkin-server和Eureka-server,最右側是WebUI展現及開發接口。docker
Zipkin 的服務端,在使用 Spring Boot 2.x 版本後,官方就不推薦自行定製編譯了,反而是直接提供了編譯好的 jar 包來給咱們使用。
因此官方提供了一鍵腳本數據庫
curl -sSL https://zipkin.io/quickstart.sh | bash -s java -jar zipkin.jar
若是用 Docker 的話,直接docker run -d -p 9411:9411 openzipkin/zipkin
apache
這裏使用docker環境測試,數據存儲選擇默認的內存方式。啓動zipkinserver後,直接訪問9411,看到管理頁面:springboot
zipkinserver啓動後,啓動EurekaServer,先本地啓動一個,端口暫定爲7777.bash
好了,如今依賴服務有了,接下來改造兩個現有的微服務(爲至少兩個有調用關係的服務配置),做爲zkclient。要作的事情很簡單,下面幾步:
1)微服務增長zipkin依賴
compile "org.springframework.cloud:spring-cloud-starter-sleuth" compile "org.springframework.cloud:spring-cloud-starter-zipkin"
2) 啓動類增長EurekaClient註解@EnableDiscoveryClient
3)application配置文件增長Eureka配置
eureka.instance.hostname=localhost eureka.client.serviceUrl.defaultZone = http://${eureka.instance.hostname}:7777/eureka/ eureka.instance.preferIpAddress= true
1)開啓sleuth client
spring.sleuth.web.client.enabled=true spring.sleuth.sampler.percentage=1.0
sampler.percentage是採樣率,1表明選取所有樣本,由於是測試,因此直接設置成1,實際狀況多是個小數,0.3或者0.5,根據需求自行決定。
2)配置zipkinserver地址spring.zipkin.base-url=http://192.168.72.101:9411/
1) Eureka服務清單
2) Zipkin服務鏈路
須要注意的是,因爲Sleuth trace filter僅針對Spring內置的Rest調用作攔截,跨服務的調用須要使用Spring官宣方式,如RestTemplate,直接使用apache的httpclient工具包調用,是沒法追蹤到完整鏈路。
下面從實現層面瞭解,Zipkin的工做機制。引入sleuth和zipkin依賴包以後,系統自動掃描全部包中的@configuration,TraceAutoConfiguration是sleuth包的配置入口,看看它的定義,spring.sleuth.enabled開啓的時候註解有效。
@Configuration @ConditionalOnProperty( value = {"spring.sleuth.enabled"}, matchIfMissing = true ) @EnableConfigurationProperties({TraceKeys.class, SleuthProperties.class}) public class TraceAutoConfiguration { ...
同理,Zipkin的配置以下:
@Configuration @EnableConfigurationProperties({ZipkinProperties.class, SamplerProperties.class}) @ConditionalOnProperty(value = "spring.zipkin.enabled", matchIfMissing = true) @AutoConfigureBefore(TraceAutoConfiguration.class) public class ZipkinAutoConfiguration { ...
TraceFilter做爲整個追蹤的切入口,針對全部的request進行過濾標記,並經過AsyncReporter進行異步發送報文。下圖框起來的部分,分別是接口地址和編碼協議(Thrift)
Zipkin使用起來很簡單,可是由於是接口級的跟蹤,能看到的信息比較有限,另外頁面的展現形式也相對簡單,缺乏多角度或者多樣性,因此,咱們再試試SKYWalking。
skywalking的工做機制,須要三塊協同,一塊是skywalking server,負責接收、存儲並展現,因此server模塊包含一個展現web子模塊;第二塊是agent,負責代理微服務並收集須要的信息,轉發給server;第三塊即是微服務自己,須要在啓動時指定agent,以便生成代理類。工做原理圖大體以下:
先看下效果圖,再記錄配置過程。
選中其中一個服務,能夠查看調用關係及服務基礎狀態。
拓撲圖還有個扁平展現效果(很適合ppt介紹有沒有)
儀表盤看服務狀態:
追蹤欄看調用明細:
失敗調用還有錯誤日誌:
告警欄速覽全局風險:
吹完療效,看下怎麼配置,先看server。
下載最新的skywalking,選了6.4,一開選的6.1有bug,拓撲圖常常出不來。server的運行能夠運行在容器內,也能夠運行虛擬服務器譬如ECS上。server的配置主要是存儲相關,mysql和es任選一個,看數據量和操做便捷性,數據量可控的狀況下,簡單起見,直接用mysql,換掉innodb引擎便可。
server的訪問端口分別是:11800和12800,分別是gRPC和rest端口,若是改了,須要經過修改後面config的訪問端口。這裏提示開防火牆端口。
Agent的一樣有兩種方式,一種是將agent打在鏡像中,微服務的鏡像基於這個鏡像;另外一種是直接copy到一個共享目錄,每一個微服務啓動參數增長指向。第二種方式在測試環境比較實用,生產環境基本上用鏡像更合適,由於微服務運行在容器中,訪問共享目錄不現實。
無論選擇哪一種方式,config的配置是關鍵。
agentName須要和微服務參數指定的一致。後臺服務地址指向oapserver。
最後一步,微服務啓動參數增長agent指向:
-Dskywalking.agent.application_code=agent-test
這個agent-test就是agentname,須要和agent配置的name一致!
非容器方式的配置主要就這三步,完事就能夠看到效果了。固然,服務以前的調用,須要用spring提供的restTemplate,不要直接用apache的httpclient工具包,不然不會被採集。關於容器環境的部署,後面抽空再補記錄。