Spring Cloud 微服务(七)- 上:日志收集集成
本文简单介绍如何在项目中集成日志收集。
1. 缘由
每次看日志信息都需要登陆到远程服务器,会很麻烦,而且不同应用的日志需要切换到不同的日志文件,有时候还要联合多个日志文件查看请求涉及的所有信息。总结下来主要有 3 点问题:
- 查看不便
- 信息分散
- 检索麻烦
怎么解决呢?使用日志收集工具,将所有日志统一收集汇总分析,Spring 列举了两款日志收集工具:
笔者这里使用 Kibana 实现日志收集,Kibana 只做日志信息可视化,还需要使用到 Elasticsearch 和 Logstash,俗称 ELK。
2. 通过 Docker 安装 ELK
参考 docker-elk,检出到本地后,修改 Logstash 配置:
learn-docker/composes/elk/logstash/config/logstash.yml
#指定接收 logstash 队列中的所有消息
input {
rabbitmq {
host => "rabbitmq"
port => 5672
type => "logstash"
exchange => "logger"
exchange_type => "topic"
key => "#"
queue => "logstash"
durable => true
}
}
修改后内容已上传至 peacetrue-docker,可检出后与本项目配套使用。
3. 改造项目
修改项目日志配置,输出日志到消息队列。添加 logback-spring.xml
配置文件,重要部分内容如下:
logback-spring.xml
<appender name="AMQP" class="org.springframework.amqp.rabbit.logback.AmqpAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<excludeMdcKeyName>rootLevel</excludeMdcKeyName>
<shortenedLoggerNameLength>36</shortenedLoggerNameLength>
<fieldNames>
<logger>class</logger>
<thread>thread</thread>
</fieldNames>
</encoder>
<host>${amqpHost}</host>
<port>${amqpPort}</port>
<username>${amqpUsername}</username>
<password>${amqpPassword}</password>
<durable>false</durable>
<deliveryMode>NON_PERSISTENT</deliveryMode>
<applicationId>${springAppName}</applicationId>
<generateId>true</generateId>
<charset>UTF-8</charset>
</appender>
<springProfile name="rabbitmqLog">
<root level="${rootLevel}">
<appender-ref ref="AMQP"/>
</root>
<!--很重要,DEBUG 级别会死循环。调用 RabbitTemplate 上传日志会记录 DEBUG 级别日志,记录日志又会触发上传日志 -->
<logger name="org.springframework.amqp.rabbit.core" level="INFO"/>
</springProfile>
每个项目都需要使用这个配置文件,如果拷贝到各个项目会很麻烦。在远程仓库通过 logging.config: file:peacetrue-microservice-common/logback-spring.xml
统一指定。
4. 启动项目
这里使用配置中心进行测试,启动应用后,会自动创建 logger
交换机:
日志消息通过路由键 应用名.类名.日志级别 发送到 logger
交换机;Logstash 从 logstash
队列上接收所有消息,然后转发至 Elasticsearch;最后 Kibana 从 Elasticsearch 读取数据后进行展示。
5. 查看日志
打开 Kibana 页面 http://localhost:5601 ,输入账号密码 elastic/changeme,查看日志信息:
Figure 1. kibana日志信息
6. 集成 Sleuth
现在 Kibana 可以看到所有应用的日志信息,但不能查看某个特定请求[1]相关的所有日志,需要通过 Sleuth 添加追踪信息。
首先,在项目中添加 org.springframework.cloud:spring-cloud-starter-sleuth
依赖。重新启动项目后,日志信息如下:
root.log
2020-07-21 08:38:51.994 INFO [peacetrue-microservice-config-center,,,] 51465 --- [nio-8888-exec-9] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-07-21 08:38:52.026 INFO [peacetrue-microservice-config-center,,,] 51465 --- [nio-8888-exec-9] o.s.web.servlet.DispatcherServlet : Completed initialization in 31 ms
2020-07-21 08:39:14.502 INFO [peacetrue-microservice-config-center,8f3f9cab95d38edb,8f3f9cab95d38edb,false] 51465 --- [nio-8888-exec-3] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/var/folders/1s/ly4n5ft11r19j6859j20mb380000gn/T/config-repo-4056814041444408501/application.yml (document #7)
2020-07-21 08:39:14.502 INFO [peacetrue-microservice-config-center,8f3f9cab95d38edb,8f3f9cab95d38edb,false] 51465 --- [nio-8888-exec-3] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/var/folders/1s/ly4n5ft11r19j6859j20mb380000gn/T/config-repo-4056814041444408501/application.yml (document #6)
在日志级别后面,会出现 [appName,spanId,traceId,export]
:
- appName:应用名
- spanId:追踪内节点标识,没有为空
- traceId:追踪标识,没有为空
- export:是否上报到 Zipkin,目前没有集成 Zipkin,都是 false
这是 Sleuth 提供的,有了这些信息,就可以将整个请求链条串起来。
重新查看 Kibana:
Figure 2. 重新查看 Kibana
现在通过 trace
过滤,就能查出整个请求涉及的相关日志。
7. 关于 logstash-logback-encoder
参考 https://www.baeldung.com/java-application-logs-to-elastic-stack
可以直接使用 net.logstash.logback:logstash-logback-encoder:4.11
,从日志文件中读取日志后上传到 Elasticsearch,不需要使用 RabbitMQ,也不需要单独部署 Logstash 服务,简化了流程。但需要每个项目配置类似的 logback.conf
,logback.conf
中不能使用占位符[2],分环境配置也很麻烦,最终放弃。
8. 总结
做完之后,发现用 Sentry 更合适。ELK 主要是全文检索分析统计,如果只是汇总查看信息没必要。
1. 比如访问外部客户端的 /message 接口,外部客户端会调接口网关,接口网关再调用资源服务
2. 未经证实
- 企业级Tomcat安全管理优化方案
- “妈妈”域名Mommy.com66万高价易主 现已建站
- 脸书Messenger已中招,新的加密货币挖矿病毒出现!
- Linux中MySQL配置文件my.cnf参数优化
- 干货,比较全面的c#.net公共帮助类(Common.Utility)
- Linux中如何恢复rm命令误删除的文件之extundelete编译安装及使用
- JDK1.7 安装加(一劳永逸的环境配置)
- Jquery 遍历数组之$().each方法与$.each()方法介绍
- ExtJs学习笔记(2)_Basic GridPanel[基本网格]
- Jquery 遍历数组之grep()方法介绍
- ExtJs学习笔记(1)_Hello World!
- Jquery filter()方法简介
- 加拿大滑铁卢大学刘腾博士:平行增强学习及其无人驾驶应用
- 曾六位数被秒的yadea.com 终端真是雅迪!
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- SAP CRM订单数据库表CRMD_SHIPPING的填充原理
- 使用art-template模板引擎渲染数据
- SAP CRM索引数据库表CRMD_ORDER_INDEX的更新原理
- 将自己的nodeJS项目分享到npm上
- react中使用prop-types检测props数据类型
- git的常用命令及工作中冲突问题解决方法
- 关于react中的context
- 基于Node.js的Express框架
- react官方推荐的classnames库
- 在Deno中构建一个命令行天气预报程序
- react-router4
- redux
- react-redux
- Webstorm之界面美化-含破解版
- 使用Cmder替换cmd,让开发更高效