摘要: 本文簡(jiǎn)單介紹了如何利用Zipkin對(duì)SpringCloud應(yīng)用進(jìn)行服務(wù)分析。在實(shí)際的應(yīng)用場(chǎng)景中,Zipkin可以結(jié)合壓力測(cè)試工具一起使用,分析系統(tǒng)在大壓力下的可用性和性能。

設(shè)想這么一種情況,如果你的微服務(wù)數(shù)量逐漸增大,服務(wù)間的依賴關(guān)系越來(lái)越復(fù)雜,怎么分析它們之間的調(diào)用關(guān)系及相互的影響?
服務(wù)追蹤分析
一個(gè)由微服務(wù)構(gòu)成的應(yīng)用系統(tǒng)通過服務(wù)來(lái)劃分問題域,通過REST請(qǐng)求服務(wù)API來(lái)連接服務(wù)來(lái)完成完整業(yè)務(wù)。對(duì)于入口的一個(gè)調(diào)用可能需要有多個(gè)后臺(tái)服務(wù)協(xié)同完成,鏈路上任何一個(gè)調(diào)用超時(shí)或出錯(cuò)都可能造成前端請(qǐng)求的失敗。服務(wù)的調(diào)用鏈也會(huì)越來(lái)越長(zhǎng),并形成一個(gè)樹形的調(diào)用鏈。

隨著服務(wù)的增多,對(duì)調(diào)用鏈的分析也會(huì)越來(lái)越負(fù)責(zé)。設(shè)想你在負(fù)責(zé)下面這個(gè)系統(tǒng),其中每個(gè)小點(diǎn)都是一個(gè)微服務(wù),他們之間的調(diào)用關(guān)系形成了復(fù)雜的網(wǎng)絡(luò)。

有密集恐懼癥的同學(xué)就忽略吧。
針對(duì)服務(wù)化應(yīng)用全鏈路追蹤的問題,Google發(fā)表了Dapper論文,介紹了他們?nèi)绾芜M(jìn)行服務(wù)追蹤分析。其基本思路是在服務(wù)調(diào)用的請(qǐng)求和響應(yīng)中加入ID,標(biāo)明上下游請(qǐng)求的關(guān)系。利用這些信息,可以可視化地分析服務(wù)調(diào)用鏈路和服務(wù)間的依賴關(guān)系。
Spring Cloud Sleuth和Zipkin
對(duì)應(yīng)Dpper的開源實(shí)現(xiàn)是Zipkin,支持多種語(yǔ)言包括JavaScript,Python,Java, Scala, Ruby, C#, Go等。其中Java由多種不同的庫(kù)來(lái)支持。
在這個(gè)示例中,我們準(zhǔn)備開發(fā)兩個(gè)基于Spring Cloud的應(yīng)用,利用Spring Cloud Sleuth來(lái)和Zipkin進(jìn)行集成。Spring Cloud Sleuth是對(duì)Zipkin的一個(gè)封裝,對(duì)于Span、Trace等信息的生成、接入HTTP Request,以及向Zipkin Server發(fā)送采集信息等全部自動(dòng)完成。
這是Spring Cloud Sleuth的概念圖。

服務(wù)REST調(diào)用
本次演示的服務(wù)有兩個(gè):tracedemo做為前端服務(wù)接收用戶的請(qǐng)求,tracebackend為后端服務(wù),tracedemo通過http協(xié)議調(diào)用后端服務(wù)。
利用RestTemplate進(jìn)行HTTP請(qǐng)求調(diào)用
tracedemo應(yīng)用通過restTemplate調(diào)用后端tracedemo服務(wù),注意,URL中指明tracedemo的地址為backend
。
@RequestMapping("/")public String callHome(){ LOG.log(Level.INFO, "calling trace demo backend"); return restTemplate.getForObject("http://backend:8090", String.class);}
后端服務(wù)響應(yīng)HTTP請(qǐng)求,輸出一行日志后返回經(jīng)典的“hello world”。
@RequestMapping("/")public String home(){ LOG.log(Level.INFO, "trace demo backend is being called"); return "Hello World.";}
引入Sleuth和Zipkin依賴包
可以看到,這是典型的兩個(gè)spring應(yīng)用通過RestTemplate進(jìn)行訪問的方式,哪在HTTP請(qǐng)求中注入追蹤信息并把相關(guān)信息發(fā)送到Zipkin Server呢?答案在兩個(gè)應(yīng)用所加載的JAR包里。
本示例采用gradle來(lái)構(gòu)建應(yīng)用,在build.gradle中加載了sleuth和zipkin相關(guān)的JAR包:
dependencies { compile('org.springframework.cloud:spring-cloud-starter-sleuth') compile('org.springframework.cloud:spring-cloud-sleuth-zipkin') testCompile('org.springframework.boot:spring-boot-starter-test')}
Spring應(yīng)用在監(jiān)測(cè)到Java依賴包中有sleuth和zipkin后,會(huì)自動(dòng)在RestTemplate的調(diào)用過程中向HTTP請(qǐng)求注入追蹤信息,并向Zipkin Server發(fā)送這些信息。
哪么Zipkin Server的地址又是在哪里指定的呢?答案是在application.properties中:
spring.zipkin.base-url=http://zipkin-server:9411
注意Zipkin Server的地址為zipkin-server
。
構(gòu)建Docker鏡像
為這兩個(gè)服務(wù)創(chuàng)建相同的Dockerfile,用于生成Docker鏡像:
FROM java:8-jre-alpineRUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositoriesVOLUME /tmpADD build/libs/*.jar app.jarRUN sh -c 'touch /app.jar'ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
構(gòu)建容器鏡像的步驟如下:
cd tracedemo./gradlew builddocker build -t zipkin-demo-frontend .cd ../tracebackend./gradlew builddocker build -t zipkin-demo-backend .
構(gòu)建鏡像完成后用docker push
命令上傳到你的鏡像倉(cāng)庫(kù)。
Zipkin Server
利用Annotation聲明方式創(chuàng)建Zipkin
在build.gradle中引入Zipkin依賴包。
dependencies { compile('org.springframework.boot:spring-boot-starter') compile('io.zipkin.java:zipkin-server') runtime('io.zipkin.java:zipkin-autoconfigure-ui') testCompile('org.springframework.boot:spring-boot-starter-test')}
在主程序Class增加一個(gè)注解@EnableZipkinServer
@SpringBootApplication@EnableZipkinServerpublic class ZipkinApplication { public static void main(String[] args) { SpringApplication.run(ZipkinApplication.class, args); }}
在application.properties
將端口指定為9411。
server.port=9411
構(gòu)建Docker鏡像
Dockerfile和前面的兩個(gè)服務(wù)一樣,這里就不重復(fù)了。
在阿里云容器服務(wù)上部署
創(chuàng)建docker-compose.yml文件,內(nèi)容如下:
version: "2"services: zipkin-server: image: registry.cn-hangzhou.aliyuncs.com/jingshanlb/zipkin-demo-server labels: aliyun.routing.port_9411: http://zipkin restart: always frontend: image: registry.cn-hangzhou.aliyuncs.com/jingshanlb/zipkin-demo-frontend labels: aliyun.routing.port_8080: http://frontend links: - zipkin-server - backend restart: always backend: image: registry.cn-hangzhou.aliyuncs.com/jingshanlb/zipkin-demo-backend links: - zipkin-server restart: always
在阿里云容器服務(wù)上使用編排模版創(chuàng)建
應(yīng)用,訪問zipkin端點(diǎn),可以看到服務(wù)分析的效果。
訪問前端應(yīng)用3次,頁(yè)面顯示3次服務(wù)調(diào)用。

點(diǎn)擊其中任意一個(gè)trace,可以看到請(qǐng)求鏈路上不同span所花費(fèi)的時(shí)間。

進(jìn)入Dependencies頁(yè)面,還可以看到服務(wù)之間的依賴關(guān)系。

從這個(gè)過程可以看出,Zipkin和Spring Cloud的集成做得很好。而且對(duì)服務(wù)追蹤分析的可視化也很直觀。
注意的是,在生產(chǎn)環(huán)境中還需要為Zipkin配置數(shù)據(jù)庫(kù),這里就不詳細(xì)介紹了。
本文的示例代碼在此:https://github.com/binblee/zipkin-demo
小節(jié)
本文簡(jiǎn)單介紹了如何利用Zipkin對(duì)SpringCloud應(yīng)用進(jìn)行服務(wù)分析。在實(shí)際的應(yīng)用場(chǎng)景中,Zipkin可以結(jié)合壓力測(cè)試工具一起使用,分析系統(tǒng)在大壓力下的可用性和性能。這部分內(nèi)容未來(lái)會(huì)在DevOps系列中繼續(xù)介紹。