這是SpringCloud實戰系列中第7篇文章,瞭解前面第兩篇文章更有助於更好理解本文內容:
①SpringCloud 實戰:引入Eureka組件,完善服務治理
②SpringCloud 實戰:引入Feign組件,發起服務間調用
③SpringCloud 實戰:使用 Ribbon 客戶端負載均衡
④SpringCloud 實戰:引入Hystrix組件,分佈式系統容錯
⑤SpringCloud 實戰:引入Zuul組件,開啓網關路由
⑥SpringCloud 實戰:引入gateway組件,開啓網關路由功能html
近年來,隨着微服務架構的流行,不少公司都走上了微服務拆分之路。從而使系統變得愈來愈複雜,本來單體的系統被拆成不少個服務,每一個服務之間經過輕量級的 HTTP 協議進行交互。java
單體架構時,一個請求的調用鏈路很是清晰,通常由負載均衡器,好比 Nginx。將調用方的請求轉發到後端服務,後端服務進行業務處理後返回給調用方。而當架構變成微服務架構時,可能帶來一系列的問題,好比下面三個問題:spring
分佈式鏈路跟蹤原理在於如何能將請求通過的服務節點都關聯起來。當一個請求從客戶端到達網關後,至關因而第一個入口,這時就須要生成一個惟一的請求 ID,做爲此次請求的標識。從網關到達服務 A 後,確定是須要將請求 ID 傳遞到服務 A 中的,這樣才能將網關到服務 A 的請求關聯起來,依次類推,後面會通過多層服務,都須要將信息一層層傳遞。固然在每一層都須要將數據進行上報、統一存儲、展現等操做。後端
從咱們對這個需求的理解來看,鏈路跟蹤並非很複雜,而複雜的點在於如何實現這一套跟蹤框架,就拿請求信息傳遞這件事來講,服務之間交互,有的用的是 Feign 調用接口,有的用的是 RestTemplate 調用接口,要想將信息傳遞到下游服務,那麼必須得擴展這些調用的框架才能夠。bash
Span服務器
基本工做單元,例如,發送 RPC 請求是一個新的 Span,發送 HTTP 請求是一個新的 Span,內部方法調用也是一個新的 Span。網絡
Trace架構
一次分佈式調用的鏈路信息,每次調用鏈路信息都會在請求入口處生成一個 TraceId
。負載均衡
Annotation框架
用於記錄事件的信息。在 Annotation 中會有 CS、SR、SS、CR 這些信息,前面的C表示客戶端,S表示服務器端; 後面的S表示sent,也就是發起請求時的動做,R表示Received,也就是接受到請求時的動做;下面分別介紹下這些信息的做用。
Client Sent
,客戶端發起一個請求,這個 Annotation 表示 Span 的開始。Client Received
,表示 Span 的結束,客戶端已成功從服務器端收到響應,用 CR 的時間戳減去 CS 的時間戳就能夠知道客戶端從服務器接收響應所需的所有時間。Server Sent
,在請求處理完成時將響應發送回客戶端,用 SS 的間戳減去 SR 的時間戳會顯示服務器端處理請求所需的時間。Server Received
,服務器端得到請求並開始處理它,用 SR 的時間戳減去 CS 的時間戳會顯示網絡延遲時間。Zipkin
是 Twitter
的一個開源項目,是一個致力於收集全部服務監控數據的分佈式跟蹤系統,它提供了收集數據和查詢數據兩大接口服務。有了 Zipkin
咱們就能夠很直觀地查看調用鏈,而且可能很方便看出服務之間的調用關係,以及調用耗費的時間。
Zipkin還提供了可插拔數據存儲方式:In-Memory、MySql、Cassandra以及Elasticsearch。測試方即可直接採用In-Memory方式進行存儲,生產推薦使用Elasticsearch。
若是使用了 Java 8 或者更高的版本,能夠獲取最新的可執行 jar 包來進行啓動。
下載jar包:
curl -sSL https://zipkin.io/quickstart.sh | bash -s
若是下載太慢,能夠直接訪問Maven地址進行下載最新的jar。
其餘方式安裝,能夠查看官網的quickstart。
啓動服務
java -jar zipkin.jar
訪問Zipkin
成功啓動服務後,訪問http://127.0.0.1:9411/zipkin/便可。
Spring Cloud Sleuth
是一種分佈式的服務鏈路跟蹤解決方案,經過使用 Spring Cloud Sleuth 可讓咱們快速定位某個服務的問題,以及釐清服務間的依賴關係。
Sleuth
能夠添加鏈路信息到日誌中,這樣的好處是能夠統一將日誌進行收集展現,而且能夠根據鏈路的信息將日誌進行串聯。
Sleuth 中的鏈路數據可直接上報給 Zipkin
,在 Zipkin
中就能夠直接查看調用關係和每一個服務的耗時狀況.
Sleuth 中內置了不少框架的埋點,好比:Zuul、Feign、Hystrix、RestTemplate
等。正由於有了這些框架的埋點,鏈路信息才能一直往下傳遞。
在咱們的微服務項目中添加Zipkin依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
配置Zipkin地址
spring.zipkin.base-url=http://127.0.0.1:9411/
配置採樣比例
實際使用中可能調用了 10 次接口,可是 Zipkin 中只有一條數據,這是由於收集信息是有必定比例的,Zipkin 中的數據條數與調用接口次數默認比例是 10:1,經過下面的配置來改變這個比例值:
spring.sleuth.sampler.probability=1.0
驗證
啓動咱們的微服務,訪問 http://localhost:9000/eureka-client/sayHello 接口,接口由網關路由到eureka-client 服務,eureka-client 服務再調用eureka-provider服務,接口返回eureka-provider服務的端口等信息。
而後訪問 http://127.0.0.1:9411/zipkin ,點擊查詢,便可查看到相關訪問記錄
點擊菜單上面的依賴,能夠查看項目的依賴關係
數據的發送若是採用 HTTP 對性能仍是有影響的。若是Zipkin 的服務端在重啓或者掛掉時,那麼將丟失部分採集數據。爲了解決這些問題,咱們能夠集成 RabbitMQ 或者Kafka 來發送採集數據,利用消息隊列來提升發送性能,保證數據不丟失;
若是要使用RabbitMQ或Kafka而不是HTTP,須要引入spring-rabbit
or spring-kafka
相關依賴。
<dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> </dependency>
而後在配置文件修改相關配置:
# WEB、KAFKA、RABBIT、ACTIVEMQ spring.zipkin.sender.type=kafka
刪除以前配置的 spring.zipkin.base-url
配置kafka、rabbit
每一個跟蹤系統都須要具備Reporter <Span>
和Sender
,若是要覆蓋提供的bean,則須要給它們指定一個特定的名稱 ZipkinAutoConfiguration.REPORTER_BEAN_NAME
and ZipkinAutoConfiguration.SENDER_BEAN_NAME
。
下面是示例:
@Configuration protected static class MyConfig { @Bean(ZipkinAutoConfiguration.REPORTER_BEAN_NAME) Reporter<zipkin2.Span> myReporter() { return AsyncReporter.create(mySender()); } @Bean(ZipkinAutoConfiguration.SENDER_BEAN_NAME) MySender mySender() { return new MySender(); } static class MySender extends Sender { private boolean spanSent = false; boolean isSpanSent() { return this.spanSent; } @Override public Encoding encoding() { return Encoding.JSON; } @Override public int messageMaxBytes() { return Integer.MAX_VALUE; } @Override public int messageSizeInBytes(List<byte[]> encodedSpans) { return encoding().listSizeInBytes(encodedSpans); } @Override public Call<Void> sendSpans(List<byte[]> encodedSpans) { this.spanSent = true; return Call.create(null); } } }