随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要可以帮助理解系统行为于分析性能问题的工具以便发生故障的时候,能够快速定位和解决问题。在复杂的微服务架构系统中,几乎每个前端请求都会形成一个复杂的分布式服务调用链路。
一个请求完整调用链可能如下图所示:
本视频跟学 优极限_2021年链路追踪教学-SpringCloud全家桶之Sleuth+Zipkin教程-核心知识点精讲
希望各位多多支持原视频,本篇文章是学习完视频之后,笔记的提炼。
“链路追踪”一词是在2010年提出的,当时谷歌发布了一篇Dapper论文: Dapper, 大规模分布式系统的跟踪系统,介绍了谷歌自研的分布式链路追踪的实现原理,还介绍了他们是怎么低成本实现对应用透明的。
论文(中文翻译)
单纯的理解链路追踪,就是指一次任务的开始到结束, 期间调用的所有系统及耗时(时间跨度)都可以完整记录下来。
实Dapper一开始只是一个独立的调用链路追踪系统, 后来逐渐演化成了监控平台,并且基于监控平台孕育出了很多工具,比如实时预警、过载保护、 指标数据查询等。
除了谷歌的Dapper,还有一些其他比较有名的产品, 比如阿里的鹰眼、大众点评的CAT、Twitter 的Zipkin、Naver (著名社交软件LINE的母公司)的PinPoint以及国产开源的SkyWalking (已贡献给Apache)等。
Spring Cloud Sleuth为Spring Cloud实现了分布式跟踪解决方案。兼容Zipkin, HTrace 和其他基于日志的追踪系统,例如ELK (Elasticsearch. Logstash、 Kibana) 。
Spring Cloud Sleuth提供了以下功能:
链路追踪
:通过Sleuth可以很清楚的看出一个请求都经过了那些服务,可以很方便的理清服务间的调用关系等。性能分析
:通过Sleuth可以很方便的看出每个采样请求的耗时,分析哪些服务调用比较耗时,当服务调用的耗时随着请求量的增大而增大时,可以对服务的扩 容提供定的提醒。数据分析,优化链路
:对于频繁调用一个服务,或并行调用等,可以针对业务做一些优化措施。可视化错误
:对于程序未捕获的异常,可以配合Zipkin查看。基本工作单位,一次单独的调用链可以称为一个Span, Dapper 记录的是Span的名称,以及每个Span的ID和父ID,重建在一次追踪过程中不同Span之间的关系,图中一个矩形框就是一个 Span,前端从发出请求到收到回复就是一个Span。
开始跟踪的初始跨度称为root span 。该跨度的ID的值等于跟踪ID。
Dapper录了span名称,以及每个span的ID和父spanID,以重建在一次追踪过程中不同span之间的关系。如果一个span没有父ID被称为root span。所有span都挂在一个特定的Trace上,也共用一个trace id。
图示为Help.Call微服务模块展开的具体结构。
一列Span组成的树状结构,一个Trace认为是一次完整的链路, 内部包含n多个Span。Trace 和Span存在一对多的关系,Span与Span之间存在父子关系。
举个例子:户端调用服务A、服务B、服务C、服务F,而每个服务例如C就是一个Span,如果在服务C中另起线程调用了D,那么D就是C的子Span,如果在服务D中另起线程调用了E,那么E就是D的子Span,这个C->D->E的链路就是条Trace。如果链路追踪系统做好了,链路数据有了,借助前端解析和渲染工具,可以达到下图中的效果:
我们后面要学习的zipkin的可视化界面如下:
用来及时记录一个事件的存在,一些核心annotations用来定义一个请求的开始和结束。
公式:
网络延迟 = sr - cs
服务端处理请求需要的时间 = ss - sr
客户端从服务端获取回复的所有所需时间 = cr - cs
如果想知道一个接口在哪个环节出现了问题,就必须清楚该接口调用了哪些服务,以及调用的顺序,如果把这些服务串起来,看起来就像链条一样,我们称其为调用链。
想要实现调用链,就要为每次调用做个标识,然后将服务按标识大小排列,可以更清晰地看出调用顺序,我们暂且将该标识命名为spanid。
实际场中,我们需要知道某次请求调用的情况,所以只有spanid还不够,得为每次请求做个唯一标识, 这样才能根据标识查出本次请求调用的所有服务,而这个标识我们命名为traceid。
现在根据spanid可以轻易地知道被调用服务的先后顺序,但无法体现调用的层级关系,正如下图所示,多个服务可能是逐级调用的链条,也可能是同时被同一个服务调用。
所以应该每次都记录下是谁调用的,我们用parentid 作为这个标识的名字。
到现在,已经知道调用顺序和层级关系了,但是接口出现问题后,还是不能找到出问题的环节,如果某个服务有问题,那个被调用执行的服务一定耗时很长, 要想计算出耗时,上述的三个标识还不够, 还需要加上时间戳,时间戳可以更精细一点,精确到微秒级。
增加请求发起的timestamp。
只记录发起调用时的时间戳还算不出耗时,要记录下服务返回时的时间戳,有始有终才能算出时间差,既然返回的也记了,就把上述的三个标识都记一下吧, 不然区分不出是谁的时间戳。
虽然能计算出从服务调用到服务返回的总耗时,但是这个时间包含了服务的执行时间和网络延迟,有时候我们需要区分出这两
类时间以方便做针对性优化。那如何计算网络延迟呢?我们可以把调用和返回的过程分为以下四个事件。
假如在这四个事件发生时记录下时间戳,就可以轻松计算出耗时,比如:
sr减去cs就是调用时的网络延迟
ss 减去sr就是服务执行时间
cr减去ss就是服务响应的延迟
cr减cs就是整个服务调用执行的时间
其实span内除了记这几个参数之外,还可以记录一其他信息,比如发起调用服务名称、被调服务名称、返回结果、IP、调用服务的名称等,最后,我们再把相同parentid的span信息合成一个大的span块,就完成了一个完整的调用链。
以上原型图来自张以诺的绘制。
课件资料:
百度云-课件
提取码:c8cp
在IDEA中打开
导入项目后如下:
然后顺序启动:
eureka-server
eureka-server2
gateway
order-service
product-service
启动eureka-server和eureka-server2的时候增加配置
register-with-eureka: false #是否将自己注册到eureka中
fetch-registry: false #是否从eureka中拉去信息列表
这里注意,如果出现子项目@SpringBootApplication报红问题
解决方案:右键-maven-reload project
验证Eureka是否启动成功
访问
http://localhost:8761/
验证product-service服务是否启动成功
访问
http://localhost:7070/product/listByIds?id=1&id=2
http://localhost:9090/order/1
http://localhost:9000/order-service/order/1
http://localhost:9000/product-service/product/listByIds?id=1&id=2
在需要进行链路追踪的项目中(服务网关、商品服务、订单服务)添加 spring-cloud-starter-sleuth 依赖。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-sleuthartifactId>
dependency>
在需要链路追踪的项目中(服务网关、商品服务、订单服务)添加 logback.xml 日志文件,内容如下(logback 日志的输出级别需要是 DEBUG 级别):
注意修改
< property name=“log.path”
value=“${catalina.base}/gateway-server/logs”/ >
中项目名称。
日志核心配置:
%d{yyyy-MM-dd HH:mm:ss.SSS}
[${applicationName},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}] [%thread]%-5level %logger{50} - %msg%n
注意:资料中提供的日志文件有编码问题,直接拷贝我这里的即可
logback.xml
<configuration scan="true" scanPeriod="10 seconds">
<contextName>my_logbackcontextName>
<property name="log.path" value="${catalina.base}/gateway-server/logs"/>
<springProperty scope="context" name="applicationName"
source="spring.application.name" defaultValue="localhost"/>
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS}
[${applicationName},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}] [%thread] %-5level
%logger{50} - %msg%n"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUGlevel>
filter>
<encoder>
<pattern>${LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
appender>
<appender name="DEBUG_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log_debug.logfile>
<encoder>
<pattern>${LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUGlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
appender>
<appender name="INFO_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log_info.logfile>
<encoder>
<pattern>${LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFOlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
appender>
<appender name="WARN_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log_warn.logfile>
<encoder>
<pattern>${LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARNlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
appender>
<appender name="ERROR_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log_error.logfile>
<encoder>
<pattern>${LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
<totalSizeCap>10GBtotalSizeCap>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERRORlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
appender>
<logger name="myLog" level="INFO" additivity="false">
<appender-ref ref="CONSOLE"/>
logger>
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="DEBUG_FILE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="WARN_FILE"/>
<appender-ref ref="ERROR_FILE"/>
root>
configuration>
访问:
http://localhost:9000/order-service/order/1
[gateway-server,f82de2d68493f0cb,f82de2d68493f0cb]
[product-service,f82de2d68493f0cb,93fc5e739328a597]
订单服务打印信息
[order-service,f82de2d68493f0cb,a94f977efaf08f05]
通过打印信息可以得知,
整个链路的 traceId为:f82de2d68493f0cb,
spanId 为:93fc5e739328a597 和 a94f977efaf08f05 。
查看日志文件并不是一个很好的方法,当微服务越来越多日志文件也会越来越多,查询工作会变得越来越麻烦,Spring 官方推荐使用Zipkin 进行链路跟踪。Zipkin 可以将日志聚合,并进行可视化展示和全文检索。
ZIPKIN官网
ZIPKIN是 Twitter 公司开发贡献的一款开源的分布式实时数据追踪系统(Distributed TrackingSystem),基于 Google Dapper 的论文设计而来,其主要功能是聚集各个异构系统的实时监控数据。
它可以收集各个服务器上请求链路的跟踪数据,并通过 Rest API 接口来辅助我们查询跟踪数据,实现对分布式系统的实时监控,及时发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。除了面向开发的 API 接口之外,它还提供了方便的 UI 组件,每个服务向 Zipkin 报告计时数据,Zipkin 会根据调用关系生成依赖关系图,帮助我们直观的搜索跟踪信息和分析请求链路明细。Zipkin 提供了可插拔数据存储方式:In-Memory、MySql、Cassandra 以及 Elasticsearch。
分布式跟踪系统还有其他比较成熟的实现,例如:Naver 的 PinPoint、Apache 的 HTrace、阿里的鹰眼 Tracing、京东的 Hydra、新浪的 Watchman,美团点评的 CAT,Apache 的 SkyWalking 等。
Zipkin 分为两端,一个是 Zipkin 服务端,一个是 Zipkin 客户端,客户端也就是微服务的应用,客户端会配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务里面的 Sleuth 的监听器监听,并生成相应的 Trace 和 Span 信息发送给服务端。发送的方式有两种,一种是消息总线的方式如 RabbitMQ 发送,还有一种是 HTTP 报文的方式发送。
服务端是一个独立的可执行的 jar 包,官方下载地址:ZIPKIN下载地址,使用 java -jar zipkin.jar 命令启动,端口默认为9411 。我们下载的 jar 包为:zipkin-server-2.20.1-exec.jar。
资料中带这个jar包:
启动命令如下:
java -jar zipkin-server-2.20.1-exec.jar
访问:
http://localhost:9411/
在需要进行链路追踪的项目中(服务网关、商品服务、订单服务)添加 spring-cloud-starter-zipkin 依赖。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zipkinartifactId>
dependency>
在需要进行链路追踪的项目中(服务网关、商品服务、订单服务)配置 Zipkin 服务端地址及数据传输方式。默认即如下配置。
spring:
zipkin:
base-url: http://localhost:9411/ # 服务端地址
sender:
type: web # 数据传输方式,web 表示以 HTTP 报文的形式向服务端
sleuth:
sampler:
probability: 1.0 # # 收集数据百分比,默认 0.1(10%)
这里type:web 是按照Http报文的方式发送的,后续会更改为其它方式。
更改玩之后重启项目
现在的调用链路如下:
client -> gateway -> order-service -> product-service
访问:
http://localhost:9000/order-service/order/1
新版操作如下:访问:
http://localhost:9411/
我们多访问几次订单或者库存,这里zipkin也会产生几条数据
点击对应的追踪信息可查看请求链路详细。
查看时间戳
还可以下载为JSON的数据
通过依赖可以查看链路中服务的依赖关系。而且还有服务调度的动态展示,有个小球移动,非常人性化。
旧版操作如下:
访问:
http://localhost:9411/
点击查找结果如下:
点击对应的追踪信息可查看请求链路详细。
通过依赖可以查看链路中服务的依赖关系。
而目前我们的所有配置,只要重启都没有了,那我们就需要存储追踪服务。
Zipkin Server 默认存储追踪数据至内存中,这种方式并不适合生产环境,一旦 Server 关闭重启或者服务崩溃,就会导致历史数据消失。Zipkin 支持修改存储策略使用其他存储组件,支持 MySQL,Elasticsearch 等。
打开 MySQL 数据库,创建 zipkin 库,执行以下 SQL 脚本。
官网地址:官网地址
CREATE DATABASE zipkin;
USE zipkin;
这里就不能通过jar的默认形式直接启动服务端了,而是要添加启动参数,重新部署服务端:
官网地址:Zipkin服务端用于MySql
java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin
访问:
http://localhost:9000/order-service/order/1
在 MySQL 模式下,每次启动服务端时,服务端会从数据库加载链路信息展示至 Web 界面。
我们用CTRL + C,esc 退出Zipkin,然后此时访问zipkin服务端,发现无法访问,那之前的数据丢失了吗,我们重启zipkin服务端看看
访问
http://localhost:9411/zipkin/
之前的课程中我们已经学习过 RabbitMQ 的详细使用,这里不再过多赘述,直接开启使用即可。
目前的链路模式是:
client
开启虚拟机,通过以下命令启动 RabbitMQ 服务端。
systemctl start docker
docker start mq
访问
ip:15672
添加启动参数,重新部署服务端:
官网地址:官网部署-mq
java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin --RABBIT_ADDRESSES=192.168.10.101:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_VIRTUAL_HOST=/ --RABBIT_QUEUE=zipkin
启动参数中包含 MySQL 和 RabbitMQ 的配置,实现基于 MQ 并存储链路信息至 MySQL,如下图:
访问:http://192.168.10.101:15672/#/queues 可以看到已经创建好了 zipkin 队列。
这里为了看见消息消费的过程,我们停止服务端,并且清空mysql中zipkin数据库的表。
官网文档:官方文档
在网关、订单服务、产品服务都添加
<dependency>
<groupId>org.springframework.amqpgroupId>
<artifactId>spring-rabbitartifactId>
dependency>
application.yml
spring:
application:
name: gateway-server # 应用名称
cloud:
gateway:
discovery:
locator:
# 是否与服务发现组件进行结合,通过 serviceId 转发到具体服务实例。
enabled: true # 是否开启基于服务发现的路由规则
lower-case-service-id: true # 是否将服务名称转小写
zipkin:
base-url: http://localhost:9411/ # 服务端地址
sender:
# ype: web # 数据传输方式,web 表示以 HTTP 报文的形式向服务端
type: rabbit # 数据传输方式,web 表示以 HTTP 报文的形式向服务端
sleuth:
sampler:
probability: 1.0 # # 收集数据百分比,默认 0.1(10%)
rabbitmq:
host: 192.168.10.101
port: 5672
username: guest
password: guest
virtual-host: /
listener:
direct:
retry:
enabled: true
max-attempts: 5
initial-interval: 5000
simple:
retry:
enabled: true
max-attempts: 5
initial-interval: 5000
先关闭 Zipkin 服务端,访问:
http://localhost:9000/order-service/order/1
客户端已将链路追踪数据写入队列当中:
启动 Zipkin 服务端后,队列中消息被堆积
此时我们再此启动Zipkin的服务端
java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=localhost --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=root --MYSQL_DB=zipkin --RABBIT_ADDRESSES=192.168.10.101:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_VIRTUAL_HOST=/ --RABBIT_QUEUE=zipkin
之前的课程中我们已经学习过 Elasticsearch 的详细使用,这里不再过多赘述,直接开启使用即可。
启动集群,访问:
http://192.168.10.101:9200/
启动 head 插件,访问:http://192.168.10.101:9100/ 结果如下:
添加启动参数,重新部署服务端:
官网地址:Zipkin服务端
java -jar zipkin-server-2.20.1-exec.jar --STORAGE_TYPE=elasticsearch --ES_HOSTS=http://192.168.10.101:9200/,http://192.168.10.102:9200/,http://192.168.10.103:9200/ --RABBIT_ADDRESSES=192.168.10.101:5672 --RABBIT_USER=guest --RABBIT_PASSWORD=guest --RABBIT_QUEUE=zipkin
启动参数中包含 Elasticsearch 和 RabbitMQ 的配置,实现基于 MQ 并存储链路信息至Elasticsearch。
访问:http://192.168.10.101:9100 可以看到已经创建好了 zipkin 索引库。
官网文档:官方文档
<dependency>
<groupId>org.springframework.amqpgroupId>
<artifactId>spring-rabbitartifactId>
dependency>
spring:
zipkin:
base-url: http://localhost:9411/ # 服务端地址
sender:
type: rabbit
rabbitmq:
queue: zipkin # 队列名称
rabbitmq:
host: 192.168.10.101 # 服务器 IP
port: 5672 # 服务器端口
username: guest # 用户名
password: guest # 密码
virtual-host: / # 虚拟主机地址
listener:
direct:
retry:
enabled: true # 是否开启发布重试
max-attempts: 5 # 最大重试次数
initial-interval: 5000 # 重试间隔时间(单位毫秒)
simple:
retry:
enabled: true # 是否开启消费者重试
max-attempts: 5 # 最大重试次数
initial-interval: 5000 # 重试间隔时间(单位毫秒)
sleuth:
sampler:
probability: 1.0 # 收集数据百分比,默认 0.1(10%)
访问:
http://localhost:9000/order-service/order/1
ELK 是 elastic 公司提供的一套完整的日志收集以及展示的解决方案,是三个产品的首字母缩写,分别是 ElasticSearch、Logstash 和 Kibana。
之前的课程中我们已经学习过 ELK 的详细使用,这里不再过多赘述,直接开启使用即可。文中使用的 ELK 版本统一为 7.5.2。
Logstash 运行时指定的配置文件 log-to-es.conf 内容如下:
# 数据入口
input {
tcp {
mode => "server"
host => "192.168.10.101"
port => 9250
}
}
# 处理数据
filter {
# 获取 @timestamp 的值并加上 8*60*60(北京时间比 logstash 中@timestamp 晚了 8 小
时),然后赋值给变量 timestamp。
ruby {
code => "event.set('timestamp', event.get('@timestamp').time.localtime +
8*60*60)"
}
# 将 timestamp 值重新赋值给 @timestamp
ruby {
code => "event.set('@timestamp', event.get('timestamp'))"
}
# 删除变量 timestamp
mutate {
remove_field => ["timestamp"]
}
}
# 数据出口
output {
elasticsearch {
hosts => ["192.168.10.101:9200", "192.168.10.102:9200",
"192.168.10.103:9200"]
index => "applog"
}
}
在需要进行链路追踪的项目中(服务网关、商品服务、订单服务)添加 logstash-logback-encoder 依赖。
<dependency>
<groupId>net.logstash.logbackgroupId>
<artifactId>logstash-logback-encoderartifactId>
<version>6.3version>
dependency>
在需要进行链路追踪的项目中(服务网关、商品服务、订单服务)添加 logstash 输出 JSON 格式数据 。
logback.xml
<configuration scan="true" scanPeriod="10 seconds">
...
<appender name="LOGSTASH_PATTERN"
class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>192.168.10.101:9250destination>
<encoder
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{
"severity": "%level",
"service": "${springAppName:-}",
"trace": "%X{X-B3-TraceId:-}",
"span": "%X{X-B3-SpanId:-}",
"exportable": "%X{X-Span-Export:-}",
"pid": "${PID:-}",
"thread": "%thread",
"class": "%logger{40}",
"rest": "%message"
}
pattern>
pattern>
providers>
encoder>
appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOGSTASH_PATTERN"/>
<appender-ref ref="DEBUG_FILE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="WARN_FILE"/>
<appender-ref ref="ERROR_FILE"/>
root>
...
configuration>
访问:http://192.168.10.101:9100 可以看到已经创建好了 applog 索引库。
访问:http://localhost:9000/order-service/order/1 查看索引库结果如下:
访问:http://192.168.10.101:5601/ Kibana 首页
添加 applog 索引库。
不使用时间过滤器。
搜索 gateway 结果如下: