SpringCloud集成sleuth和zipkin實現(xiàn)微服務鏈路追蹤的實戰(zhàn)分享
技術積累
spring cloud sleuth介紹
Sleuth是Spring cloud的分布式跟蹤解決方案。
1.span(跨度),基本工作單元。一次鏈路調用,創(chuàng)建一個span,span用一個64位id唯一標識。包括:id,描述,時間戳事件,spanld,span父id.span被啟動和停止時,記錄了時間信息,初始化span叫:rootspan,它的span id和trace id相等。
2.trace(跟蹤),一組共享"root span”的span組成的樹狀結構稱為 trace,trace也有一個64位ID,trace中所有span共享一個trace id。類似于一顆 span 樹。
3.annotation (標簽),annotation用來記錄事件的存在,其中,核心annotation用來定義請求的開始和結束CS(Client Send客戶端發(fā)起請求)??蛻舳税l(fā)起請求描述了span開始,
SR(Server Received服務端接到請求)。服務端獲得請求并準備處理它。SR-CS=網(wǎng)絡延遲SS(Server Send服務器端處理完成,并將結果發(fā)送給客戶端)。表示服務器完成請求處理,響應客戶端時。SS-SR=服務器處理請求的時間,
CR(Client Received 客戶端接受服務端信息)。span結束的標識??蛻舳私邮盏椒掌鞯捻憫?。CR-CS=客戶端發(fā)出請求到服務器響應的總時間。
其實數(shù)據(jù)結構是一顆樹,從root span 開始。
工具定位
Spring Cloud Sleuth是一個用于Spring Cloud應用程序的分布式追蹤工具,它主要專注于在服務間傳播追蹤信息。
主要功能
傳播追蹤上下文:在服務調用間傳遞Trace ID和Span ID,確保整個請求鏈路的追蹤信息保持一致。
集成日志框架:修改日志框架的配置,使得日志記錄中包含Trace和Span的ID。
與Spring Cloud生態(tài)集成:與Spring Cloud的其他組件(如Ribbon、Hystrix、Zuul等)無縫集成。
依賴性:Sleuth是為Spring Cloud應用程序設計的,它依賴于Spring框架和Spring Boot。
zipkin介紹
Zipkin是一款開源的分布式實時數(shù)據(jù)追蹤系統(tǒng)(Distributed Tracking System),基于 Google Dapper的論文設計而來,由 Twitter 公司開發(fā)貢獻。其主要功能是聚集來自各個異構系統(tǒng)的實時監(jiān)控數(shù)據(jù)。
工具定位
Zipkin是一個分布式追蹤系統(tǒng),它提供了追蹤數(shù)據(jù)的收集、存儲、查找和展示功能。
主要功能
收集追蹤數(shù)據(jù):Zipkin通過其客戶端庫(如Brave)收集追蹤數(shù)據(jù)。
存儲追蹤數(shù)據(jù):支持多種存儲方案,如內存、MySQL、Cassandra、Elasticsearch等。
查詢和展示:提供Web界面,用于查詢追蹤數(shù)據(jù),并以可視化的方式展示服務間的調用關系和延遲。
獨立性:Zipkin可以獨立于任何應用程序或框架運行,并且可以與多種編程語言和框架集成。
zipkin 官網(wǎng)
https://zipkin.io/pages/quickstart.html
Zipkin與Sleuth的協(xié)作
數(shù)據(jù)收集:Sleuth負責在Spring Cloud應用程序中生成和傳播追蹤數(shù)據(jù),而Zipkin負責收集這些數(shù)據(jù)。
數(shù)據(jù)展示:Sleuth生成的追蹤數(shù)據(jù)可以通過Zipkin的Web界面進行查詢和展示。
集成:在Spring Cloud應用程序中,Sleuth通常與Zipkin一起使用,Sleuth負責追蹤信息的生成和傳播,Zipkin負責存儲和展示。
SpringCloud多模塊搭建
多模塊微服務項目結構
新增父項目來管理微服務各個模塊
#父模塊pom必須聲明
pom
新增子模塊
Zipkin Server部署
由于springcloud F版本不支持自定義zipkin server,故我們采用docker鏡像進行部署zipkin server。
docker pull 鏡像
docker pull openzipkin/zipkin:latest
啟動zipkin server
未持久化(內存):
docker run --name zipkin-server -d --restart=always -p 9411:9411 openzipkin/zipkin:latest
http://127.0.0.1:9411/zipkin/
持久化到MySQL5:
docker run --name zipkin-server-mysql -d --restart=always -p 19411:9411 -e MYSQL_USER=root -e MYSQL_PASS=12345678 -e MYSQL_HOST=127.0.0.1 -e STORAGE_TYPE=mysql -e MYSQL_DB=zipkin -e MYSQL_TCP_PORT=13306 openzipkin/zipkin:3.3
mysql DD語句如下:
https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql -- -- Copyright The OpenZipkin Authors -- SPDX-License-Identifier: Apache-2.0 -- CREATE TABLE IF NOT EXISTS zipkin_spans ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', `trace_id` BIGINT NOT NULL, `id` BIGINT NOT NULL, `name` VARCHAR(255) NOT NULL, `remote_service_name` VARCHAR(255), `parent_id` BIGINT, `debug` BIT(1), `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL', `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query', PRIMARY KEY (`trace_id_high`, `trace_id`, `id`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds'; ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames'; ALTER TABLE zipkin_spans ADD INDEX(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames'; ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range'; CREATE TABLE IF NOT EXISTS zipkin_annotations ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id', `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id', `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1', `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB', `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation', `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp', `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null', `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address', `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null', `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null' ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds'; ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames'; ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces and autocomplete values'; ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job'; CREATE TABLE IF NOT EXISTS zipkin_dependencies ( `day` DATE NOT NULL, `parent` VARCHAR(255) NOT NULL, `child` VARCHAR(255) NOT NULL, `call_count` BIGINT, `error_count` BIGINT, PRIMARY KEY (`day`, `parent`, `child`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
持久化到ES:
docker run --name zipkin-server-es -d -p 19411:9411 --restart=always -e STORAGE_TYPE=elasticsearch -e ES_HOSTS=127.0.0.1:9200 openzipkin/zipkin:latest
JAR運行:
curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=12345678
我們測試選擇不持久化
docker run -d -p 9411:9411 --name zipkinServer --restart=always openzipkin/zipkin
3、啟動完成
SpringCloud 接入 Sleuth 與 Zipkin
pom引入依賴 (springboot2.6+)
<properties> <spring-cloud.version>2021.0.5</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> <version>3.1.10</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> <version>3.1.10</version> </dependency> </dependencies>
appilication.yml配置修改
spring: zipkin: #zipkin服務所在地址 base-url: http://127.0.0.1:9411/ sender: type: web #使用http的方式傳輸數(shù)據(jù) #配置采樣百分比 sleuth: sampler: probability: 1 # 將采樣比例設置為 1.0,也就是全部都需要。默認是0.1也就是10%,一般情況下,10%就夠用了 ##打開debug日志 logging: level: org.springframework.web.servlet.DispatcherServlet: Debug
type=web也就是通過 HTTP 的方式發(fā)送數(shù)據(jù)到 Zipkin 。
如果請求量比較大,這種方式其實性能是比較低的,一般情況下我們都是通過消息中間件來發(fā)送,比如 RabbitMQ 。如果日志數(shù)據(jù)量比較大,一般推薦擁有更高吞吐量的 Kafka 來進行日志推送。這種方式就是讓服務將 Sleuth 收集的日志推給 MQ ,讓 Zipkin 去監(jiān)控 MQ 的信息,通過 MQ 的隊列獲取到服務的信息。這樣就提高了性能。
而日志的存儲則可以采用mysql、 Elasticsearch 對數(shù)據(jù)進行持久化,這樣可以保證 Zipkin 重啟后,鏈路信息不會丟失。
增加測試鏈路代碼
鏈路為:
user-service --> order-service --> finance-service
user-service增加請求入口getOrderAmount:
/** * 計算訂單金額 * @param orderId * @author senfel * @date 2024/12/9 18:25 * @return java.lang.String */ @RequestMapping("/getOrderAmount") public String getOrderAmount(@RequestParam(name = "orderId") String orderId) { return orderService.getOrderAmount(orderId); }
user-service增加feign調用order-service:
/** * FeeService * @author senfel * @version 1.0 * @date 2024/12/9 18:02 */ @FeignClient(name = "order-service",fallback = OrderServiceFallback.class) public interface getOrderAmount { /** * 獲取訂單金額 * @param orderId * @author senfel * @date 2024/12/9 18:06 * @return java.lang.String */ @RequestMapping(value = "/order/getOrderAmount",method = RequestMethod.GET) String getOrderAmount(@RequestParam(name = "orderId") String orderId); }
order-service增加調用入口getOrderAmount:
/** * 獲取訂單金額 * @param orderId * @author senfel * @date 2024/12/9 18:06 * @return java.lang.String */ @RequestMapping(value = "/getOrderAmount",method = RequestMethod.GET) public String getOrderAmount(@RequestParam(name = "orderId") String orderId){ return financeService.getFee(orderId); }
order-service增加feign調用finance-service:
/** * FinanceService * @author senfel * @version 1.0 * @date 2024/12/9 18:10 */ @FeignClient(name = "finance-service",fallback = FinanceServiceFallback.class) public interface FinanceService { /** * 獲取費用 * @param orderId * @author senfel * @date 2024/12/9 18:12 * @return java.lang.String */ @RequestMapping(value = "/finance/getFee",method = RequestMethod.GET) String getFee(@RequestParam(name = "orderId") String orderId); }
finance-service增加請求入口getFee:
/** * 獲取費用 * @param orderId * @author senfel * @date 2024/12/9 18:12 * @return java.lang.String */ @RequestMapping(value = "/getFee",method = RequestMethod.GET) public String getFee(@RequestParam(name = "orderId") String orderId) { return "100"; }
調用微服務進行驗證
啟動微服務調用getOrderAmount()
進入zipkin界面查看請求調用鏈路和各個階段耗時
至此,我們已經(jīng)完微服務鏈路追蹤實戰(zhàn).。
以上就是SpringCloud集成sleuth和zipkin實現(xiàn)微服務鏈路追蹤的實戰(zhàn)分享的詳細內容,更多關于SpringCloud sleuth和zipkin鏈路追蹤的資料請關注腳本之家其它相關文章!
相關文章
超簡單的java獲取鼠標點擊位置坐標的實例(鼠標在Jframe上的坐標)
在Java窗體Jframe上獲取鼠標點擊的坐標,其中使用了匿名內部類,實例代碼非常簡單易懂,大家可以學習一下2018-03-03