Java 关闭 Spring Boot 应用程序时无法注销数据源 JMX MBean
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24947717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Failed to Unregister DataSource JMX MBean While Shutting Down a Spring Boot Application
提问by jlai
I have a simple Spring Boot application using org.apache.commons.dbcp2.BasicDataSource as dataSource bean.
我有一个简单的 Spring Boot 应用程序,它使用 org.apache.commons.dbcp2.BasicDataSource 作为数据源 bean。
The data source is exposed as MBean automatically by Spring boot.
Spring boot 自动将数据源公开为 MBean。
The bean declaration:
bean声明:
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(dbUrl);
dataSource.setDriverClassName(jdbcDriver);
dataSource.setUsername(dbUserName);
dataSource.setPassword(dbPassword);
return dataSource;
}
Everything works fine . However, I see error while shutting down the application. This error only occurs when running the executable jar. When using Gradle Spring plugin (gradle bootRun), this is not shown.
一切正常。但是,我在关闭应用程序时看到错误。此错误仅在运行可执行 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.run(AbstractApplicationContext.java:809)
I am wondering, 1. How does this bean get exposed as JMX MBean? 2. How to properly unregister this MBean?
我想知道, 1. 这个 bean 是如何作为 JMX MBean 公开的?2. 如何正确注销这个MBean?
采纳答案by Marcon
Spring is trying to close BasicDataSource twice:
Spring 试图关闭 BasicDataSource 两次:
- BasicDataSource close itself automatically when application close
- Spring use default destroy method to close DataSource but it's already closed
- 应用程序关闭时 BasicDataSource 自动关闭
- Spring使用默认的destroy方法关闭DataSource但它已经关闭
To avoid this, use:
为避免这种情况,请使用:
@Bean(destroyMethod = "")
public DataSource dataSource()
In your Java Configuration
在您的 Java 配置中
回答by user832462
I ran into the same problem. Adding an MBean server and registering the datasource can not fix it either.
我遇到了同样的问题。添加 MBean 服务器并注册数据源也无法修复它。
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jmx.html
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jmx.html
My conclusion is that DBCP2's BasicDataSource has a bug at unregistering itself from the MBean server.
我的结论是 DBCP2 的 BasicDataSource 在从 MBean 服务器取消注册时有一个错误。
I fixed mine by switching to mchange's c3p0: http://www.mchange.com/projects/c3p0/
我通过切换到 mchange 的 c3p0 来修复我的:http: //www.mchange.com/projects/c3p0/
回答by simple
I had the same issue. c3p0 works very well.
我遇到过同样的问题。c3p0 工作得很好。
if using spring framework
- pom.xml
如果使用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>
initially used
最初使用
DataSource ds_unpooled = DataSources.unpooledDataSource(persistenceUrl,
persistenceUsername,
persistencePassword);
return DataSources.pooledDataSource(ds_unpooled);
but it couldn't handle the load I need to perform and switched to the following
但它无法处理我需要执行的负载并切换到以下内容
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;
those values are from other posts that I have gathered online.
这些值来自我在网上收集的其他帖子。
in my experience for my specific task, running c3p0 performs faster than dbcp2 v:2.1.1 under the same environment.
根据我对特定任务的经验,在相同环境下运行 c3p0 的速度比 dbcp2 v:2.1.1 快。
hope this help a bit. cheers!
希望这会有所帮助。干杯!
回答by helinxiang
BasicDataSource extends BasicDataSourceMXBean
, so it is auto registered with JMX server as MBean [org.apache.commons.dbcp2:name=dataSource,type=BasicDataSource]
. When springboot shutdowns, MBeanExporter unregisters the MBean, then springboot tries to destroy BasicDataSource
, and calls BasicDataSource's method close()
, unregisters the MBean again (BasicDataSource catches the JMException, and print this warning). It's just a warning. If you don't want to print it, you can disable JMX in springboot.
BasicDataSource extends BasicDataSourceMXBean
,所以它自动在 JMX 服务器上注册为 MBean [org.apache.commons.dbcp2:name=dataSource,type=BasicDataSource]
。当 springboot 关闭时,MBeanExporter 注销 MBean,然后 springboot 尝试销毁BasicDataSource
,并调用 BasicDataSource 的方法close()
,再次注销 MBean(BasicDataSource 捕获 JMException,并打印此警告)。这只是一个警告。如果不想打印,可以在springboot中禁用JMX。
application.yml
spring:
jmx:
enabled: false