Open HozonLee opened 3 months ago
目前是把数据源对象直接用成了springboot的属性配置对象,后面再看下怎么优化改造吧
复现方式:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<scope>test</scope>
</dependency>
package com.alibaba.druid.spring.boot3.testcase;
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceWrapper; import com.alibaba.druid.spring.boot3.demo.DemoApplication; import jakarta.annotation.Resource; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext;
/**
ConfigurationProperties 触发 rebind 导致连接泄露 */ @SpringBootTest(classes = DemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"management.endpoints.web.exposure.include=health"}) public class Issue6004TestCase {
private static final Logger logger = LoggerFactory.getLogger(Issue6004TestCase.class);
@Resource private DruidDataSourceWrapper dataSource;
@Resource private ApplicationContext applicationContext;
@Test public void test() { String beanName = applicationContext.getBean(DruidDataSourceWrapper.class).getName(); Assertions.assertDoesNotThrow(() -> { logger.info("Max active: {}", dataSource.getMaxActive()); for (int i = 0; i <= dataSource.getMaxActive() + 1; i++) { logger.info("Current created: {}, active: {}, idle: {}", dataSource.getCreateCount(), dataSource.getActiveCount(), dataSource.getPoolingCount()); // 不引入 spring-cloud 依赖,模拟 org.springframework.cloud.endpoint.event.RefreshEventListener#handle(org.springframework.cloud.endpoint.event.RefreshEvent) applicationContext.getAutowireCapableBeanFactory().destroyBean(dataSource); applicationContext.getAutowireCapableBeanFactory().initializeBean(dataSource, beanName); } }); }
}
暂时通过重写 `getConnection()` 规避:
```java
@Override
public DruidPooledConnection getConnection() throws SQLException {
boolean rebinding = Arrays.stream(Thread.currentThread().getStackTrace())
.map(StackTraceElement::getClassName)
.anyMatch(x -> StringUtils.equals("org.springframework.boot.context.properties.ConfigurationPropertiesBinder", x));
if (rebinding) {
return null;
}
return getConnection(maxWait);
}
Database Type
Mysql
Database Version
5.7
Druid Version
1.2.22
JDK Version
Openjdk17
Error SQL
any
Testcase Code
在nacos中配置Druid的一些基本信息,使用自动装配,连续随意在nacos配置文件中修改配置(8次)左右,这时候发起请求数据库的API调用,请求一直卡住不动,jdk8下不会触发,查看源码刷新配置后会触发get打头等方法调用,(包含getConnection方式),获取连接后,未释放连接,导致默认初始化的最大连接数被用完导致以上问题
Stacktrace Info
No response
Error Info
No response