前言

  1. 本文采用Spring cloud本文为2.1.8RELEASEversion=Greenwich.SR3

本文基于前两篇文章eureka-server、eureka-client、eureka-ribbon和eureka-feign的实现。

参考

概述

现实生产环境当中,随着业务的发展,系统规模是越来越大的,各个服务之间的调用也越来越复杂,通常一个由客户端发起的请求在后端系统中会经过N个不同服务的来产生结果,这样就会产生一个调用链路,每一条链路都有可能出现不通的错误或者是延迟,当出现错误或者延迟的情况下,追踪问题变的非常困难,所以Spring cloud为我们提供了Sleuth分布式链路追踪,能帮忙我们快速定位问题以及相应的监控。(我这里的demo模块也好多,过后需要整理下,不影响小伙伴们的学习)

1. Sleuth简单使用

1.1 在相关工程中添加Sleuth依赖

在eureka-client、eureka-ribbon、eureka-feign工作中增加Sleuth依赖。

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-sleuth</artifactId>
  4. </dependency>

1.2 添加日志记录

在需要输入日志的地方增加日志打印。这里只简单例举eureka-ribbon工程中的controller日志。

  1. package spring.cloud.demo.eurekaribbon.controller;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. import spring.cloud.demo.eurekaribbon.service.EurekaRibbonService;
  7. /**
  8. * @auther: maomao
  9. * @DateT: 2019-09-17
  10. */
  11. @RestController
  12. @Slf4j
  13. public class EurekaRibbonConntroller {
  14. @Autowired
  15. private EurekaRibbonService eurekaRibbonService;
  16. @RequestMapping("/sayHello")
  17. public String syaHello() {
  18. log.info("eureka-ribbon server......");
  19. String message = eurekaRibbonService.sayHello();
  20. log.info("[eureka-ribbon][EurekaRibbonConntroller][syaHello], message={}", message);
  21. return "ribbon result: " + message;
  22. }
  23. }

1.3 启动服务

准备工作已经完成,这时候我们按顺序启动所有服务。然后我们访问http://localhost:8901/sayHello,查看控制台会输出,

  1. 2019-11-06 19:48:48.058 INFO [eureka-ribbon,086a3ab9cf8d31a8,086a3ab9cf8d31a8,false] 59750 --- [nio-8901-exec-9] s.c.d.e.c.EurekaRibbonConntroller : ribbon request, server=eureka-ribbon
  2. 调用 服务 eureka-client/info
  3. 服务 eureka-client/info 返回信息:http://eureka1.client.com:8801/info
  4. 调用 服务 eureka-client/info success
  5. 2019-11-06 19:48:48.351 INFO [eureka-ribbon,086a3ab9cf8d31a8,f06ab1e22c04430a,false] 59750 --- [ibbonService-10] s.c.d.e.service.EurekaRibbonService : ribbon->EurekaRibbonService->sayHello->调用 服务 eureka-client/info 返回信息:message=http://eureka1.client.com:8801/info
  6. 2019-11-06 19:48:48.351 INFO [eureka-ribbon,086a3ab9cf8d31a8,086a3ab9cf8d31a8,false] 59750 --- [nio-8901-exec-9] s.c.d.e.c.EurekaRibbonConntroller : ribbon request, server=eureka-ribbon, message=http://eureka1.client.com:8801/info

日志说明:

我们在控制台中可以查看到类似这样的日志:[eureka-ribbon,086a3ab9cf8d31a8,f06ab1e22c04430a,false],这些就是Sleuth帮忙我们生成的。

  • 第一个值:eureka-ribbon,代表我们的应用名称。
  • 第二个值:086a3ab9cf8d31a8,TraceID, 用来标识一条请求链路。
  • 第三个值:f06ab1e22c04430a,SpanID,用来标识一个基本的工作单元。
  • 第四个值:false,表示是否将该信息输出到其他日志收集服务中,例如:Zipkin。

TraceID和SpanID关系:一个链路对应多个基本工作单元,也就是一个TraceID对应多个SpanID。

我这里例举的eureka-ribbon工程中的控制台输出的日志内容,同理我们可以查看eureka-client工程的控制台输出,也会用类似的日志输出。

1.4 小结

至此,Spring cloud Sleuth分布式链路追踪就初步搭建完成,由此我们可以总结出,Sleuth的核心就是生成的TraceID和SpanID,一条链路的日志信息是由TraceID串联起来的。

2. 整合Logstash

有了日志输出还不够,我们还需要日志收集,官方文档使用的是Logstash,接下来我们开始整和Logstash。

2.1 加入Logstash依赖

  1. <dependency>
  2. <groupId>net.logstash.logback</groupId>
  3. <artifactId>logstash-logback-encoder</artifactId>
  4. <version>6.2</version>
  5. </dependency>

这里加入的是最新的logback依赖包,低版本的和Spring cloud 2.x版本不兼容。

2.2 增加logback-spring.xml

在eureka-client和eureka-ribbon中加入logback-spring.xml,这里需要注意的是,logback-spring.xml加载在application.yml配置之前,所以要新建bootstrap.yml,这样logback-spring.xml才能获取到对应的应用名称。

bootstrap.yml设置:

  1. spring:
  2. application:
  3. name: eureka-ribbon
  4. server:
  5. port: 8901

logback-spring.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration>
  3. <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
  4. <springProperty scope="context" name="springAppName" source="spring.application.name"/>
  5. <!-- Example for logging into the build folder of your project -->
  6. <property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}"/>
  7. <!-- You can override this to have a custom pattern -->
  8. <property name="CONSOLE_LOG_PATTERN"
  9. value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
  10. <!-- Appender to log to console -->
  11. <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
  12. <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
  13. <!-- Minimum logging level to be presented in the console logs-->
  14. <level>INFO</level>
  15. </filter>
  16. <encoder>
  17. <pattern>${CONSOLE_LOG_PATTERN}</pattern>
  18. <charset>utf8</charset>
  19. </encoder>
  20. </appender>
  21. <!-- Appender to log to file in a JSON format -->
  22. <appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender">
  23. <file>${LOG_FILE}.json</file>
  24. <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  25. <fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>
  26. <maxHistory>7</maxHistory>
  27. </rollingPolicy>
  28. <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
  29. <providers>
  30. <timestamp>
  31. <timeZone>UTC</timeZone>
  32. </timestamp>
  33. <pattern>
  34. <pattern>
  35. {
  36. "severity": "%level",
  37. "service": "${springAppName:-}",
  38. "trace": "%X{X-B3-TraceId:-}",
  39. "span": "%X{X-B3-SpanId:-}",
  40. "parent": "%X{X-B3-ParentSpanId:-}",
  41. "exportable": "%X{X-Span-Export:-}",
  42. "pid": "${PID:-}",
  43. "thread": "%thread",
  44. "class": "%logger{40}",
  45. "rest": "%message"
  46. }
  47. </pattern>
  48. </pattern>
  49. </providers>
  50. </encoder>
  51. </appender>
  52. <root level="INFO">
  53. <appender-ref ref="console"/>
  54. <!-- uncomment this to have also JSON logs -->
  55. <appender-ref ref="logstash"/>
  56. <!--<appender-ref ref="flatfile"/>-->
  57. </root>
  58. </configuration>

2.3 重启相关服务

重新启动相关服务,并访问http://localhost:8901/sayHello,在相应的控制台中可以看到类似日志,

  1. 2019-11-07 11:14:21.136 INFO [eureka-ribbon,0983491b6471be0f,48598b8942c2c814,false] 3288 --- [RibbonService-1] s.c.d.e.service.EurekaRibbonService : ribbon->EurekaRibbonService->sayHello->调用 服务 eureka-client/info 返回信息:message=http://eureka1.client.com:8801/info
  2. 2019-11-07 11:14:21.139 INFO [eureka-ribbon,0983491b6471be0f,0983491b6471be0f,false] 3288 --- [nio-8901-exec-1] s.c.d.e.c.EurekaRibbonConntroller : >>>traceId=null, spanId=null
  3. 2019-11-07 11:14:21.140 INFO [eureka-ribbon,0983491b6471be0f,0983491b6471be0f,false] 3288 --- [nio-8901-exec-1] s.c.d.e.c.EurekaRibbonConntroller : [eureka-ribbon][EurekaRibbonConntroller][syaHello], message=http://eureka1.client.com:8801/info, traceId=0983491b6471be0f

日志内容之前已经进行过详细的说明,这里就不在说明,这时我们可以在工程目录外发现有一个build的目录,我们进入这个build目录可以看到已应用名称开头的.json文件,该文件就是logback-spring.xml中配置的logstash的appender输出的日志文件。

2.3 小结

logstash的日志配置我们就完成了,logstash除了可以通过上面的方式生成json日志文件之外,还可以使用LogstashTcpSocketAppender将日志内容直接输出到logstash的服务端,这里就不过多说明,感兴趣的小伙伴可以自行研究。

3 整合Zipkin

在Spring cloud D版本以后,zipkin-server是通过引入依赖的方式构建的,到了E版本之后,官方就是开始启用了jar的形式来运行zipkin-server。所以我们先到zipkin的官网下载最新的zipkin.jar。

3.1 修改要跟踪的工程应用

在eureka-client、eureka-ribbon、spring-gateway增加相关依赖。

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-zipkin</artifactId>
  4. </dependency>

3.2 修改application.yml配置

在eureka-client、eureka-ribbon、spring-gateway应用的application.yml增加一下配置:

  1. spring:
  2. sleuth:
  3. sampler:
  4. probability: 1 #采样频率
  5. web:
  6. enabled: true
  7. zipkin:
  8. base-url: http://localhost:9411/ #zipkin服务地址

3.3 启动服务

启动eureka-client、eureka-ribbon、spring-gateway应用服务。

zipkin启动方式:java -jar zipkin.jar

运行zipkin.jar以后,我访问http://localhost:9411/zipkin,这时候我们可以看到如下图显示:



然后我们在访问http://localhost:8100/ribbon/sayHello?token=xxx地址(这个地址的请求链路是spring-gateway:eureka-ribbion:eureka-client),然后我们点击zipkin的查询按钮,我们可以看到如下显示:



然后可以点击单个链路信息查看详细信息,如下图显示:

由这张图就可查看到详细链路追踪信息。

3.4 小结

至此,整合zipkin就完成了,这种默认的方式是http收集,我们还可以采用消息中间件来收集日志信息,感兴趣的小伙伴可以自行研究。

总结

本文重点讲述了Spring Cloud通过Sleuth+Zipkin实现了服务的跟踪,后续我会补充一篇结合ELK的日志收集。通过这篇文章我们也简单的了解了链路追踪的原理,就是通过traceId将整个过程串联起来,然后通过spanID来计算各个环节的时间延迟。

代码地址

gitHub地址


《Srping Cloud 2.X小白教程》目录


  • 写作不易,转载请注明出处,喜欢的小伙伴可以关注公众号查看更多喜欢的文章。
  • 联系方式:4272231@163.com

spring cloud 2.x版本 Sleuth+Zipkin分布式链路追踪的更多相关文章

  1. Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】

    Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin[Finchley 版]  发表于 2018-04-24 |  随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请 ...

  2. spring boot 2.0.3+spring cloud (Finchley)7、服务链路追踪Spring Cloud Sleuth

    参考:Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin[Finchley 版] Spring Cloud Sleuth 是Spring Cloud的一个组件,主要功能是 ...

  3. SpringCloud Sleuth + Zipkin 实现链路追踪

    一.Sleuth介绍   为什么要使用微服务跟踪? 它解决了什么问题? 1.微服务的现状?   随着业务的发展,单体架构变为微服务架构,并且系统规模也变得越来越大,各微服务间的调用关系也变得越来越复杂 ...

  4. zipkin分布式链路追踪系统

    基于zipkin分布式链路追踪系统预研第一篇   分布式服务追踪系统起源于Google的论文“Dapper, a Large-Scale Distributed Systems Tracing Inf ...

  5. spring cloud 系列第7篇 —— sleuth+zipkin 服务链路追踪 (F版本)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.简介 在微服务架构中,几乎每一个前端的请求都会经过多个服务单元协调来提 ...

  6. 基于zipkin分布式链路追踪系统预研第一篇

    本文为博主原创文章,未经博主允许不得转载. 分布式服务追踪系统起源于Google的论文“Dapper, a Large-Scale Distributed Systems Tracing Infras ...

  7. spring cloud微服务快速教程之(十一) Sleuth(zipkin) 服务链路追踪

    0.前言 微服务架构上众多微服务通过REST调用,可能需要很多个服务协同才能完成一个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败.随着业务的不断扩张,服务之间互相调用 ...

  8. rabbitmq+sleuth+zinkip 分布式链路追踪

    我们都知道,微服务之间通过feign传递,在复杂的微服务架构系统中,几乎每一个前端请求都会形成一个复杂的分布式服务调用链路,在每条链路中任何一个依赖服务出现延迟超时或者错误都有可能引起整个请求最后的失 ...

  9. Spring cloud微服务安全实战-7-12整合链路追踪和日志监控

    调用链路的监控和统一日志的监控结合起来.比如说我在调用链监控上发现有一个调用订单的服务慢了.通过pinpoint可以看到 .用户发出来的请求,经过了网关,经过了order,经过了pagement.通过 ...

随机推荐

  1. "(error during evaluation)" computed

    在vue-cli搭建的去哪网app项目中使用了  computed  计算属性 computed计算属性在chrome插件中的 vue devtools 插件中报错 应该显示出来 computed 属 ...

  2. 22(8).模型融合---RegionBoost

    在adaboost当中,样本的权重alpha是固定的,蓝色五角星所在的圈中3个○分错了,红色五角星所在的圈中4个×和1个○都分对了,很容易让人想到,这个模型,对于红色位置的判断更加可信. 动态权重,每 ...

  3. 在项目中常用的JS方法封装

    使用方法简单,只需要放在你的 utils.js 工具文件中,直接export const 加上下面封装方法,在别的文件中使用 {方法1,方法2,方法3...}引用后直接使用即可. 01.输入一个值.返 ...

  4. web攻击与防御技术-平台搭建与暴力破解

    平台搭建是首先安装xampp并把pikachu的压缩文件解压在HTdocs下 然后 点击后显示 安装成功 首先随便输入一些东西 然后用burpsuite抓包 对username和password字段进 ...

  5. OverLoad怎么用

    首先给出一个实例 package practice3; public class TryOverLoad { public static void main(String[] args) { Syst ...

  6. Feign Ribbon Hystrix 三者关系 | 史上最全, 深度解析

    史上最全: Feign Ribbon Hystrix 三者关系 | 深度解析 疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -25[ 博客园 总入口 ] 前言 疯狂创客圈(笔者尼恩创建的 ...

  7. Java 创建线程的3种方法及各自优势

    1. 继承 Thread 类,然后调用 start 方法. class MyThread extends Thread { //重写run方法,线程运行后,跑的就是run方法 public void ...

  8. navicat的一些常用快捷键

    Navicat可以支持连接多种数据库,使用上的功能也比较强大. 如果使用了IDEA内置的数据库工具(个人喜欢用这个)或是SQL Server官方的数据库管理工具的话,会发现使用上都存在区别,区别就主要 ...

  9. Java描述设计模式(11):观察者模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.观察者模式 1.概念描述 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.观察者模式定义了一种一对多 ...

  10. C#斐波那契数列求法(比较阶乘和循环所用时间)

    using System; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Console.Writ ...