简体   繁体   English

为什么我的Tomcat只打开8个JDBC连接

[英]Why does my Tomcat only open 8 JDBC connections

When setting up the database connections in Tomcat 8, for some reason Tomcat is not following what I configured in the context.xml, with as result that I run out of connections, leading to resource contentions at the application server side (BLOCKED/WAITING threads). 在Tomcat 8中设置数据库连接时,由于某种原因,Tomcat没有遵循我在context.xml中配置的内容,导致我的连接用尽,导致应用程序服务器端的资源争用(BLOCKED / WAITING线程) )。 I always have 8 connections (show processlist in mariadb/mysql) after the pool initializes. 池初始化后,我总是有8个连接(在mariadb / mysql中显示进程列表)。 My configuration states a minimum of 10 connections and a maximum of 100 connections. 我的配置规定至少10个连接和最多100个连接。

I tested different configurations, but this does not make any difference at all, which is strange at least. 我测试了不同的配置,但这根本没有任何区别,这至少是奇怪的。 The context.xml is used else it would not be able to connect to the database at all. 使用context.xml,否则根本无法连接到数据库。

What is happening here? 这里发生了什么? Why only 8 connections? 为什么只有8个连接?

Software versions: - MySQL JDBC driver: Latest (5.1.35) - Java 1.8.0_05 软件版本: - MySQL JDBC驱动程序:最新版本(5.1.35) - Java 1.8.0_05

I also observed with with my previous setup: Tomcat 7, Java 1.7, older MySQL JDBC drivers, MySQL instead of MariaDB. 我还观察过我以前的设置:Tomcat 7,Java 1.7,较旧的MySQL JDBC驱动程序,MySQL而不是MariaDB。 So the problem does not seem directly version related. 所以这个问题似乎并不直接与版本相关。

Show processlist output (Showing the 8 processes): 显示进程列表输出(显示8个进程):

| Id    | User          | Host          | db                | Command | Time | State     | Info            | Progress |                                                                     
+-------+---------------+---------------+-------------------+---------+------+-----------+-----------------+----------+
| 71153 | root          | localhost     | vnitdatacollector | Query   |    0 | init      | show processlist|    0.000 |                                                                     
| 73473 | vnit_datacoll | virt005:58585 | vnitdatacollector | Sleep   |    0 |           | NULL            |    0.000 |                                                                     
| 73474 | vnit_datacoll | virt005:58586 | vnitdatacollector | Sleep   |    0 |           | NULL            |    0.000 |                                                                     
| 73482 | vnit_datacoll | virt005:58606 | vnitdatacollector | Query   |    0 | update    | INSERT INTO ... |    0.000 |
| 73483 | vnit_datacoll | virt005:58607 | vnitdatacollector | Sleep   |    0 |           | NULL            |    0.000 |                                                                     
| 73485 | vnit_datacoll | virt005:58618 | vnitdatacollector | Query   |    0 | query end | INSERT INTO ... |    0.000 |
| 73487 | vnit_datacoll | virt005:58624 | vnitdatacollector | Sleep   |    0 |           | NULL            |    0.000 |                                                                     
| 73488 | vnit_datacoll | virt005:58634 | vnitdatacollector | Sleep   |    0 |           | NULL            |    0.000 |                                                                     
| 73489 | vnit_datacoll | virt005:58637 | vnitdatacollector | Query   |    7 | update    | INSERT INTO ... |    0.000 |
+-------+---------------+---------------+-------------------+---------+------+-----------+-----------------+----------+

I have the following context.xml configuration: 我有以下context.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
  <Resource 
    name="jdbc/dbaccess" 
    auth="Container" 
    type="javax.sql.DataSource"
    maxActive="100" 
    maxIdle="100"
    minIdle="10"
    maxWait="1000"
    initialSize="10"
    minEvictableIdleTimeMillis="5000"
    testOnBorrow="true"
    validationQuery="SELECT 1" 
    timeBetweenEvictionRunsMillis="5000" 
    testWhileIdle="true"
    removeAbandoned="true" 
    removeAbandonedTimeout="60" 
    logAbandoned="true"
    username="some_user" 
    password="{the password}" 
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://dbserver:3306/dbaccess?useFastDateParsing=false&amp;jdbcCompliantTruncation=false"
  />
  <Resource
    name="mail/emailconnection"
    auth="Container"
    type="javax.mail.Session"
    mail.smtp.host="some.stmp.server"
  />             
</Context>

The following thread issue then shows up after a (short) period: 然后在(短)时段后显示以下线程问题:

"Thread-495" #517 daemon prio=5 os_prio=0 tid=0x00007f678c040800 nid=0x1642 waiting on condition [0x00007f67848f4000]
java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000000f21933f0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at org.apache.tomcat.dbcp.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:582)
    at org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:439)
    at org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:360)
    at org.apache.tomcat.dbcp.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:118)
    at org.apache.tomcat.dbcp.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1412)
    at com.hipersonik.util.ServiceLocator.getConnection(ServiceLocator.java:32)

Quote from " Tomcat Expert: Configuring jdbc-pool for high-concurrency ": 引自“ Tomcat专家:为高并发配置jdbc-pool ”:

When Tomcat reads the type="javax.sql.DataSource" it will automatically configure its repackaged DBCP, unless you specify a different factory. 当Tomcat读取type="javax.sql.DataSource" ,它将自动配置其重新打包的DBCP,除非您指定其他工厂。 The factory object is what creates and configures the connection pool itself. 工厂对象是创建和配置连接池本身的对象。

It turns out that DBCP package just ignores a series of settings. 事实证明,DBCP包只是忽略了一系列设置。 Adding the following line to the context.xml resource configuration, gets better response in the database: 将以下行添加到context.xml资源配置中,可以在数据库中获得更好的响应:

<Resource 
 ....
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
 ....
/>

Show processlist in mysql then immediately shows the desired behaviour. 在mysql中显示进程列表然后立即显示所需的行为。

By default (ie if not setting the factory setting of your ressource), tomcat7 uses commons dbcp1. 默认情况下(即,如果未设置资源的出厂设置),tomcat7使用commons dbcp1。

Tomcat also provides an alternate pool implementation (the tomcat jdbc connection pool) that you can use by setting factory=org.apache.tomcat.jdbc.pool.DataSourceFactory on your ressource Tomcat还提供了一个备用池实现(tomcat jdbc连接池),您可以通过在您的资源上设置factory = org.apache.tomcat.jdbc.pool.DataSourceFactory来使用它

Tomcat8 uses commons dbcp2 by default, which has different names for some very important configuration parameters ( see https://tomcat.apache.org/migration-8.html#Database_Connection_Pooling ) as dbcp1 (and the tomcat jdbc connection pool, because it mostly has the same configuration options as commons dbcp1). Tomcat8默认使用commons dbcp2,它对于一些非常重要的配置参数(请参阅https://tomcat.apache.org/migration-8.html#Database_Connection_Pooling )具有不同的名称作为dbcp1(和tomcat jdbc连接池,因为它主要是具有与commons dbcp1相同的配置选项。

So basically, before tomcat8, you didn't have to pay attention to which connection pool you were using because of the configuration compatibilty. 所以基本上,在tomcat8之前,由于配置兼容性,您不必关注正在使用的连接池。 With tomcat8, you have to pay attention. 有了tomcat8,你必须要注意。

Tomcat connection pool documentation: https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html Tomcat连接池文档: https//tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html

Default commons dbcp2 documentation: https://tomcat.apache.org/tomcat-8.0-doc/jndi-resources-howto.html#JDBC_Data_Sources 默认commons dbcp2文档: https ://tomcat.apache.org/tomcat-8.0-doc/jndi-resources-howto.html#JDBC_Data_Sources

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM