您的位置:首页 > 其它

使用sleuth实现微服务跟踪

2017-09-04 15:08 429 查看


在微服务架构中,众多的微服务之间互相调用,如何清晰地记录服务的调用链路是一个需要解决的问题。同时,由于各种原因,跨进程的服务调用失败时,运维人员希望能够通过查看日志和查看服务之间的调用关系来定位问题,而
Spring cloud sleuth
组件正是为了解决微服务跟踪的组件。

sleuth的原理介绍可以参考这篇文章: [服务链路追踪(Spring Cloud Sleuth)](http://blog.csdn.net/forezp/article/details/70162074)

本文主要讲解sleuth的两方面用法

- sleuth+elk 结合,聚合微服务日志

- sleuth+ zipkin结合,显示文件调用链路

本文代码参考hello+world+helloworldh+helloworldfeign+track这5个项目

sleuth+elk聚合日志

sleuth配置

- 在微服务项目引入下列依赖

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


配置文件
application.yml
增加

logging:
level:
root: INFO
org.springframework.web.servlet.DispatcherServlet: DEBUG
org.springframework.cloud.sleuth: DEBUG


依次启动
hello项目
helloworld项目
,在浏览器输入
http://localhost:8020/message
后两个项目的控制台输出如下日志





其中
a7c81616d25c1a88
是TraceId,后面跟着的是SpanId,依次调用有一个全局的TraceId,将调用链路串起来。

查看日志文件并不是一个很好的方法,当微服务越来越多日志文件也会越来越多,通过ELK可以将日志聚合,并进行可视化展示和全文检索。

sleuth配合elk使用

ELK是一款日志分析系统,它是
Logstash
+
ElasticSearch
+
Kibana
的技术组合,它可以通过logstash收集各个微服务日志,并通过Kibana进行可视化展示,而且还可以对大量日志信息通过ElasticSearch进行全文检索。



操作步骤:

- 安装ELK,我使用了docker安装了ELK,具体安装步骤可参考这篇文章:

[Docker ElK安装部署使用教程](http://www.cnblogs.com/soar1688/p/6849183.html)

区别是在启动logstash时,指定了日志来源路径

/opt/logstash/bin/logstash -e
'input { file { codec => json path => "/opt/build/*.json" } }
output { elasticsearch { hosts => ["localhost"] } }'


项目添加依赖

<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>4.9</version>
</dependency>


在src/java/resources目录下新建logback-spring.xml,配置如下内容

<?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"/>

<property name="LOG_FILE"
value="${BUILD_FOLDER:-build}/${springAppName}"/>

<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%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}}"/>

<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>

<!-- 按照每天生成日志文件 -->
<appender name="filelog"  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>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>

<!-- 使用json格式保存日志文件 -->
<appender name="jsonlog"  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>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>

<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="jsonlog"/>
<appender-ref ref="filelog"/>
</root>

</configuration>


因为上面的日志文件用到spring.application.name,所以需要项目名称的配置挪到bootstrap.yml。

- 测试结果,在浏览器输入
http://localhost:8020/message
发起几次调用后,打开
http://localhost:5601后
看到上述的Kibana页面,说明可以正常使用ELK查询,分析跟踪日志。

sleuth 结合zipkin

通过查看日志分析微服务的调用链路并不是一个很直观的方案,结合zipkin可以很直观地显示微服务之间的调用关系。







通过zipkin可以将调用链路可视化显示。

下面讲解配置步骤:

服务端zipkin-server配置

新建项目
track
,并引入依赖

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


启动类添加
@EnableDiscoveryClient
@EnableZipkinServer
注解

配置文件
application.yml


spring:
application:
name: sleuth-server
server:
port: 9411

eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/ instance:
instanceId: ${spring.application.name}:${spring.cloud.client.ipAddress}:${server.port}


以上服务端就搭建好了

客户端整合zipkin步骤

客户端添加依赖

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


配置文件添加

spring:
zipkin:
base-url: http://127.0.0.1:9411 sleuth:
sampler:
percentage: 1.0


指定了zipkin server的地址,下面制定需采样的百分比,默认为0.1,即10%,这里配置1,是记录全部的sleuth信息,是为了收集到更多的数据(仅供测试用)。在分布式系统中,过于频繁的采样会影响系统性能,所以这里配置需要采用一个合适的值。

zipkin改进

在这里对zipkin进行改进,主要包含两方面

- 通过消息中间件收集sleuth数据

- 持久化sleuth数据

1、通过消息中间件收集sleuth数据

通过消息中间件可以将zipkin server和微服务解耦,微服务无需知道zipkin server地址,只需将sleuth数据传入消息中间件。同时,也可以解决zipkin server与微服务网络不通情况。

改造服务端

- 修改zipkin server(trace项目)配置

<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-server</artifactId>
</dependency>-->
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>


配置文件application.yml增加

rabbitmq:
host: localhost
port: 5673
username: guest
password: guest


这是sleuth数据来源

- 启动类
@EnableZipkinServer
改为
@EnableZipkinStreamServe


以上服务端改造完毕,下面改造客户端(以
helloworld-feign项目为例


改造客户端

helloworldfeign
项目为例

- 修改依赖

<!-- 使用消息中间件后,不再直接和zipkin server-->
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>-->

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-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>


配置文件增加

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


并删除下面指向zipkin server的配置

spring:
zipkin:
base-url: http://127.0.0.1:9411[/code] 
这样就完成了客户端的配置,依次启动
track
helloworldfeign
项目,通过
http://localhost:8030/message
调用其他服务后,在zipkin server 成功获取了
helloworldfeign
的sleuth数据。

在以上的过程中,只要重启zipkin server,发现之前的数据丢失。这是因为zipkin server获取的数据是放在内存的,我们可以获取的服务追踪数据放入到ElasticSearch

2、持久化sleuth数据

- 修改依赖

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

<!-- 持久化到ElasticSearch-->
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>-->
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
<version>1.29.2</version>
</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>


配置文件增加

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


再次启动track项目后,可以将数据持久化到elasticsearch。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐