久趣下载站

当前位置: 首页 » 游戏攻略 » SpringBoot入门到精通(十三)日志:别小看它,否则吃亏的是自己!学会你也可以设计架构

SpringBoot入门到精通(十三)日志:别小看它,否则吃亏的是自己!学会你也可以设计架构


别小看他,当你面对的时候,就会知道,多么痛的领悟!

如何在 Spring Boot 中使用 Logback 记录详细的日志?

整合LogBack,Log4J…等,是不是很多方法!但需要注意,我讲的可能和你是一样的,但也是不一样的。

实战检验真理!论日志的重要性。

在开发企业级应用时,日志记录是一项非常重要的功能。良好的日志记录可以帮助我们快速定位和解决问题。比如异常排查,接口交互!大多数认为,直接log.info.debug一下就可以了…

细节很重要:

通常,生产环境,日志级别要求是很严格的(设置INFO的举手),企业级开发,基本要求不允许太多日志,通常不推荐使用DEBUG级别的日志,因为这会产生大量的日志输出,不仅占用存储空间,还可能影响系统性能。。

SpringBoot与LogBack日志(合并)

1. 引入依赖

在 Spring Boot 项目中,

Logback 是默认的日志框架。Spring Boot 会自动配置 Logback

,因此你通常不需要手动添加 Logback 的依赖。但是,为了确保所有必要的依赖都已包含,你可以在 pom.xml 文件中明确指定这些依赖。

2. 配置 Logback

在 src/main/resources 目录下创建或编辑 logback-spring.xml 文件(按照自动装配机制,文件名和位置,默认)

文件名:logback-spring.xml  (基于自动装配)

位置:src/main/resources/  (基于自动装配)

3. 配置变化量

你可以在 Spring Boot 的配置文件中,使用环境变量来设置日志变量,Spring Boot 支持在 application.properties 或 application.yml 文件中引用环境变量:

你还可以结合多环境配置文件,来设置不同的日志路径。例如,为开发环境、测试环境和预发布环境分别设置不同的日志路径。

application-dev.properties

application-uat.properties

application-pre.properties

application.properties 文件激活特定环境的配置文件即可

SpringBoot与LogBack日志(生产细节控)

问题一

无论是否集群服务,十个人并发也是并发,发起同一个功能或不通功能属于并发交互,日志记录器打印日志时也是有交叉打印。那么如何在百千万行的交叉日志记录中,找到属于某一个指定功能操作的记录呢!

A、B、C都在请求message服务,每个业务的处理时间肯定不一致,并发交叉日志打印时,如何排查耗时?

解决方案:每次交互,从日志的开始就进行标记,直到这个交互结束,只要保证,每个线程,每个交互,标记是唯一的,哪就可以了,即使日志交叉打印,因为保证了唯一标记不同,所以也会很好区分。

Logback 支持在日志输出中插入 MDC(Mapped Diagnostic Context)变量的占位符。在【定义日志文件中记录日志的内容格式】时,有一处标红,那里就是一个MDC取值的示例,MDC 是一个线程上下文相关的键值对存储,可以用来在日志中添加额外的信息,如请求的唯一标识符(UUID)

MDC(Mapped Diagnostic Context)

MDC 概述

MDC 是一个线程上下文相关的键值对存储,每个线程都有自己的 MDC 实例。MDC 是 Logback 和 Log4j 中提供的一个功能,主要用途是在日志记录中添加与当前线程相关的上下文信息,些信息可以是请求的唯一标识符、用户 ID、会话 ID 等,以便在日志中进行更细粒度的跟踪和调试。

主要功能

存储上下文信息:MDC 允许你在日志记录中存储和访问与当前线程相关的上下文信息。

日志格式化:在日志输出模式中使用 MDC 变量,可以在日志消息中插入这些上下文信息。

线程安全:MDC 是线程安全的,每个线程都有独立的 MDC 实例,不会互相干扰。


MDC的使用

1.在每个日志打印之前使用(不推荐,不利用统一管理,但凡有人忘,新人,那日志就没有了,重复,还太麻烦)

控制台输出


2.利用过滤器Filter

可以自定义实现Filter接口哈,这就比较老了,与时俱进吧,Boot中有了,就用吧。


OncePerRequestFilter 概述


OncePerRequestFilter 的主要目的是确保即使在一个请求被多个过滤器链中的多个实例处理时,也只会执行一次过滤逻辑。这对于避免重复处理和潜在的性能问题非常重要。

OncePerRequestFilter 是 Spring Framework 提供的一个过滤器类,用于

确保每个请求只被处理一次

。它继承自 org.springframework.web.filter.OncePerRequestFilter 类,并且通常用于需要在每个 HTTP 请求上执行某些操作的场景,例如日志记录、性能监控、安全检查等。

主要特点

单次执行:确保每个请求只被处理一次,即使在过滤器链中有多个实例。

线程安全:适用于多线程环境,确保线程安全。

灵活性:可以通过重写 doFilterInternal 方法来自定义过滤逻辑。

使用场景

日志记录:在每个请求开始和结束时记录日志。

性能监控:记录每个请求的处理时间。

安全检查:在请求到达控制器之前进行身份验证和授权。

跨域处理:设置响应头以支持跨域请求。、

创建自定义过滤器

创建一个继承自 OncePerRequestFilter 的自定义过滤器,用于生成唯一请求标识符并将其设置到 MDC 中:

备注:关于统一异常处理,请观看我的”
统一异常处理“
,这些都是架构必须要会的。

优化日志第三步,AOP

日志搭建基本完善,但是日志输出呢?每个接口都需要手动log…..

可以利用Spring AOP 对控制器进行环绕通知。在每个控制器的请求处理业务之前,应答返回之前,加入日志记录:接口名,控制器名称,交互的请求报文,应答报文等。

ThreadLocal 是 Java 提供的一个线程局部变量存储机制,每个线程都有自己独立的 ThreadLocal 变量副本,互不干扰。它的主要作用是为每个线程提供独立的变量副本,从而实现线程间的隔离和数据的安全性。下面详细解释 ThreadLocal 的作用、意义和常见使用场景。

作用

线程隔离:

每个线程都有自己独立的 ThreadLocal 变量副本,确保不同线程之间不会相互影响。

适用于需要在线程内部保存状态且不希望其他线程访问这些状态的场景。

简化线程间数据传递:

避免在方法调用之间传递参数,减少方法签名的复杂性。

提高代码的可读性和可维护性。

使用场景

日志追踪:

在分布式系统中,为了追踪请求的整个调用链路,可以在 ThreadLocal 中存储一个唯一的请求标识符(如 traceId),并在日志中输出这个标识符,以便于问题定位和调试。

事务管理:

在事务处理中,可以使用 ThreadLocal 存储事务上下文信息,确保同一个线程中的多个方法调用共享同一个事务上下文。

例如,Spring 的事务管理器 TransactionSynchronizationManager 使用 ThreadLocal 来管理事务上下文。

用户会话信息:

在 Web 应用中,可以使用 ThreadLocal 存储用户的会话信息(如用户 ID、角色等),以便在多个方法调用中使用这些信息,而不需要每次都传递参数。

自定义类ThreadLocalContext ,这个不一定用到,看自己的任务需求,其实这个应该单独介绍的,后来想想还是算了,懒

日志输出样式:(不要看我的日期,我都是手打的)

问题二

日志log….必须要注意的事项。

当有异常处理,不想抛出异常,但需要显示提示,并日志追踪,想便于日志排查时,那么



须使用重载哦



。否则,可能你什么都看不到

SpringBoot与LogBack日志(动态更新级别)

在开发和运维过程中,日志是诊断问题的重要工具。Spring Boot 提供了强大的日志管理功能,但默认情况下,日志级别是在启动时配置的(如上,启动的时候已经配置了日志级别为INFO)。

有时候,我们希望在应用程序运行时动态地调整日志级别,以便更灵活地进行调试和监控。比如生产日志通产为了节省服务器资源,会选择INFO级别,但是问题出现后,又想要DEBU详情,就需要动态更新了。

问题:更新日志级别,由 INFO -→ DEBUG || DEBUG -→ INFO 如果是更改项目配置文件,哪就需要进行服务重启,生产中在不进行版本迭代的情况下,服务重启,是禁忌!如何实现动态更新日志级别,且不重启应用呢?

方式一:SpringBoot监控(不推荐)

先说不推荐原因:生产,对外开放端点,是不明智的选择。当然,安全管理好了,也不是不可以。


Spring Boot Actuator



spring boot

项目一个监控模块,提供了很多原生的端点,包含了对应用系统的自省和监控的集成功能,比如应用程序上下文里全部的Bean、r日志级别、运行状况检查、健康指标、环境变量及各类重要度量指标等等。因此可以通过其自带的日志监控,实现动态更新日志级别。

1. 搭建SpringBoot监控。

参考阅读”
SpringBoot监控
“,里面有详细说明介绍。

2. 注意端点的开启,指定并开启loggers

访问:
localhost:8080/actuator/
loggers,将获取到一个JSON数据:

简单说明:”ROOT”、”com”、”com.alibaba”




…..这些,就是日志记录器的名称,说白了就是你的包层次….着这个包层次,下的所有类,如果有日志,那么其对应的日志级别。(其中ROOT,最高级)







configuredLevel:配置级别(希望配置的级别)

effectiveLevel:有效级别(当前正在使用的级别)







另:子包路径的日志级别,会被父级别传递,反之,单独设置子包日志级别,不影响父包日志级别







如上:若更新 ROOT 日志级别,其他所有级别会同步更新,更新





com.alibaba






日志级别,com.alibaba……所有子级层次的,都会被更新,ROOT 、 com 则不受影响!









3. 动态更新日志级别










POST请求:http://localhost:8080/actuator/loggers/日志记录器名称









请求参数:{“configuredLevel”: “DEBUG”}









重新访问:

http://localhost:8080/actuator/loggers,看下JSON日志级别,就被更新了。此时,查看服务日志即可。














方式二:接口更新LoggerContext(不是强烈推荐,但条件下可以考虑)

先说不推荐原因:自己写接口维护,每次更新调用接口,不是特别方便,但可以用。

接口方式更新日志级别:条件情况可以考虑。如除了对外服务端,还是内部运维管理服务。可以将此接口提供内部服务的管理。由运维部操作使用(本身动态更新日志级别目的,就是为运维开展的)

调用接口:http://IP:端口/api/levelSetting?levelName=root&level=debug

方式三:Nacos配置中心(推荐,但不写)

先说不写原因:微服务知识点,既然本次编辑的是SpringBoot的,Cloud的东东放进来不是很好吧。所以分个类,可以看后续SpringCloud 、SpringCloud Alibaba的更新。这里由
Nacos官方文档
,也可以参考

1. 下载 Nacos 并启动 Nacos server

2. 引入Nacos配置依赖

3. 配置整合Nacos

4. 测试在Nacos控制台更新配置

猜你喜欢
本类排行