web-dev-qa-db-ja.com

Spring Bootアプリケーションのシャットダウン中にDataSource JMX MBeanの登録を解除できませんでした

DataSource Beanとしてorg.Apache.commons.dbcp2.BasicDataSourceを使用する簡単なSpring Bootアプリケーションがあります。

データソースは、Springブートによって自動的にMBeanとして公開されます。

Bean宣言:

@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.このBeanはどのようにJMX MBeanとして公開されますか? 2.このMBeanを適切に登録解除するにはどうすればよいですか?

19
jlai

SpringはBasicDataSourceを2回閉じようとしています:

  1. BasicDataSourceは、アプリケーションが閉じるときに自動的に閉じます
  2. Springはデフォルトのdestroyメソッドを使用してDataSourceを閉じますが、すでに閉じています

これを回避するには、以下を使用します。

@Bean(destroyMethod = "")
public DataSource dataSource() 

あなたのJava設定で

25
Marcon

_BasicDataSource extends BasicDataSourceMXBean_、つまり、MBean _[org.Apache.commons.dbcp2:name=dataSource,type=BasicDataSource]_としてJMXサーバーに自動登録されます。 springbootがシャットダウンすると、MBeanExporterはMBeanの登録を解除し、次にBasicDataSourceを破棄してBasicDataSourceのメソッドclose()を呼び出し、MBeanの登録を解除します(BasicDataSourceはJMExceptionをキャッチして、この警告を出力します)。これは単なる警告です。印刷したくない場合は、springbootでJMXを無効にすることができます。

_application.yml
spring:
jmx:
enabled: false
_
1
helinxiang

私も同じ問題に遭遇しました。 MBeanサーバーを追加してデータソースを登録しても修正できません。

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jmx.html

私の結論は、DBCP2のBasicDataSourceには、MBeanサーバーからの登録を解除する際のバグがあるということです。

私はmchangeのc3p0に切り替えることで私の問題を修正しました: http://www.mchange.com/projects/c3p0/

1
user832462

同じ問題がありました。 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よりも高速に実行されます。

これが少し役に立てば幸いです。乾杯!

0
simple