Zipkin介绍与在SpringCloud alibaba中的使用

Zipkin

在微服务(分布式系统)等多个服务组成的系统中,一个请求是跨多个服务处理的,这样就很难理解整个请求处理流程(可追溯性)。当故障和请求延迟因可追溯性降低而加剧时,这也使得更难找到哪个服务有问题。通过可视化服务间依赖和调用的系统称为分布式跟踪系统,它的作用就是帮助去解决此类问题。

介绍

官网地址:https://zipkin.io/
Zipkin是一个分布式跟踪系统,它能聚集来自各个异构系统的实时监控数据。类似的分布式跟踪系统还有其他比较成熟的实现,例如:Naver的Pinpoint、Apache的HTrace、阿里的鹰眼Tracing、京东的Hydra、新浪的Watchman,美团点评的CAT,skywalking等。

构成

在这里插入图片描述

Reporter

Reporter 负责将日志从您的应用程序转发到 Zipkin 服务器,有三种主要的传输方式:HTTP、Kafka和Scribe。

Collector

跟踪数据到达Zipkin收集器守护进程后,Zipkin收集器将对其进行验证、存储和索引,以便进行查找。

Storage

负责存储的持久化,最初是为了在Cassandra上存储数据而构建的,因为Cassandra是灵活且可扩展的,并且在Twitter中被大量使用。=除了Cassandra,Zipkin原生支持ElasticSearch和MySQL。

API

API 提供以各种方式从存储中提取数据的功能。

UI

它是一个 UI,可将存储在浏览器中的日志数据可视化。

部署与使用

docker

docker run -d -p 9411:9411 openzipkin/zipkin

Java(>1.8)

curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar

源码

# get the latest source
git clone https://github.com/openzipkin/zipkin
cd zipkin
# Build the server and also make its dependencies
./mvnw -DskipTests --also-make -pl zipkin-server clean install
# Run the server
java -jar ./zipkin-server/target/zipkin-server-*exec.jar

启动后,访问 http://127.0.0.1:9411 可以看到效果:
在这里插入图片描述

项目演示

利用mysql启动zipkin

使用java -jar运行,zipkin默认会把信息存储到内存中,这样重启后就会丢失,这里我们利用mysql作为存储介质。
DDL如下:


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;

运行jar包命令:

java -jar zipkin-server-2.24.0-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=123456

这里博主的jar包版本为 zipkin-server-2.24.0-exec

项目依赖调用演示(springcloud alibaba)

新建项目server1和server2,并利用Feign调用从server1向server2发起一个http调用
观察zipkin

准备工作
  1. 到https://github.com/alibaba/nacos/releases下下载nacos 项目
    到nacos项目下 nacos-server-1.1.4\nacos\bin 启动cmd脚本
    双击startup.cmd
    启动成功后访问 http://localhost:8848/nacos/
  2. 本地启动zipkin
    启动后访问 http://127.0.0.1:9411/
新建springboot项目server1

完整pom文件为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>server1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>server1</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Nacos 客户端 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
        <!--服务间通信组件OpenFeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <!--添加Sleuth依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <!--Zipkin 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </pluginRepository>
    </pluginRepositories>

</project>

主类:

@SpringBootApplication
@EnableDiscoveryClient//开启服务注册发现功能
@EnableFeignClients//启动Feign功能
public class Server1Application {

    public static void main(String[] args) {
        SpringApplication.run(Server1Application.class, args);
    }

}

controller

@RestController
public class SampleController {
    @Resource
    private BServiceFeignClient bService;

    @GetMapping("/a")
    public String methodA(){
        String result = bService.methodB();
        result = "-> Service A" + result;
        return result;
    }
}

client

@FeignClient("b-service")
public interface BServiceFeignClient {
    @GetMapping("/b")
    public String methodB();
}

yml

server:
  port: 7001
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        username: nacos
        password: nacos
  application:
    name: a-service
  sleuth:
    sampler: #采样器
      probability: 1.0 #采样率,采样率是采集Trace的比率,默认0.1
      rate: 10000 #每秒数据采集量,最多n条/秒Trace
    web: #Spring Cloud Sleuth 针对 Web 组件的配置项,例如说 SpringMVC
      enabled: true
  zipkin: #设置zipkin服务端地址
      base-url: http://127.0.0.1:9411
新建springboot项目server2

pom文件和主类和server1相同

controller

@RestController
public class SampleController {


    @GetMapping("/b")
    public String methodA(){
        String result = "";
        result = "-> Service B" + result;
        return result;
    }
}

yml

server:
  port: 7002
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        username: nacos
        password: nacos
  application:
    name: b-service
  sleuth:
    sampler: #采样器
      probability: 1.0 #采样率,采样率是采集Trace的比率,默认0.1
      rate: 10000 #每秒数据采集量,最多n条/秒Trace
    web: #Spring Cloud Sleuth 针对 Web 组件的配置项,例如说 SpringMVC
      enabled: true
  zipkin: #设置zipkin服务端地址
    base-url: http://127.0.0.1:9411
测试

启动两个项目,访问 http://127.0.0.1:7001/a 页面输出 Service A-> Service B
观察Zipkin
在这里插入图片描述
点击 show 按钮查看详情
在这里插入图片描述
点击依赖可以查看应用间的依赖调用关系
在这里插入图片描述
在这里插入图片描述