微服务系列详解- Part 6:使用Spring Cloud Sleuth和Zipkin进行分布式跟踪

本文介绍了在微服务环境中使用Spring Cloud Sleuth进行分布式跟踪,并通过Zipkin进行可视化。讲解了如何设置Zipkin服务器,将跟踪信息导出到Zipkin,以及如何在Zipkin UI中查看和分析调用链。

微服务是一团糟的调试工作。在本教程中,我们将发现如何在Spring Cloud环境中调试分布式调用。抽丝剥茧 细说架构那些事——【优锐课】

上篇文章说到,微服务系列详解-Part5:Spring Cloud Zuul代理作为API网关

微服务架构中的挑战之一是调试问题的能力。一个简单的用户操作可能会触发一系列下游微服务调用。在微服务中跟踪与特定用户操作相关的日志将很麻烦。除此之外,我们可能想跟踪为什么某个微服务调用要花费这么多时间。我们可以使用Spring Cloud Sleuth处理此类问题。Spring Cloud Sleuth提供了分布式跟踪功能,我们还可以将这些跟踪信息导出到Zipkin以可视化呼叫跟踪。

在这篇文章中,我们将学习:
• 跟踪分布式服务呼叫
• 使用Spring Cloud Sleuth进行分布式跟踪
• 使用Zipkin服务器进行分布式跟踪

在微服务世界中,用户对UI的操作可能会调用一个微服务API端点,而端点又会调用另一个微服务端点。

例如,当用户看到目录时,shoppingcart-ui将调用目录服务REST API http://localhost:8181/api/products,而产品反过来又调用了库存服务REST API http://localhost:8282/api/inventor以检查库存可用性。

假设发生了异常或返回的数据无效,并且你想通过查看日志来调查问题所在。但是到目前为止,还没有办法将特定用户的日志跨多个服务关联起来。

Poor Man’s分布式追踪

一种解决方案是在调用链的开头,我们可以创建一个CORRELATION_ID并将其添加到所有日志语句中。连同它一起,还将CORRELATION_ID作为标头发送到所有下游服务,以便那些下游服务在日志中也使用CORRELATION_ID。这样,我们可以识别与跨服务的特定操作相关的所有日志语句。

我们可以使用Logging框架的MDC功能来实现此解决方案。通常,我们会有一个WebRequest拦截器,你可以在其中检查是否有CORRELATION_ID标头。如果标题中没有CORRELATION_ID,则创建一个新的并将其设置在MDC中。日志记录框架包括所有日志语句在MDC中设置的信息。

但是,除了我们不做所有这些工作之外,我们还可以使用Spring Cloud Sleuth,它将为我们做所有以及更多的事情。

首先,在这里熟悉Span,Trace,Annotations的一些术语。

让我们将Sleuth启动器添加到库存服务和目录服务中。

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

添加Sleuth启动器并启动服务后,你可以在日志中观察到类似以下内容。

2018-03-20 10:19:15.512  INFO [inventory-service,,,] 53685 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver ...
2018-03-20 10:24:15.507  INFO [inventory-service,,,] 53685 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver ...

现在点击任何清单服务REST端点,例如http://localhost:8282/api/inventory。然后,你可以在日志中观察TraceID,SpanID。

2018-03-20 10:15:38.466  INFO [inventory-service,683f8e4370413032,d8abe400c68a9a6b,false] 53685 --- [oryController-3] ...

Sleuth在MDC的日志中包括模式[appname,traceId,spanId,exportable]。

现在,调用目录服务端点http://localhost:8181/api/products端点,该端点在内部调用清单服务端点http://localhost:8282/api/inventory。

在目录服务日志中,你可以找到类似以下内容的日志语句:

`2018-03-20 10:54:29.625  INFO [catalog-service,0335da07260d3d6f,0335da07260d3d6f,false] 53617 --- [io-8181-exec-10]` ...

并且,在清单服务中检查日志,你可以找到类似以下内容的日志语句:

2018-03-20 10:54:29.662  INFO [inventory-service,0335da07260d3d6f,1af68249ac3a6902,false] 53685 --- [oryController-6] ...

请注意,对于同一REST API调用,目录服务和库存服务中的TraceID 0335da07260d3d6f相同。这样,我们可以轻松地将各个服务之间的日志关联起来。
[inventory-service,0335da07260d3d6f,1af68249ac3a6902,false]中的false表示此跟踪未导出到任何跟踪服务器(如Zipkin)。让我们看看如何将跟踪信息导出到Zipkin。

我们学习了如何使用Sleuth在日志中添加跟踪信息。除此之外,我们还可以将该信息导出到Zipkin,以便我们可以通过UI对其进行可视化。

创建Zipkin服务器作为Spring Boot应用程序

我们可以将Zipkin服务器作为Spring Boot应用程序启动,也可以在Docker容器中运行。

到目前为止,Zipkin不支持Spring Boot2。因此,我们可以使用1.5.10.RELEASE版本创建SpringBoot应用程序zipkin-server并添加zipkin-server,zipkin-autoconfigure-ui依赖项。

<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 
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sivalabs</groupId>
    <artifactId>zipkin-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>zipkin-server</name>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
    <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>
    <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>
    </repositories>
</project>

将@EnableZipkinServer批注添加到主入口点类。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import zipkin.server.EnableZipkinServer;
@SpringBootApplication
@EnableZipkinServer
public class ZipkinServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZipkinServerApplication.class, args);
    }
}

在application.properties中设置端口和应用程序名称。

spring.application.name=zipkin-server
server.port=9411

现在,你可以通过运行ZipkinServerApplication启动Zipkin服务器。

Zipkin服务器作为Docker容器

可以将Docker映像用于OpenZipkin,而不是将Zipkin服务器创建为SpringBoot应用程序。

我们可以使用以下docker-compose-mem.yml文件创建一个由内存数据存储支持的Zipkin服务器。

version: '2'
services:
  # The zipkin process services the UI, and also exposes a POST endpoint that
  # instrumentation can send trace data to. Scribe is enabled by default.
  zipkin:
    image: openzipkin/zipkin
    container_name: zipkin
    # Environment settings are defined here https://github.com/openzipkin/zipkin/tree/1.19.0/zipkin-server#environment-variables
    environment:
      - STORAGE_TYPE=mem
      # Uncomment to disable scribe
      # - SCRIBE_ENABLED=false
      # Uncomment to enable self-tracing
      # - SELF_TRACING_ENABLED=true
      # Uncomment to enable debug logging
      # - JAVA_OPTS=-Dlogging.level.zipkin=DEBUG
    ports:
      # Port used for the Zipkin UI and HTTP Api
      - 9411:9411

你还可以通过使用https://github.com/openzipkin/docker-zipkin/blob/master/docker-compose.yml使用MySQL数据存储支持的docker映像。

Zipkin服务器启动后,你可以转到http://localhost:9411/以查看Zipkin服务器UI仪表板。

将跟踪信息导出到Zipkin服务器

我们观察到跟踪信息打印在日志中,但没有导出。 我们可以将它们导出到Zipkin服务器,以便在Zipkin Server UI仪表板中可视化跟踪。

将Zipkin Client启动程序添加到库存服务和目录服务。

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

在清单服务和目录服务的bootstrap.properties中配置Zipkin服务器URL。

spring.zipkin.base-url=http://localhost:9411/
spring.sleuth.sampler.probability=1

注意:默认情况下,spring.sleuth.sampler.probability = 0.1表示仅将10%的跟踪信息导出到Zipkin。

现在,重新启动清单服务和目录服务,并调用http://localhost:8181/api/products端点。你可以观察到true记录在日志中意味着已导出。

2018-03-20 11:41:02.241  INFO [catalog-service,7d0d44fe314d7758,7d0d44fe314d7758,true] 53617 --- [nio-8181-exec-5] c.s.c.services.ProductService

现在转到Zipkin UI仪表板,你可以在第一个下拉列表中看到填充的服务名称。选择你要检查的服务或全部选中,然后单击“查找跟踪”按钮。

单击任何跟踪,你可以查看每个跨度的呼叫链和等待时间详细信息。

你也可以单击顶部导航栏中的“依赖关系”链接以查看服务依赖关系。

感谢阅读!这个系列就算完结了。

另外还有一些资源分享给各位,需要的可以免费领取~
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值