我为我的角度项目开发了一个弹簧引导RestController并遇到问题。在我的剩余服务逻辑中,我使用了两个不同的数据库来获取数据。带有多个数据源Oracle和H2的弹簧引导
在这里你可以看到数据源配置:
[application.properties]
#datasource1
spring.datasource.url=[url]
spring.datasource.username=[username]
spring.datasource.password=[password]
spring.datasource.driverClassName=org.h2.Driver
#datasource2
spring.secondDatasource.url=[url]
spring.secondDatasource.username=[username]
spring.secondDatasource.password=[password]
spring.secondDatasource.driverClassName=oracle.jdbc.OracleDriver
[DatasourceConfig.java]
@Bean
@Primary
@ConfigurationProperties(prefix="spring.datasource")
public DataSource h2DataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix="spring.secondDatasource")
public DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
记录输出:(无例外被丢进对于这个问题)
...
2016-11-22 13:20:25.853 [INFO ] 1 [main] d.b.s.Application : Started Application in 7.757 seconds (JVM running for 12.515)
2016-11-22 13:20:31.731 [INFO ] 62 [http-nio-8080-exec-1] o.s.w.s.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2016-11-22 13:20:31.757 [INFO ] 62 [http-nio-8080-exec-1] o.s.w.s.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 26 ms
2016-11-22 13:20:34.984 [INFO ] 65 [http-nio-8080-exec-5] d.b.s.r.RESTclient : /rest/getMyData
2016-11-22 13:20:34.992 [INFO ] 63 [http-nio-8080-exec-2] d.b.s.r.RESTclient : /rest/getMyData2
2016-11-22 13:20:34.993 [INFO ] 69 [http-nio-8080-exec-8] d.b.s.r.RESTclient : /rest/getMyData3
2016-11-22 13:20:35.004 [DEBUG] 65 [http-nio-8080-exec-5] d.b.s.DataSourceService : getH2Connection()
2016-11-22 13:20:35.022 [DEBUG] 63 [http-nio-8080-exec-2] d.b.s.DataSourceService : getOracleConnection()
2016-11-22 13:20:35.022 [DEBUG] 69 [http-nio-8080-exec-8] d.b.s.DataSourceService : getH2Connection()
问题是,其余服务的每个使用的工作线程(http-nio-8080-?,...)在我的DataSourceService中的datasource.getConnection()挂起。它永远冻结,并等待无法获得的连接。
@Service
public class DataSourceService {
private final DataSource h2DataSource;
private final DataSource oracleDataSource;
@Autowired
public DataSourceService(DataSource h2DataSource, DataSource oracleDataSource) {
this.h2DataSource = h2DataSource;
this.oracleDataSource = oracleDataSource;
}
public Connection getH2Connection() throws SQLException {
LoggerUtil.logDebug(getClass(), "getH2Connection()");
return h2Connection.getConnection();
}
public Connection getOracleConnection() throws SQLException {
LoggerUtil.logDebug(getClass(), "getOracleConnection()");
return oracleConnection.getConnection();
}
}
关于它的奇怪的是,有时它的工作原理没有改变过的代码行(所有时间的5%)和大部分(所有时间的95%),其挂断。
在我的pom.xml我有以下数据库驱动的依赖:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.193</version>
<scope>runtime</scope>
</dependency>
如果所有的数据源具有相同的驱动程序,这不会发生,但结合我发现这种奇怪的行为。
我的想法是,这只有当h2Database在oracle之前被初始化时才会发生。在这一点上,spring classloader加载了h2-driver类,它们将被缓存。接下来,oracle将被初始化,并且一些类将关闭完全相同,以便某些h2类被用于oracle。正因为如此,冻结的奇怪状态被创建。 (也许反之亦然)。
我现在的问题是:为什么我不能在Spring-boot的同时使用H2和Oracle数据库?
编辑:
后一些调试我发现更详细的信息:
[org.apache.tomcat.jdbc.pool.ClassLoaderUtil]
Row 29: loadClass(...)
...
Row 38: return Class.forName(className, true, cl); //className: "oracle.jdbc.OracleDriver" cl: Launcher$AppClassLoader
在ClassLoaderUtil为查找通过className的驱动程序类。可以毫无问题地解决className“org.h2.Driver”,但“oracle.jdbc.OracleDriver”不会。
之后,我做了一个线程转储,你可以看到卡住的点。此时有5个卡住的线程在不同的位置卡住。
HTTP-NIO-8080-EXEC-2 @ 8307(可运行) (仅使用Oracle数据库)
"[email protected]" daemon prio=5 tid=0x40 nid=NA runnable
java.lang.Thread.State: RUNNABLE
blocks [email protected]
at java.lang.Class.forName0(Class.java:-1)
at java.lang.Class.forName(Class.java:348)
at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38)
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:271)
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203)
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:718)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:650)
at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:468)
at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:143)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118)
- locked <0x2139> (a org.apache.tomcat.jdbc.pool.DataSource)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131)
at d.b.s.DataSourceService.getConnection(DataSourceService.java:51) //<-- That's my package
...
HTTP-NIO-8080-EXEC-3 @ 8308(可运行) (比较Oracle和H2数据)
"[email protected]" daemon prio=5 tid=0x41 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at oracle.jdbc.driver.OracleDriver.<clinit>(OracleDriver.java:190)
at java.lang.Class.forName0(Class.java:-1)
at java.lang.Class.forName(Class.java:348)
at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38)
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:271)
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203)
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:718)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:650)
at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:468)
at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:143)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118)
- locked <0x213d> (a org.apache.tomcat.jdbc.pool.DataSource)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131)
at d.b.s.DataSourceService.getConnection(DataSourceService.java:51)
...
HTTP-NIO-8080-EXEC-4 @ 8309(可运行) (Oracle和H2数据之间的比较)
(间相同的exec-2)
HTTP-NIO-8080-EXEC-5 @ 8310(可运行) (仅使用H2数据库)
"[email protected]" daemon prio=5 tid=0x43 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at sun.reflect.GeneratedConstructorAccessor109.newInstance(Unknown Source:-1)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:-1)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
at java.sql.DriverManager$2.run(DriverManager.java:603)
at java.sql.DriverManager$2.run(DriverManager.java:583)
at java.security.AccessController.doPrivileged(AccessController.java:-1)
at java.sql.DriverManager.loadInitialDrivers(DriverManager.java:583)
at java.sql.DriverManager.<clinit>(DriverManager.java:101)
at org.h2.Driver.load(Driver.java:155)
at org.h2.Driver.<clinit>(Driver.java:41)
at java.lang.Class.forName0(Class.java:-1)
- locked <0x211b> (a java.lang.Class)
at java.lang.Class.forName(Class.java:348)
at org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:38)
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:271)
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203)
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:718)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:650)
at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:468)
at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:143)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131)
- locked <0x20e9> (a org.apache.tomcat.jdbc.pool.DataSource)
at d.b.s.DataSourceService.getConnection(DataSourceService.java:51)
...
HTTP-NIO-8080-EXEC-6 @ 8311 (等待监视实体) (Oracle和H2数据之间的比较)
"[email protected]" daemon prio=5 tid=0x44 nid=NA waiting for monitor entry
java.lang.Thread.State: BLOCKED
waiting for [email protected] to release lock on <0x2139> (a org.apache.tomcat.jdbc.pool.DataSource)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:115)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131)
at d.b.s.DataSourceService.getConnection(DataSourceService.java:51)
...
对我来说似乎不合法,我认为它与Spring Boot无关。既然你正在配置你自己的'DataSource',你完全可以绕过Spring Boot为你做的事情。也许池没有足够的连接,你没有正确关闭连接?再次,与Spring Boot无关。 –