万隆的笔记 万隆的笔记
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
  • 快速开始

  • 服务注册与发现

  • 服务熔断

  • 服务网关

  • 配置中心

  • 服务追踪

    • 服务链路追踪-ZipKin
      • ZipKin概述
      • 架构概览
      • 创建ZipKin服务端
      • 配置ZipKin客户端-追踪服务
      • 追踪测试
      • 参考
    • ZipKin架构
    • Spring Boot Admin
  • SpringCloud-Netflix
  • 服务追踪
2021-09-17
目录

服务链路追踪-ZipKin

# 服务链路追踪-ZipKin

微服务架构是通过业务来划分服务的,使用 REST或RPC 调用。对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。随着服务的越来越多,对调用链的分析会越来越复杂。它们之间的调用关系也许如下。

对外暴露的一个功能接口 业务复杂的微服务系统
zipkin-architecture-2 zipkin-architecture-3

因此,对服务调用链进行监控是非常必要的。

# ZipKin概述

ZipKin (opens new window) 是一个 Twitter 公司开源的分布式追踪系统,它致力于收集服务的计时数据,以解决微服务架构中的延迟问题,功能包括数据的收集、存储、查找和展现。它的理论模型来自于 Google Dapper (opens new window) 论文。

各业务系统在彼此调用时,将特定的跟踪消息传递至 ZipKin,Zipkin在收集到跟踪信息后将其聚合处理、存储、ZipKin UI 展示等,开发者可以通过 ZipKin UI 生成的依赖关系图,便获得网络延迟、调用链路、系统依赖等等,让开发者轻松的收集和分析数据,方便监测系统中存在的瓶颈。

# 架构概览

ZipKin 总体采用的是C/S架构。客户端采集数据后异步发送给服务端用来展示数据。在每个Instrumented的客户端,写入了TraceId,然后统一收集数据在服务端存储。这里Instrumented翻译为仪器化,代表一个接入了ZipKin的客户端。

zipkin-architecture-1

Zipkin的基础架构,主要由4个核心组件构成:

  • Collector:收集器组件,它主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为Zipkin内部处理的Span格式,以支持后续的存储、分析、展示等功能。
  • Storage:存储组件,它主要对处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中,我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到 数据库或es 中。
  • API:RESTful API组件,它主要用来提供外部访问接口。比如给客户端展示跟踪信息,或是外接系统访问以实现监控等。
  • UI:Web UI组件,基于API组件实现的上层应用。通过UI组件用户可以方便而有直观地查询和分析跟踪信息。

Zipkin的相关概念:

  • Trace:一系列 Spans 组成的一个树状结构,表示对一次请求的跟踪,Trace以一个64 位 ID 表示。
  • Span:Zipkin基本工作单元,一个服务的处理跟踪是一个Span,包含了一些描述信息:id,parentId,name,timestamp,duration,annotations等。
  • Annotation:用来及时记录一个事件的存在,一些核心 Annotations 用来定义一个请求的开始和结束。
    • cs:Client Sent,客户端发起一个请求,这个 Annotation 描述了这个 Span 的开始
    • sr:Server Received,服务端获得请求并准备开始处理它,如果将其 sr 减去 cs 时间戳便可得到网络延迟
    • ss:Server Sent 表明请求处理的完成(当请求返回客户端),如果 ss 减去 sr 时间戳便可得到服务端需要的处理请求时间
    • cr:Client Received 表明 Span 的结束,客户端成功接收到服务端的回复,如果 cr 减去 cs 时间戳便可得到客户端从服务端获取回复的所有所需时间

更多见ZipKin架构。

# 创建ZipKin服务端

# 版本问题

从 Spring Boot 2.x 版本后,Zipkin官网已经不再推荐自己搭建定制Zipkin,而是直接提供了编译好的jar包或者推荐使用Docker部署。而从Spring Boot 2.2.x 以后的版本集成 zipkin 的方式改变了,原来是通过@EnablezipkinServer注解,现在这个注解不起作用了,现在基本都采用官方提供的jar部署:

-- java
curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar
-- Docker
docker run -d -p 9411:9411 openzipkin/zipkin

附:使用 Docker Compose 快速部署 ZipKin 服务器,docker-compose.yml 配置文件如下:

version: '3.1'
services:
  zipkin:
    image: openzipkin/zipkin
    container_name: zipkin
    ports:
      - 9411:9411

下面是Spring boot 2.2.x以下版本,创建自定义ZipKin服务端的方式,请根据具体版本做选择搭建。

创建一个工程名为hello-spring-cloud-zipkin的项目,使用的Spring Boot版本为2.1.18.RELEASE 。

# 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.1.18.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <artifactId>hello-spring-cloud-zipkin</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <!-- Environment Settings -->
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <!-- Spring Settings -->
        <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
        <zipkin.version>2.10.1</zipkin.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->

        <!-- Spring Cloud Begin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin</artifactId>
            <version>${zipkin.version}</version>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-slf4j-impl</artifactId>
                </exclusion>
            </exclusions>
            <version>${zipkin.version}</version>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
            <version>${zipkin.version}</version>
        </dependency>
        <!-- Spring Cloud End -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.hello.spring.cloud.zipkin.ZipkinApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

注意,引入的三个ZipKin相关的依赖并没有标明版本,但是版本并没有托管到SpringBoot中,这里是托管到了自有的dependencies项目,使用的版本号为2.10.1。

提示

细心的人可能会发现,此处引入groupId为io.zipkin.java的zipkin依赖,在仓库中已经被标记为Deprecated (opens new window)并且版本已经定格在2.10.1,这是因为ZipKin官方已经不建议自定义Server (opens new window),如果引入最新io.zipkin.zipkin2可能会导致项目出现各种问题,最新的建议用Docker或用官方提供的jar部署。

# Application

通过 @EnableZipkinServer 注解开启 Zipkin Server 功能,同样需要开启@EnableEurekaClient注解,因为需要将服务注册到Eureka中心。

package com.example.hello.spring.cloud.zipkin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import zipkin.server.internal.EnableZipkinServer;

@SpringBootApplication
@EnableEurekaClient
@EnableZipkinServer
public class ZipkinApplication {

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

}

# application.yml

ZipKin默认的服务端的端口号为9411

spring:
  main:
    allow-bean-definition-overriding: true
  application:
    name: hello-spring-cloud-zipkin


server:
  port: 9411

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

management:
  metrics:
    web:
      server:
        auto-time-requests: false

# 配置ZipKin客户端-追踪服务

配置ZipKin客户端,即将相当于给服务装上追踪仪,让服务可以被追踪。

# POM

在 所有需要被追踪的服务 中增加 spring-cloud-starter-zipkin 依赖:

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

# application.yml

在这些项目的 application.yml 配置文件中增加 Zipkin Server 的地址即可:

spring:
  zipkin:
    base-url: http://localhost:9411

# 追踪测试

依次启动相关项目,打开浏览器访问:http://localhost:9411/zipkin/,可以查看到ZipKin提供的UI界面:

zipkin-ui-1

这里以监控服务消费者 - Feign (opens new window)为例,直接调用消费者提供的接口(也可以通过网关): http://localhost:8765/hi?msg=HelloFeign,在ZipKin的UI界面传入相关查询条件,点击Find Traces,可以查看具体服务相互调用的情况(当ZipKin收到某个服务异步发送过来的监控信息的时候,Service Name下拉选项便会出现在该服务):

zipkin-ui-2

点击进去可以查看更加具体的信息:

zipkin-ui-3

或者点击服务依赖分析,可以直接得看到服务追踪链:

zipkin-ui-4

在实际生产中,我们往往是通过traceId去查询服务追踪的。服务被追踪后,我们可以在后台看到对应的log日志,例如上例: zipkin-ui-5

bc32708002ea92f8为traceId,12ab44db0159e3e1为spanId。

zipkin-ui-6

附,项目启动一般顺序:

  1. Eureka注册与发现中心
  2. Config统一配置中心
  3. 各种附加服务:例如ZipKin、Netflix Turbine等
  4. 服务提供者、服务消费者
  5. 服务网关:例如 Zuul、GateWay

# 参考

1.Zipkin简介及基本概念 (opens new window)

上次更新: 5/30/2023, 12:51:40 AM
ZipKin架构

ZipKin架构→

最近更新
01
Vue-Ajax
06-13
02
2025
01-15
03
Elasticsearch面试题
07-17
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式