您好,登錄后才能下訂單哦!
這篇文章主要介紹Spring Cloud Sleuth整合zipkin的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
SpringCloud Sleuth 簡(jiǎn)介
Spring Cloud Sleuth為Spring Cloud實(shí)現(xiàn)了分布式跟蹤解決方案。
Spring Cloud Sleuth借鑒了Dapper的術(shù)語。
Span:基本的工作單元。Span包括一個(gè)64位的唯一ID,一個(gè)64位trace碼,描述信息,時(shí)間戳事件,key-value 注解(tags),span處理者的ID(通常為IP)。
Trace:一組Span形成的樹形結(jié)構(gòu)。
Annotation:用于及時(shí)記錄存在的事件。常用的Annotation如下:
cs:客戶端發(fā)送(client send) 客戶端發(fā)起一個(gè)請(qǐng)求,表示span開始
sr:服務(wù)器接收(server received) 服務(wù)器接收到客戶端的請(qǐng)求并開始處理,sr - cs 的時(shí)間為網(wǎng)絡(luò)延遲
ss:服務(wù)器發(fā)送(server send) 服務(wù)器處理完請(qǐng)求準(zhǔn)備返回?cái)?shù)據(jù)給客戶端。ss - sr 的時(shí)間表示服務(wù)器端處理請(qǐng)求花費(fèi)的時(shí)間
cr:客戶端接收(client received) 客戶端接收到處理結(jié)果,表示span結(jié)束。 cr - cs 的時(shí)間表示客戶端接收服務(wù)端數(shù)據(jù)的時(shí)間
下圖展示了Span和Trace在系統(tǒng)中的聯(lián)系
Sleuth 默認(rèn)采用 Http 方式將 span 傳輸給 Zipkin
在application.properties文件中指定
spring.zipkin.sender.type=web
使用 RabbitMQ 異步發(fā)送 span 信息
為什么選擇 RabbitMQ 消息中間件發(fā)送 span 信息
sleuth 默認(rèn)采用 http 通信方式,將數(shù)據(jù)傳給 zipkin 作頁面渲染,但是 http 傳輸過程中如果由于不可抗因素導(dǎo)致 http 通信中斷,那么此次通信的數(shù)據(jù)將會(huì)丟失。而使用中間件的話,RabbitMQ 消息隊(duì)列可以積壓千萬級(jí)別的消息,下次重連之后可以繼續(xù)消費(fèi)。
隨著線程增多,并發(fā)量提升之后,RabbitMQ 異步發(fā)送數(shù)據(jù)明顯更具有優(yōu)勢(shì)。
RabbitMQ 支持消息、隊(duì)列持久化,可以通過消息狀態(tài)落庫、重回隊(duì)列、鏡像隊(duì)列等技術(shù)手段保證其高可用。
示例
示例簡(jiǎn)介
示例包含sleuth-search、sleuth-cart、sleuth-order三個(gè)系統(tǒng),用來模擬電商系統(tǒng)中下單的流程,用戶可以搜索商品然后立即下單,也可以搜索多個(gè)商品后加入購物車,然后下單,調(diào)用情況即 search -> cart -> order,或 search -> order。
示例使用 RestTemplate 來完成三個(gè)系統(tǒng)間的 http 請(qǐng)求響應(yīng),請(qǐng)求方式也都遵循Restful風(fēng)格。
版本說明
版本一定要對(duì)應(yīng)好,一些低版本的SpringBoot無法兼容新版本的SpringCloud和zipkin
工具 | 版本 |
---|---|
SpringBoot | 2.1.6.RELEASE |
SpringCloud | Greenwich.SR3 |
zipkin | 2.16.2 |
項(xiàng)目結(jié)構(gòu)
demo-cloudsleuth |- sleuth-search |- sleuth-cart |- sleuth-order pom.xml
導(dǎo)入依賴
<!-- 引入 springboot 和 springcloud 父工程 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> </dependency> <!-- Springboot 相關(guān) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
配置 RestTemplate,RestTemplate是SpringBoot提供的封裝好的http工具類,可以幫助我們簡(jiǎn)化http的使用。
package com.anqi.cart.resttmplate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return new RestTemplate(factory); } @Bean public ClientHttpRequestFactory clientHttpRequestFactory() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(5000); factory.setReadTimeout(5000); return factory; } }
三個(gè)系統(tǒng)下的application.properties,端口分別是8081 8082 8083
#server.port=8081 server.port=8082 server.port=8083 server.servlet.context-path=/ spring.zipkin.base-url=http://localhost:9411/ spring.zipkin.service.name=sleuth-cart #使用默認(rèn) http 方式收集 span 需要配置此項(xiàng) #spring.zipkin.sender.type=web #sleuth 使用 rabbitmq 來向 zipkin 發(fā)送數(shù)據(jù) spring.zipkin.sender.type=rabbit spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest #設(shè)置采樣率默認(rèn)為 0.1 注意之前的版本是percentage 新版本中更換為 probability spring.sleuth.sampler.probability=1
三個(gè)系統(tǒng)下的RestTemplate的配置,用來簡(jiǎn)化 http 請(qǐng)求
package com.anqi.cart.resttmplate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return new RestTemplate(factory); } @Bean public ClientHttpRequestFactory clientHttpRequestFactory() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(5000); factory.setReadTimeout(5000); return factory; } }
@RequestMapping("cart") @RestController public class CartController { @Autowired RestTemplate restTemplate; @Autowired CartService cartService; private static final String orderUrl = "http://localhost:8084/order/create"; @GetMapping("/add/{cartId}") public String addToCart(@PathVariable("cartId") String cartId) { cartService.addProductToCart(cartId, "小米8"); ResponseEntity<String> res = restTemplate.getForEntity(orderUrl, String.class); return res.getBody(); } }
@RequestMapping("order") @RestController public class OrderController { @GetMapping("/create") public String creatOrder() { System.out.println("create order"); return "create_order"; } }
@RestController public class SearchController { @Autowired RestTemplate restTemplate; private static final String cartUrl = "http://localhost:8083/cart/add/1"; private static final String orderUrl = "http://localhost:8084/order/create"; @GetMapping("/search") public String search() { ResponseEntity<String> cartRes = restTemplate.getForEntity(cartUrl, String.class); ResponseEntity<String> orderRes = restTemplate.getForEntity(orderUrl, String.class); return "cart:" + cartRes.getBody() + "- order:" + orderRes.getBody(); } }
運(yùn)行結(jié)果分析
默認(rèn) http 傳輸 span 信息
啟動(dòng)Zipkin
java -jar zipkin-server-2.16.2-exec.jar
網(wǎng)頁中手動(dòng)訪問
http://localhost:8082/search
我們?cè)L問zipkin站點(diǎn)查詢調(diào)用情況
http://localhost:9411/zipkin/traces/94b954d843012ca9
可以從下圖中完整清晰的看到三個(gè)系統(tǒng)的調(diào)用關(guān)系
下圖為zipkin調(diào)用預(yù)覽,我們請(qǐng)求四次http://localhost:8082/search來更直觀的觀察數(shù)據(jù)。在以下界面中,較為簡(jiǎn)潔的顯示Span的個(gè)數(shù)以及調(diào)用總時(shí)延。
我們進(jìn)入一個(gè)完整的調(diào)用鏈后訪問其中的一個(gè)節(jié)點(diǎn)得到以下數(shù)據(jù)。
以下為一次全鏈路追蹤的詳細(xì)信息,包含7個(gè)span的所有信息,以上看到的頁面展示均有以下數(shù)據(jù)加以渲染而成。
[ { "traceId": "94b954d843012ca9", "parentId": "bab70b1e69a5f3e3", "id": "96387b33a823ca8f", "kind": "SERVER", "name": "get /order/create", "timestamp": 1569060494069123, "duration": 1161, "localEndpoint": { "serviceName": "sletuth-order", "ipv4": "192.168.0.107" }, "remoteEndpoint": { "ipv4": "127.0.0.1", "port": 49863 }, "tags": { "http.method": "GET", "http.path": "/order/create", "mvc.controller.class": "OrderController", "mvc.controller.method": "creatOrder" }, "shared": true }, { "traceId": "94b954d843012ca9", "parentId": "94b954d843012ca9", "id": "90f7e5cfa89e0d80", "kind": "SERVER", "name": "get /order/create", "timestamp": 1569060494076287, "duration": 1296, "localEndpoint": { "serviceName": "sletuth-order", "ipv4": "192.168.0.107" }, "remoteEndpoint": { "ipv4": "127.0.0.1", "port": 49864 }, "tags": { "http.method": "GET", "http.path": "/order/create", "mvc.controller.class": "OrderController", "mvc.controller.method": "creatOrder" }, "shared": true }, { "traceId": "94b954d843012ca9", "parentId": "94b954d843012ca9", "id": "bab70b1e69a5f3e3", "kind": "CLIENT", "name": "get", "timestamp": 1569060494063693, "duration": 10374, "localEndpoint": { "serviceName": "sleuth-search", "ipv4": "192.168.0.107" }, "tags": { "http.method": "GET", "http.path": "/cart/add/1" } }, { "traceId": "94b954d843012ca9", "parentId": "94b954d843012ca9", "id": "90f7e5cfa89e0d80", "kind": "CLIENT", "name": "get", "timestamp": 1569060494074966, "duration": 2848, "localEndpoint": { "serviceName": "sleuth-search", "ipv4": "192.168.0.107" }, "tags": { "http.method": "GET", "http.path": "/order/create" } }, { "traceId": "94b954d843012ca9", "id": "94b954d843012ca9", "kind": "SERVER", "name": "get /search", "timestamp": 1569060494062631, "duration": 16332, "localEndpoint": { "serviceName": "sleuth-search", "ipv4": "192.168.0.107" }, "remoteEndpoint": { "ipv6": "::1", "port": 49859 }, "tags": { "http.method": "GET", "http.path": "/search", "mvc.controller.class": "SearchController", "mvc.controller.method": "search" } }, { "traceId": "94b954d843012ca9", "parentId": "bab70b1e69a5f3e3", "id": "96387b33a823ca8f", "kind": "CLIENT", "name": "get", "timestamp": 1569060494067090, "duration": 3197, "localEndpoint": { "serviceName": "sleuth-cart", "ipv4": "192.168.0.107" }, "tags": { "http.method": "GET", "http.path": "/order/create" } }, { "traceId": "94b954d843012ca9", "parentId": "94b954d843012ca9", "id": "bab70b1e69a5f3e3", "kind": "SERVER", "name": "get /cart/add/{cartid}", "timestamp": 1569060494066140, "duration": 8150, "localEndpoint": { "serviceName": "sleuth-cart", "ipv4": "192.168.0.107" }, "remoteEndpoint": { "ipv4": "127.0.0.1", "port": 49862 }, "tags": { "http.method": "GET", "http.path": "/cart/add/1", "mvc.controller.class": "CartController", "mvc.controller.method": "addToCart" }, "shared": true } ]
使用 RabbitMQ 情況
啟動(dòng) zipkin,注意參數(shù)
java -jar zipkin-server-2.16.2-exec.jar --RABBIT_ADDRESSES=localhost:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_VIRTUAL_HOST=/
啟動(dòng) rabbitmq
rabbitmq-server
在測(cè)試的時(shí)候發(fā)現(xiàn) mq 和以上方式時(shí)延相差無幾,但是隨著線程數(shù)的增加也就是并發(fā)量的增加,mq 傳輸時(shí)延將會(huì)大大低于 http。
以上是“Spring Cloud Sleuth整合zipkin的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。