服務鏈路追蹤
一、服務追蹤說明
微服務架構是通過業務來劃分服務的,使⽤REST調⽤。對外暴露的⼀個接⼝,可能需要很多個服務協同才能完成這個接⼝功能,如果鏈路上任何⼀個服務出現問題或者⽹絡超時,都會形成導致接⼝調⽤失敗。
隨着業務的不斷擴張,服務之間互相調⽤會越來越複雜,它們之間的調⽤關係也許如下:
隨着服務的越來越多,對調⽤鏈的分析會越來越複雜。
二、Zipkin
1、ZipKin是⼀個開放源代碼的分佈式跟蹤系統,由Twitter公司開源,它致⼒於收集服務的定時數據,以解決微服務架構中的延遲問題,包括數據的收集、存儲、查找和展現。它的理論模型來⾃於 Google Dapper 論⽂。2、每個服務向 ZipKin 報告計時數據,ZipKin 會根據調⽤關係通過 ZipKin UI ⽣成依賴關係圖,顯示了多少跟蹤請求通過每個服務,該系統讓開發者可通過⼀個 Web 前端輕鬆的收集和分析數據,例如⽤戶每次請求服務的處理時間等,可⽅便的監測系統中存在的瓶頸
三、搭建zipkin服務器
1、創建SpringBoot項⽬(版本2.1.x)
2、添加依賴
<dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> <version>2.11.10</version> </dependency> <!--zipkin界⾯--> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> <version>2.11.10</version> </dependency>3、在啓動類添加 @EnableZipkinServer 註解
@SpringBootApplication @EnableZipkinServer public class ZipkinApplication { public static void main(String[] args) { SpringApplication.run(ZipkinApplication.class, args); } }4、配置yml
spring: application: name: zipkin server: port: 9411 management: endpoints.web.exposure.include: '*' metrics.web.server.auto-time-requests: false
四、服務中Sleuth配置
1、在服務應⽤中添加Sleuth依賴
<!-- spring-cloud-sleuth-zipkin --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> <version>2.0.2.RELEASE</version> </dependency>
2、在服務應⽤中配置yml
spring: application: name: goods-provider zipkin: enabled: true base-url: 'http://localhost:9411' sleuth: sampler: probability: 0.1
五、zipkin服務數據存儲
1、創建數據庫數據表
CREATE TABLE IF NOT EXISTS zipkin_spans ( `trace_id` BIGINT NOT NULL, `id` BIGINT NOT NULL, `name` VARCHAR(255) NOT NULL, `parent_id` BIGINT, `debug` BIT(1), `start_ts` BIGINT COMMENT & quot; Span.timestamp(): epoch micros used for endTs query and to implement TTL & quot;, `duration` BIGINT COMMENT & quot; Span.duration(): micros used for minDuration and maxDuration query & quot; ) ENGINE = InnoDB ROW_FORMAT = COMPRESSED; ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id`, `id`) COMMENT & quot; ignore insert on duplicate & quot;; ALTER TABLE zipkin_spans ADD INDEX(`trace_id`, `id`) COMMENT & quot; for joining with zipkin_annotations & quot;; ALTER TABLE zipkin_spans ADD INDEX(`trace_id`) COMMENT & quot; for getTracesByIds & quot;; ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT & quot; for getTraces and getSpanNames & quot;; ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT & quot; for getTraces ordering and range & quot;; CREATE TABLE IF NOT EXISTS zipkin_annotations ( `trace_id` BIGINT NOT NULL COMMENT & quot; coincides with zipkin_spans.trace_id & quot;, `span_id` BIGINT NOT NULL COMMENT & quot; coincides with zipkin_spans.id & quot;, `a_key` VARCHAR(255) NOT NULL COMMENT & quot; BinaryAnnotation.key or Annotation.value if type == -1 & quot;, `a_value` BLOB COMMENT & quot; BinaryAnnotation.value(), which must be smaller than 64KB & quot;, `a_type` INT NOT NULL COMMENT & quot; BinaryAnnotation.type() or -1 if Annotation & quot;, `a_timestamp` BIGINT COMMENT & quot; Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp & quot;, `endpoint_ipv4` INT COMMENT & quot; Null when Binary / Annotation.endpoint is null & quot;, `endpoint_ipv6` BINARY(16) COMMENT & quot; Null when Binary / Annotation.endpoint is null, or no IPv6 address & quot;, `endpoint_port` SMALLINT COMMENT & quot; Null when Binary / Annotation.endpoint is null & quot;, `endpoint_service_name` VARCHAR(255) COMMENT & quot; Null when Binary / Annotation.endpoint is null & quot; ) ENGINE = InnoDB ROW_FORMAT = COMPRESSED; ALTER TABLE zipkin_annotations ADD UNIQUE KEY( `trace_id`, `span_id`, `a_key`, `a_timestamp` ) COMMENT & quot; Ignore insert on duplicate & quot;; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`) COMMENT & quot; for joining with zipkin_spans & quot;; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`) COMMENT & quot; for getTraces / ByIds & quot;; ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT & quot; for getTraces and getServiceNames & quot;; ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT & quot; for getTraces & quot;; ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT & quot; for getTraces & quot;; CREATE TABLE IF NOT EXISTS zipkin_dependencies ( `day` DATE NOT NULL, `parent` VARCHAR(255) NOT NULL, `child` VARCHAR(255) NOT NULL, `call_count` BIGINT ) ENGINE = InnoDB ROW_FORMAT = COMPRESSED; ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);
2、pom依賴
<!-- zipkin-storage-mysql-v1 --> <dependency> <groupId>io.zipkin.zipkin2</groupId> <artifactId>zipkin-storage-mysql-v1</artifactId> <version>2.11.12</version> </dependency> <!--mysql驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
3、配置yml
spring: application: name: zipkin datasource: username: root password: admin123 driver-class-name: com.mysql.jdbc.Driver url: 'jdbc:mysql://localhost:3306/zipkin' zipkin: storage: type: mysql