Spring Cloud版——电影售票系统<八>使用 Spring Sleuth 实现微服务追踪

 

                GitHub地址:https://github.com/leebingbin/SpringCloud.MovieTicketing

 

一、为什么要实现微服务追踪

        监控微服务的方式有很多,例如使用 Spring Boot Actuator 监控微服务实例,使用 Hystrix 监控 Hystrix Command 等。谈到微服务追踪,就不得不提一下 Peter Deutsch 的文章 The Eight Fallacies of Distributed Computing ( 分布式计算的八大误区 ) , 内容大致如下:

        · 网络可靠

        · 延迟为零

        · 带宽无限

        · 网络绝对安全

        · 网络拓扑不会改变

        · 必须有一名管理员

        · 传输成本为零

        · 网络同质化 (由 Java 之父 Golsing 补充) 

        不难可以看出,该文章很多点都在描述一个问题 —— 网络问题。网络常常很脆弱,同时, 网络资源也是有限的。

        微服务之间通过网络进行通信。如果能够追踪每个请求,了解请求经过那些微服务 (从而了解信息是如何在服务之间流动),请求耗费时间、网络延迟、业务逻辑耗费时间等指标,那么就能更好地分析系统瓶颈、解决系统问题。因此,微服务追踪很有必要。

    1.1    Spring Cloud Sleuth 简介

        Spring Cloud Sleuth 为 Spring Cloud 提供了分布式追踪的解决方案,它大量借用了 Google Dapper 、Twitter Zipkin 和 Apache HTrace 的设计。

        Sleuth 的术语:

        · span(跨度):基本工作单元。span 用一个 64 位的 id 唯一标识。除了ID外,span 还包含其他数据,例如描述、时间戳事件、键值对的注解(标签),spanID、span父ID等。

        · trace(追踪):一组共享“root span” 的 span 组成的树状结构称为 trace 。trace 也用一个 64 位的 ID 唯一标识,trace 中的所有 span 都共享该 trace 的ID 。

        · annotation(标注): annotation 用来记录事件的存在,其中,核心 annotation 用来定义请求的开始和结束。

        - CS ( Client Sent 客户端发送 ):客户端发起一个请求,该 annotation 描述了 span 的开始。

        - SR ( Server Received 服务器端接收 ): 服务器端获得请求并准备处理它。如果用 SR 减去 CS 时间戳,就能得到网络延迟。

        - SS ( Server Sent 服务器端发送 ):该 annotation 表明完成请求处理( 当响应发回客户端时 )。如果用 SS 减去 SR 时间戳,就能得到服务器端处理请求所需时间。

        - CR( Client Received 客户端接收):span 结束标识。客户端成功接收到服务器端的响应。如果 CR 减去 CS 时间戳,就能得到从客户端发送请求到服务器响应的所需的时间。

二、整合 Spring Cloud Sleuth 与 ELK 配合使用

        2.1 为项目添加依赖

# spring-cloud-starter-sleuth

# spring-cloud-starter-sleuth
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-sleuth -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
    <version>1.3.1.RELEASE</version>
</dependency>

# logback

# logback
<!-- https://mvnrepository.com/artifact/net.logstash.logback/logstash-logback-encoder -->
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>4.11</version>
</dependency>

 

        2.2 新建 logback-spring.yml , 添加以下内容:


<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <include resource="org/springframework/boot/logging/logback/defaults.xml" />
  ​
  <springProperty scope="context" name="springAppName" source="spring.application.name" />
  <!-- Example for logging into the build folder of your project -->
  <property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}" />
  ​
  <property name="CONSOLE_LOG_PATTERN"
    value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-B3-ParentSpanId:-},%X{X-Span-Export:-}]){yellow} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />

  <!-- Appender to log to console -->
  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <!-- Minimum logging level to be presented in the console logs -->
      <level>DEBUG</level>
    </filter>
    <encoder>
      <pattern>${CONSOLE_LOG_PATTERN}</pattern>
      <charset>utf8</charset>
    </encoder>
  </appender>

  <!-- Appender to log to file -->
  <appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_FILE}</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
      <maxHistory>7</maxHistory>
    </rollingPolicy>
    <encoder>
      <pattern>${CONSOLE_LOG_PATTERN}</pattern>
      <charset>utf8</charset>
    </encoder>
  </appender>
  ​
  <!-- Appender to log to file in a JSON format -->
  <appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_FILE}.json</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>
      <maxHistory>7</maxHistory>
    </rollingPolicy>
    <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
      <providers>
        <timestamp>
          <timeZone>UTC</timeZone>
        </timestamp>
        <pattern>
          <pattern>
            {
              "severity": "%level",
              "service": "${springAppName:-}",
              "trace": "%X{X-B3-TraceId:-}",
              "span": "%X{X-B3-SpanId:-}",
              "parent": "%X{X-B3-ParentSpanId:-}",
              "exportable": "%X{X-Span-Export:-}",
              "pid": "${PID:-}",
              "thread": "%thread",
              "class": "%logger{40}",
              "rest": "%message"
            }
          </pattern>
        </pattern>
      </providers>
    </encoder>
  </appender>
  ​
  <root level="INFO">
    <appender-ref ref="console" />
    <appender-ref ref="logstash" />
    <!--<appender-ref ref="flatfile"/> -->
  </root>
</configuration>

        2.3 ELK 搭建

        ELK 的搭建比较简单,参考官方文档(或我的博客)即可:

        http://www.elastic.co/guide/index.html        

        174246_J9BV_3375733.png

 

        Docker 搭建 ELK:

        http://elk-docker.readthedocs.io/ 

        174134_MRaJ_3375733.png

        2.4 编写 Logstash 文件,命名为 logstash.conf 

        使用 logstash.conf 启动 Logstash 。Logstash是一款轻量级的日志搜集处理框架,可以方便的把分散的、多样化的日志搜集起来,并进行自定义的处理,然后传输到指定的位置,比如某个服务器或者文件。

        官方参考:https://www.elastic.co/products/logstash

        175239_Yfqg_3375733.png

# logstash.conf

input {
	file {
		codec => json
		path => "/opt/build/*.json"		# 改成你项目打印的json日志文件
	}
}
filter {
	grok {
		math => { "message" => "%{TIMESTAMP_ISO08601:timestamp}\s+%{LOGLEVEL:
			severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}---\s+
			\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" }
	}
}
output {
	elasticsearch {
		hosts => "elasticsearch:9222"	# 改成你的 Elasticsearch 地址
	}
}

三、Spring Cloud Sleuth 与 Zipkin 配合使用

        1.1 Zipkin 简介

        Zipkin 是 Twitter 开源的分布式跟踪系统,基于 Dapper 的论文设计而来。它的主要功能是收集系统的时序数据,从而追踪微服务架构的系统延时等问题。Zipkin 还提供了一个非常友好的界面,来帮助分析追踪数据。

        1.2 Zipkin 官网

            Zipkin 官方网站:https://zipkin.io/

        120336_akIp_3375733.png

        1.3 引入依赖


  <dependencies>
    <dependency>
      <groupId>io.zipkin.java</groupId>
      <artifactId>zipkin-autoconfigure-ui</artifactId>
    </dependency>
    <dependency>
      <groupId>io.zipkin.java</groupId>
      <artifactId>zipkin-server</artifactId>
    </dependency>
  </dependencies>

        1.4  编写启动类,使用 @EnableZipkinServer 注解,声明一个 Zipkin Server



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);
  }
}

四、使用消息中间件收集数据

        上面介绍的使用 HTTP 直接收集跟踪数据。相比 HTTP 的方式来说,使用消息中间件有以下优点:

        · 微服务与 Zipkin Server 解耦,微服务无须知道 Zipkin Server 的网络地址。

        · 一些场景下,Zipkin Server 与微服务网络可能不通,使用 HTTP 直接收集的方式无法工作,此时可借助消息中间件实现数据收集

        1.1 添加依赖

        首先,肯定要安装 RabbitMQ 作为消息中间件进行演示,RabbitMQ 的安装可以参考我的博客或者官方文档。


  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-sleuth</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
    </dependency>
    <dependency>
      <groupId>io.zipkin.java</groupId>
      <artifactId>zipkin-autoconfigure-ui</artifactId>
    </dependency>
  </dependencies>

        1.2 修改启动类注解

        修改启动类,将注解 @EnableZipkinServer 修改为 @EnableZipkinStreamServer 。然后修改配置文件 application.yml ,添加 rabbitmq 配置。


spring:  
  rabbitmq:
    host: localhost
    port: 6666
    username: guest
    password: guest

五、存储追踪数据       

        按照上面的配置,Zipkin Server 是将数据存储在内存中。这种方式一般不适用于生产环境,因为一旦 Zipkin Server 重启或发生崩溃,就会导致历史数据的丢失。

        Zipkin Server 支持多种后端存储,如 MySQL, Elasticsearch, Cassanda 等。在这块以如何将数据存储在 Elasticsearch 中,让其使用 RabbitMQ 收集跟踪数据并使用 Elasticsearch 作为后端存储。

        1.1 添加依赖


 <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
    </dependency>
    <dependency>
      <groupId>io.zipkin.java</groupId>
      <artifactId>zipkin-autoconfigure-ui</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
    </dependency>
    <dependency>
      <groupId>io.zipkin.java</groupId>
      <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
      <version>1.16.2</version>
    </dependency>
  </dependencies>

        1.2 修改配置文件 application.yml 


zipkin:
  storage:
    type: elasticsearch
    elasticsearch:
      cluster: elasticsearch
      hosts: http://localhost:9200
      index: zipkin
      index-shards: 5
      index-replicas: 1

        1.3 Elasticsearch 官网

        Elasticsearch 官网:https://www.elastic.co/cn/

        154058_5zN4_3375733.png

 

        154228_lgVP_3375733.png

 

        参考资料:

        · 分布式计算的八大误区原文:https://blogs.oracle.com/jag/resource/Fallacies.html

        · Zipkin 官方网站:https://zipkin.io/

        · 消息队列-ActiveMQ:https://my.oschina.net/u/3375733/blog/890260

        · RabbitMQ 官网 : https://www.rabbitmq.com/ 

        · Elasticsearch 官方文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

        · Elasticsearch 官网:https://www.elastic.co/cn/

        · ELK 官方文档:https://www.elastic.co/guide/index.html

 

 

本文为博主原创文章,转载请注明出处!

https://my.oschina.net/u/3375733/blog/

转载于:https://my.oschina.net/u/3375733/blog/1613712

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值