一次springboot日志不生效问题深入分析

本文深入分析了SpringBoot日志不生效的问题,主要原因是配置变动导致日志读取失败。在启动过程中,LoggingSystem根据logback、log4j、javaLog的优先级选择日志实现。当logging.config配置在bootstrap中未被处理时,将无法按预期配置日志,导致日志不打印。解决方案是确保logging.config配置正确,并在正确的位置被加载。

springboot日志不生效问题深入分析

auth by:yangs , at 2022-09-22

现象

在一次环境排查问题中,发现某系统日志不打印。通过各种排查,总结后引起原因为配置这块后面改动比较多,有配置移动,打包脚本优化涉及关联改动。导致错误配置引起日志读取失败。无法到达预期配置的效果。

深入分析

在LoggingApplicationListener进行日志系统处理。
在启动初期LoggingSystem会根据引入包判断引用哪种日志实现。按照logback,log4j,javaLog的优先级顺序,判断类是否加载决定日志具体实现。
LoggingSystem初始化
判断是否引入对应的jar
LoggingSystem决定日志具体实现方式
接着进入环境配置处理。
在bootstrap处理里面可以看到,而恰好修改过后的配置logging.config放这个文件里面。
加载bootstrap
在这里插入图片描述
这里未启动bootstrap.enable,不会后续处理。故拿不到bootstrap里面的logging.config配置。
接着

<think>好的,用户再次询问关于Spring Boot单体项目中多端口启动的问题,需要找到配置位置并进行源码分析来修改端口。首先,我需要回顾之前的对话,确保不重复信息,同时补充更深入的分析。 用户之前的问题是关于项目启动时除了配置的端口外,还出现了另一个端口,想找到配置位置并修改。之前的回答已经涵盖了常见原因,如Actuator、Dubbo、Nacos等,并给出了排查步骤和修改方法。现在用户可能希望更深入地了解源码层面的分析,或者可能有其他潜在原因未被覆盖。 用户这次特别提到是单体项目,所以可能需要排除微服务相关组件的影响,但也不能完全排除第三方库的可能。需要强调源码中如何定位端口配置,比如自动配置类、Bean的定义等。 首先,用户需要的是如何通过分析Spring Boot的源码来找到端口配置的位置。这需要解释Spring Boot内嵌服务器的启动流程,比如Tomcat或Netty是如何被初始化的,以及哪些配置类负责端口的设置。 其次,用户可能想知道如何在代码中硬编码端口的情况,虽然不常见,但有时开发人员可能会在自定义的WebServerFactory中设置端口,导致覆盖配置文件的值。需要指导用户如何搜索这类代码。 另外,可能涉及到的自动配置类,比如ServerProperties、ManagementServerProperties,这些类如何读取配置文件中的server.port和management.server.port。需要指出这些类的源码位置,帮助用户理解配置是如何被加载的。 还有可能需要提到Spring Boot的条件化配置,比如某些库在类路径存在时会自动启用,导致额外的端口被打开。例如,Actuator的独立管理端口需要management.server.port的显式配置,否则默认使用主端口,但如果有其他库如Spring Cloud Config Server,可能需要不同的处理。 用户还可能想知道如何通过调试或日志来追踪端口的绑定过程。例如,在应用启动时,内嵌服务器初始化的日志会显示端口信息,可以通过增加日志级别来查看更多细节。 另外,需要考虑用户是否有自定义的Servlet或Filter,或者集成了其他框架如gRPC,这些可能会启动额外的服务器实例,占用端口。需要提醒用户检查项目依赖,排除不必要的库,并检查相关配置。 总结来说,需要分步骤详细说明源码分析的方法,结合配置文件和代码检查,以及如何通过工具和日志来定位问题。确保回答结构清晰,覆盖所有可能的配置位置和源码路径,帮助用户彻底解决问题。</think>### Spring Boot单体项目多端口问题的源码级分析与配置修改 --- #### 一、核心配置源码分析 Spring Boot的端口配置主要通过**内嵌Web容器**和**扩展组件**实现,以下是关键源码路径和配置逻辑: 1. **主服务端口(`server.port`)** - **源码入口**:`org.springframework.boot.autoconfigure.web.ServerProperties` ```java @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties { private Integer port; // 对应server.port配置 } ``` - **配置生效点**: `TomcatServletWebServerFactory`(Tomcat容器)或`NettyReactiveWebServerFactory`(Netty容器)在初始化时读取`ServerProperties`中的`port`值[^1]。 2. **管理端口(`management.server.port`)** - **源码入口**:`org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties` ```java @ConfigurationProperties(prefix = "management.server") public class ManagementServerProperties { private Integer port; // 对应management.server.port } ``` - **端口分离逻辑**: 若`management.server.port`与`server.port`不同,Spring Boot会启动**第二个Web容器实例**(通过`ManagementContextAutoConfiguration`)[^2]。 --- #### 二、多端口启动的常见源码场景 ##### 1. **隐式启用管理端口** - **触发条件**:引入`spring-boot-starter-actuator`依赖且未显式配置`management.server.port`。 - **源码验证**: 在`ManagementContextAutoConfiguration`中,若检测到`management.server.port`存在且与主端口不同,会创建独立子上下文: ```java @Bean public ManagementContextFactory managementContextFactory() { return (parent, configurationClasses) -> { AnnotationConfigServletWebServerApplicationContext child = new AnnotationConfigServletWebServerApplicationContext(); child.setParent(parent); child.register(configurationClasses); return child; }; } ``` ##### 2. **第三方组件占用端口(如Dubbo)** - **源码示例**:Dubbo的`ProtocolConfig`类会绑定默认端口`20880`: ```java public class ProtocolConfig extends AbstractConfig { private Integer port = 20880; // 对应dubbo.protocol.port配置 } ``` 若未显式配置`dubbo.protocol.port`,则使用默认值[^3]。 --- #### 三、定位端口配置的源码级方法 1. **全局搜索端口绑定关键字** 在IDE中使用正则表达式搜索以下模式: ```regex \b(port|PORT)\s*=\s*\d+ ``` 重点检查: - 自定义`WebServerFactory`实现类 - `@Value`注解直接注入端口值(如`@Value("${custom.port}")`) 2. **调试内嵌容器初始化流程** - 断点位置: - Tomcat:`TomcatServletWebServerFactory#getWebServer()` - Netty:`NettyReactiveWebServerFactory#getWebServer()` - 观察`port`参数来源,若发现非预期值,回溯调用栈找到配置源。 3. **分析条件化配置** 检查自动配置类是否因条件成立而启用额外端口: ```java @ConditionalOnClass(name = "org.apache.dubbo.config.ProtocolConfig") @AutoConfigureAfter(DubboAutoConfiguration.class) public class DubboMetadataAutoConfiguration { // 自动注册Dubbo协议端口 } ``` --- #### 四、端口修改实战步骤 1. **明确端口类型** - 主服务端口:`server.port` - 管理端口:`management.server.port` - 第三方组件端口:如`dubbo.protocol.port`、`grpc.server.port` 2. **配置文件覆盖(优先级最高)** 在`application.properties`中显式指定: ```properties # 主服务端口 server.port=8080 # 管理端口(若不需要则设置为-1) management.server.port=9090 # Dubbo协议端口 dubbo.protocol.port=20881 ``` 3. **排除冲突依赖(示例:禁用Actuator管理端口)** ```java @SpringBootApplication(exclude = { ManagementWebServerAutoConfiguration.class, DubboAutoConfiguration.class }) ``` 4. **自定义WebServerFactory(终极手段)** 若配置无效,直接硬编码端口(不推荐,仅用于测试): ```java @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> portCustomizer() { return factory -> factory.setPort(8081); } ``` --- #### 五、验证与调试 1. **查看端口绑定日志** 启动时关注以下日志: ```log Tomcat initialized with port(s): 8080 (http) Netty started on port 8080 Dubbo Server started on port 20880 ``` 2. **使用源码断点验证** 在`ServerProperties`和`ManagementServerProperties`的`setPort()`方法设置断点,观察赋值过程。 --- ### 相关问题 1. 如何通过Spring Boot源码分析自动配置的条件触发机制? 2. 如何调试内嵌Tomcat容器的端口绑定过程? 3. 在Spring Boot中,如何实现动态端口分配(如随机端口)? 4. 第三方组件(如gRPC)的端口配置如何与Spring Boot主端口共存?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ytadpole

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值