Spring Cloud 链路追踪

    科技2022-09-03  115

    链路追踪

    一、概念1.1 链路追踪1.2 各种系统 二、重要概念三、实现(sleuth+zipkin)sleuth1.概念2.依赖和配置 zipkin1.概念2.zipkin架构图2.使用Zipkin ServerZipkin Client 问题和优化问题优化

    一、概念

    1.1 链路追踪

    用户->网关->A->B->C->D

    分布式系统中一次调用会非常的复杂。我们需要更好的发现问题,定位问题是在哪个微服务中出现的。分析在各个定义节点的耗时确认性能瓶颈等。

    分布式链路追踪,就是将一次分布式请求还原成调用链路,进行日志记录,性能监控并将 一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等等。

    1.2 各种系统

    目前业界比较流行的链路追踪系统如:Twitter的Zipkin,阿里的鹰眼,美团的Mtrace,大众点评的 cat等,大部分都是基于google发表的Dapper。Dapper阐述了分布式系统,特别是微服务架构中链路 追踪的概念、数据表示、埋点、传递、收集、存储与展示等技术细节。

    二、重要概念

    trace 整个调用链路

    完整的一次调用,比如用户A->网关->B->C 可以定义为 traceid:1

    span 最小的工作单元(链路中的一个节点的调用)

    用户A->网关 spanid:1

    网关->B spanid:2

    B->C spanid:3

    三、实现(sleuth+zipkin)

    sleuth

    1.概念

    Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只 需要在pom文件中引入相应的依赖即可。

    2.依赖和配置

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> logging: level: root: INFO org.springframework.web.servlet.DispatcherServlet: DEBUG org.springframework.cloud.sleuth: DEBUG

    zipkin

    1.概念

    Zipkin 是 Twitter 的一个开源项目,它基于 Google Dapper 实现,它致力于收集服务的定时数据,以 解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。 我们可以使用它来收集各个服务 器上请求链路的跟踪数据,并通过它提供的 REST API 接口来辅助我们查询跟踪数据以实现对分布式系 统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。除了面向开发 的 API 接口之外,它也提供了方便的 UI 组件来帮助我们直观的搜索跟踪信息和分析请求链路明细,比 如:可以查询某段时间内各用户请求的处理时间等。 Zipkin 提供了可插拔数据存储方式:InMemory、MySql、Cassandra 以及 Elasticsearch。

    主要是收集链路追踪的日志然后进行存储展示等功能

    2.zipkin架构图

    Collector:收集器组件,它主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为

    Zipkin 内部处理的 Span 格式,以支持后续的存储、分析、展示等功能。

    Storage:存储组件,它主要对处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中,

    我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到数据库中。

    RESTful API:API 组件,它主要用来提供外部访问接口。比如给客户端展示跟踪信息,或是外接

    系统访问以实现监控等。

    Web UI:UI 组件,基于 API 组件实现的上层应用。通过 UI 组件用户可以方便而有直观地查询和

    分析跟踪信息。 每个被追踪的微服务作为zipkin客户端,收集数据处理数据的是zipkin的服务端

    2.使用

    Zipkin Server

    从spring boot 2.0开始,官方就不再支持使用自建Zipkin Server的方式进行服务链路追踪,而是直接提 供了编译好的 jar 包来给我们使用。可以从官方网站下载先下载Zipkin的web UI,我们这里下载的是 zipkin-server-2.12.9-exec.jar

    启动命令

    在命令行输入 java -jar zipkin-server-2.12.9-exec.jar 启动 Zipkin Server

    默认Zipkin Server的请求端口为 9411

    下载地址

    https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml

    Zipkin Client

    依赖

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> spring: zipkin: base-url: http://127.0.0.1:9411/ #zipkin server的请求地址 sender: type: web #请求方式,默认以http的方式向zipkin server发送追踪数据 sleuth: sampler: probability: 1.0 #采样的百分比 生产环境中不用1.0

    问题和优化

    问题

    1.http请求和fegin调用的时候,会出现问题(源码级别)

    2.放入内存中,关闭了就没了

    优化

    使用rabbitmq发生和接收日志

    Server

    启动 Zipkin Server时指定rabbitmq地址和用户密码信息

    java -jar zipkin-server-2.12.9-exec.jar --RABBIT_ADDRESSES=127.0.0.1:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest java -jar zipkin-server-2.12.9-exec.jar --RABBIT_ADDRESSES=192.168.200.128:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest

    Client

    依赖

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> </dependency>

    配置rabbitmq相关信息

    spring: zipkin: base-url: http://127.0.0.1:9411/ #zipkin server的请求地址 sender: type: rabbit #请求方式,默认以http的方式向zipkin server发送追踪数据 rabbitmq: host: 192.168.200.128 #自己rabbitmq的ip地址 port: 5672 username: guest password: guest listener: direct: retry: enabled: true simple: retry: enabled: true

    数据存储到mysql

    创建数据库表

    创建数据库zipkin 然后执行下面的sql 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, `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' ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate'; ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations'; 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(`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'; ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces'; 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 ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);

    启动 Zipkin Server时指定mysql相关信息

    只吧数据存储到mysql的启动命令,里面没有配置rabbit的信息 java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql -- MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root - -MYSQL_PASS=111111 STORAGE_TYPE : 存储类型 MYSQL_HOST: mysql主机地址 MYSQL_TCP_PORT:mysql端口 MYSQL_DB: mysql数据库名称 MYSQL_USER:mysql用户名 MYSQL_PASS :mysql密码 java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=root --RABBIT_ADDRESSES=192.168.200.128:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest
    Processed: 0.010, SQL: 9