Не удалось отменить регистрацию источника данных JMX MBean при завершении работы приложения Spring Boot
У меня есть простое приложение Spring Boot, использующее org.apache.commons.dbcp2.BasicDataSource в качестве bean-компонента dataSource.
Источник данных автоматически открывается как MBean при загрузке Spring.
Объявление бина:
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(dbUrl);
dataSource.setDriverClassName(jdbcDriver);
dataSource.setUsername(dbUserName);
dataSource.setPassword(dbPassword);
return dataSource;
}
Все отлично работает Тем не менее, я вижу ошибку при закрытии приложения. Эта ошибка возникает только при запуске исполняемого файла jar. При использовании плагина Gradle Spring (gradle bootRun) это не отображается.
javax.management.InstanceNotFoundException: org.apache.commons.dbcp2:name=dataSource,type=BasicDataSource
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1095)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.exclusiveUnregisterMBean(DefaultMBeanServerInterceptor.java:427)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.unregisterMBean(DefaultMBeanServerInterceptor.java:415)
at com.sun.jmx.mbeanserver.JmxMBeanServer.unregisterMBean(JmxMBeanServer.java:546)
at org.apache.commons.dbcp2.BasicDataSource.close(BasicDataSource.java:1822)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.beans.factory.support.DisposableBeanAdapter.invokeCustomDestroyMethod(DisposableBeanAdapter.java:350)
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:273)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:540)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:516)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:827)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:485)
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:921)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:895)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.doClose(EmbeddedWebApplicationContext.java:152)
at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:809)
Мне интересно, 1. Как этот компонент отображается как JMX MBean? 2. Как правильно отменить регистрацию этого MBean?
4 ответа
Spring пытается закрыть BasicDataSource дважды:
- BasicDataSource автоматически закрывается при закрытии приложения
- Spring использует метод уничтожения по умолчанию, чтобы закрыть DataSource, но он уже закрыт
Чтобы избежать этого, используйте:
@Bean(destroyMethod = "")
public DataSource dataSource()
В вашей конфигурации Java
BasicDataSource extends BasicDataSourceMXBean
, поэтому он автоматически регистрируется на сервере JMX как MBean [org.apache.commons.dbcp2:name=dataSource,type=BasicDataSource]
, Когда Springboot завершает работу, MBeanExporter отменяет регистрацию MBean, затем Springboot пытается уничтожить BasicDataSource
и вызывает метод BasicDataSource close()
снова регистрирует MBean (BasicDataSource перехватывает исключение JMException и выводит это предупреждение). Это просто предупреждение. Если вы не хотите его печатать, вы можете отключить JMX в Springboot.
application.yml
spring:
jmx:
enabled: false
Я столкнулся с той же проблемой. Добавление сервера MBean и регистрация источника данных также не может исправить это.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jmx.html
Мой вывод заключается в том, что BasicDataSource DBCP2 имеет ошибку при отмене регистрации на сервере MBean.
Я исправил мой, перейдя на c3p0 Mchange: http://www.mchange.com/projects/c3p0/
Я была такая же проблема. c3p0 работает очень хорошо.
при использовании spring framework
- pom.xml
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
изначально использовался
DataSource ds_unpooled = DataSources.unpooledDataSource(persistenceUrl,
persistenceUsername,
persistencePassword);
return DataSources.pooledDataSource(ds_unpooled);
но он не мог справиться с нагрузкой, которую мне нужно выполнить, и переключился на следующее
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( persistenceDriver ); //loads the jdbc driver
cpds.setJdbcUrl( persistenceUrl );
cpds.setUser(persistenceUsername);
cpds.setPassword(persistencePassword);
cpds.setMinPoolSize(5);
cpds.setMaxPoolSize(50);
cpds.setUnreturnedConnectionTimeout(1800);
cpds.setMaxStatements(50);
cpds.setMaxIdleTime(21600);
cpds.setIdleConnectionTestPeriod(10800);
return cpds;
эти значения взяты из других постов, которые я собрал в сети.
по моему опыту для моей конкретной задачи, запуск c3p0 выполняется быстрее, чем dbcp2 v:2.1.1 в той же среде.
надеюсь, это поможет немного. ура!