微服务架构项目实战将日志输出至ELK编码实践
日志中心搭建好了,演示代码也编写完成。下面笔者拓展讲解一下在本书最终的微服务架构实战项目中进行配置的过程(实战项目的介绍和搭建将在第 14 章中详细介绍),把微服务架构项目中各个服务实例的日志信息输出到 ELK
日志中心,也就是在微服务实例和 ELK
日志中心之间搭建管道。
微服务架构项目中的日志输出配置
-
引入
logstash-logback-encoder
依赖。依次打开
newbee-mall-cloud-user-web
、newbee-mall-cloud-recommend-web
、newbee-mall-cloud-order-web
、newbee-mall-cloud-shop-cart-web
和newbee-mall-cloud-goods-web
五个微服务实例工程中的pom.xml
文件,在dependencies
节点下新增logstash-logback-encoder
的依赖项,配置代码如下:<dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>7.0.1</version> </dependency>
-
添加
Logback
日志配置文件。依次打开
newbee-mall-cloud-user-web
、newbee-mall-cloud-recommend-web
、newbee-mall-cloud-order-web
、newbee-mall-cloud-shop-cart-web
和newbee-mall-cloud-goods-web
五个微服务实例工程,在src/main/resources
目录下创建logback.xml
配置文件,代码如下:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <include resource="org/springframework/boot/logging/logback/console-appender.xml"/> <!-- 应用名称 --> <property name="APP_NAME" value="newbee - mall - cloud - order - service - log"/> <contextName>${APP_NAME}</contextName> <!-- 控制台的日志输出样式 --> <property name="CONSOLE_LOG_PATTERN" 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} %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>INFO</level> </filter> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>utf8</charset> </encoder> </appender> <!-- 输出到Logstash --> <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>192.168.110.57:4560</destination> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/> </appender> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="LOGSTASH"/> </root> </configuration>
配置信息基本一致,只是
APP_NAME
参数有差异。管道搭建好了,接下来启动项目测试一下,结果如图 13-23 所示。Figure 1. 图13-23 启动项目测试结果是的,又报错了,错误信息贴在下面了。
23:45:46,970 |-ERROR in ch.qos.logback.classic.joran.action.ContextNameAction - Failed to rename context [newbee-mall-cloud-order-service-log] as [nacos] java.lang.IllegalStateException: Context has been already given a name at java.lang.IllegalStateException: Context has been already given a name
报错的原因并不复杂,依赖冲突导致的。
Spring Boot
框架中已经集成了日志框架Logback
,而项目依赖nacos-client
中也配置了Logback
(nacos-client
中的Logback
加载要优先于项目自身的Logback
框架),在一个项目中context_name
只能定义一次,因此在项目启动时,nacos-client
中的Logback
加载完成后,再加载项目本身的Logback
就出现了冲突。这个报错并不影响使用,但是最好处理掉,只需要在启动类中增加如下代码:
System.setProperty("nacos.logging.default.config.enabled", "false");
只加载自定义的
Logback
配置,不使用nacos-client
依赖中的配置,这样就不会冲突了。因此,需要在newbee-mall-cloud-user-web
、newbee-mall-cloud-recommend-web
、newbee-mall-cloud-order-web
、newbee-mall-cloud-shop-cart-web
和newbee-mall-cloud-goods-web
五个微服务实例工程下的启动类中添加以上代码。 -
新增日志输出的测试代码。
这里主要是为了模拟平时
Error
日志的输出,以及测试在Kibana
中查询日志,在newbee-mall-cloud-goods-web
工程的NewBeeMallGoodsController
类中新增如下代码:@GetMapping("/test1") public Result<String> test1() throws BindException { throw new BindException(1, "BindException"); } @GetMapping("/test2") public Result<String> test2() throws NewBeeMallException { NewBeeMallException.fail("NewBeeMallException"); return ResultGenerator.genSuccessResult("test2"); } @GetMapping("/test3") public Result<String> test3() throws Exception { int i = 1 / 0; return ResultGenerator.genSuccessResult("test2"); }
因为之前已经在全局异常处理类中配置了异常的拦截和日志输出,所以在浏览器的地址栏中访问上述代码中的地址,就会直接输出三条
Error
级别的测试日志。
通过Kibana查询日志
-
查看日志
微服务工程中的实例启动后,日志都可以在
Kibana
中查看。如果想仔细验证,可以在搜索框中输入关键词进行更精准的匹配。比如,笔者分别搜索了订单微服务和用户微服务的启动类名称,搜索结果如图 13-24 和图 13-25 所示。另外,搜索时一定要注意时间区间,有时搜索不到可能是时间选择不对,页面右上角有时间选择器,单击即可切换。
-
日志定时刷新
当然,有些读者问过笔者:页面里的日志怎么不刷新呢?明明输出了日志且时间选择正确,但是
Kibana
页面就是没有显示。这是因为在默认情况下,Kibana
中的Discover
页面不会定时刷新,需要手动单击右上角的 “刷新” 按钮。想要设置自动刷新,可以按照图 13-26 中的示意设置Discover
页面的自动刷新。Figure 2. 图13-24 搜索结果1Figure 3. 图13-25 搜索结果2Figure 4. 图13-26 设置自动刷新 -
常用的日志搜索条件
除输入一些关键词外,还可以根据关键字段搜索日志。比如,直接搜索最近15分钟
Error
级别的日志,就可以在输入框中输入 “level:error” 来搜索,相关的信息就会显示出来,如图 13-27 所示。Figure 5. 图13-27 “level:error”搜索结果当然,如果想更精确,那就加上一些条件,如最近 15 分钟
GoodsServiceExceptionHandler
输出的Error
日志就可以在输入框中输入 level:error andlogger_name:"ltd.goods.cloud.newbee.config.GoodsServiceExceptionHandler" 来搜索,相关的信息就会显示出来,如图 13-28 所示。Figure 6. 图13-28 精确搜索结果除此之外,还可以使用自己在代码中定义的一些字符,如 “mamimamihong”、“zhimakaimen” 等,都是一些自定义的信息,觉得哪里可能会出问题,就输出日志看一下,这样定位问题也更快一些。当然,也不要输出太多日志,没问题了就把一些没用的日志及时删掉。
笔者在平时上班时,到工位后要做的事是查看邮件和查看负责的业务的错误日志。浏览器中一直开着
Kibana
页面,时不时地刷新一下,有问题赶紧定位并处理。Kibana
真的是企业开发中不可或缺的一个工具。 -
根据
traceId
搜索日志在前面的章节中,使用
Spring Cloud Sleuth
和Zikpin
完成了一套链路追踪系统,可以帮助开发人员串联调用链路中的上下游访问链路,快速定位线上异常出现在哪个环节。不过,仅仅只是日志打标和追踪还不够,想要得到更加详细的信息,还要借助程序中输出的日志信息。这样,链路追踪加上日志中心,整个链路追踪就闭环了,有日志打标、日志收集、日志索引、日志精确搜索、链路可视化和日志的统计报表等。这里简单举一个例子。比如,看到
Error
日志后,想要查看上下游服务实例的一些情况,就可以在Kibana
中把Error
日志中的traceId
或spanId
作为搜索条件进行查询,查询条件输入 “traceId:xxxxxxxx” 或 “spanId:xxxxxxxx”,或者直接搜索traceId
或spanId
的值也可以,如图 13-29 所示。Figure 7. 图13-29 查看上下游服务实例拔出萝卜带出泥,与之相关联的一些日志就都显示出来了。
为了课程演示需要及展现出更好的效果,笔者在代码里把一些日志级别调成了 Debug
级别。私下测试时可以这么做,但是在企业开发中千万不能这么做,因为 Debug
级别的日志真的太多了,超出想象的那种量级。ELK
日志中心的整合及配置讲解完成了,整个链路追踪过程和 ELK
日志中心的搭建及整合的知识点也完成了闭环。