[英]Java connection pool is not limiting the number of TCP connections opened to the DB server
我正在使用Hibernate屬性來定義連接池大小,以及LocalSessionFactoryBean
和DriverManagerDataSource
來創建一個org.hibernate.SessionFactory
,我正在觀察1000個TCP連接被打開到DB服務器,而不是上限100我會預計連接池大小。
設置連接Hibernate池的代碼如下所示。 注意最大大小為100,但是我正在觀察從我的工作站到數據庫服務器的1000個連接 - 我在Windows機器上使用TCPView連接到由Vagrant管理的Centos OS VM上的MariabDB實例(VirtualBox)
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
hibernateProperties.put("hibernate.show_sql", false);
hibernateProperties.put("hibernate.generate_statistics", false);
hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
hibernateProperties.put("hibernate.use_sql_comments", false);
hibernateProperties.put("hibernate.c3p0.min_size", 10);
hibernateProperties.put("hibernate.c3p0.max_size", 100);
hibernateProperties.put("hibernate.c3p0.timeout", 1500);
hibernateProperties.put("hibernate.c3p0.max_statements", 5000);
hibernateProperties.put("hibernate.c3p0.idle_test_period", 60);
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource);
localSessionFactoryBean.setHibernateProperties(hibernateProperties);
localSessionFactoryBean.setMappingResources("job.persistence.xml");
我希望看到這些連接最大值為100並重新用於以后執行的循環,但我觀察超過1000坐在TIME_WAIT中大約一分鍾才關閉它們。 以下是TCPView輸出的示例:
[System Process] 0 TCP localhost 62794 192.168.98.102 3306 TIME_WAIT
[System Process] 0 TCP localhost 62796 192.168.98.102 3306 TIME_WAIT
[System Process] 0 TCP localhost 62797 192.168.98.102 3306 TIME_WAIT
[System Process] 0 TCP localhost 62795 192.168.98.102 3306 TIME_WAIT
[System Process] 0 TCP localhost 62798 192.168.98.102 3306 TIME_WAIT
[System Process] 0 TCP localhost 62801 192.168.98.102 3306 TIME_WAIT
我顯然做錯了什么但不確定是什么。 我使用Spring來管理提供數據訪問邏輯的DAO。 DAO注冊為原型Spring作用域,而Singleton SessionFactory
注入DAO,如下所示:
@Bean(name="jobDao")
@Scope(SpringBeanScope.Prototype)
public JobDao jobDao(SessionFactory jobSessionFactory) { //...}
在DAO中,我調用sessionFactory.getCurrentSession()
來訪問數據庫會話。 以下是通用DAO基礎的摘錄,演示了這一點:
protected Session currentSession() {
return sessionFactory.getCurrentSession();
}
@Transactional
@Override
public void Add(TEntity entity) {
currentSession().save(entity);
}
有沒有人知道為什么在連接池限制為100時打開這么多TCP連接?
UPDATE
由於此問題出現在Windows開發計算機上,因此我將一個小型.NET控制台應用程序放在一起,該應用程序使用並行for循環執行一個簡單的SQL select語句,最大線程數為64,每次都創建一個新連接:
public void Test()
{
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 64;
Parallel.For(0,
1000,
options,
(i, state) =>
{
ExecuteSql();
});
}
private void ExecuteSql()
{
SqlDataAdapter adapter = new SqlDataAdapter(sql, new SqlConnection(connectionString));
DataSet orders = new DataSet();
adapter.Fill(orders, "Order");
Console.WriteLine("Thread {0} returned {1} rows", Thread.CurrentThread.ManagedThreadId, orders.Tables[0].Rows.Count);
}
TCPView結果如下所示,這是我期望在連接池解決方案中看到的,即TCP連接被重用
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61316 dev-database01 ms-sql-s ESTABLISHED 1 88 776 2,684,495 43,800 16
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61317 dev-database01 ms-sql-s ESTABLISHED 1 88 507 1,998,709 6,326 1
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61318 dev-database01 ms-sql-s ESTABLISHED 2 176 862 3,081,722 49,640 19
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61319 dev-database01 ms-sql-s ESTABLISHED 2 176 952 3,128,657 14,600 9
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61320 dev-database01 ms-sql-s ESTABLISHED 2 176 1,149 3,569,440 25,747 8
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61321 dev-database01 ms-sql-s ESTABLISHED 2 176 1,166 3,788,974
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61322 dev-database01 ms-sql-s ESTABLISHED 2 176 884 3,197,392 8,713 2
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61323 dev-database01 ms-sql-s ESTABLISHED 2 176 535 1,816,150
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61324 dev-database01 ms-sql-s ESTABLISHED 2 176 631 2,197,973
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61327 dev-database01 ms-sql-s ESTABLISHED 2 176 1,037 3,344,226 18,980 5
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61328 dev-database01 ms-sql-s ESTABLISHED 3 264 1,271 4,057,097 30,660 13
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61331 dev-database01 ms-sql-s ESTABLISHED 2 176 780 2,639,988 8,760 2
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61333 dev-database01 ms-sql-s ESTABLISHED 2 176 1,041 3,352,777 31,248 12
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61334 dev-database01 ms-sql-s ESTABLISHED 6 995 729 2,387,668
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61335 dev-database01 ms-sql-s ESTABLISHED 6 995 601 1,917,537 23,937 6
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61336 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61339 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61340 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61342 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61343 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61344 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61345 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61346 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61356 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61357 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61358 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61359 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61362 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61363 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61364 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61365 dev-database01 ms-sql-s ESTABLISHED
DatabaseTcpPortTester.vshost.exe 5036 TCP localhost 61369 dev-database01 ms-sql-s ESTABLISHED
[System Process] 0 TCP localhost 61395 dev-database01 epmap TIME_WAIT
在netstat輸出中,它們都處於TIME_WAIT
狀態,指示實際關閉之前TCP套接字的狀態。 這並不意味着數據庫連接處於活動狀態,只是TCP正處於套接字關閉的過程中。
有多少人處於ESTABLISHED
狀態? 這將告訴您在該時間點打開的數據庫連接的確切數量。
您可以參考以下鏈接了解不同的TCP套接字狀態。 https://en.wikipedia.org/wiki/Transmission_Control_Protocol
Hibernate配置是正確的,你應該使用C3P0。 如果要為每個請求創建SessionFactory
,則只能看到比最大池大小更多的連接。
從你的配置中,我看到DAO被創建為原型,這是不尋常的,因為它們應該是單身。 確保LocalSessionFactoryBean
也不使用原型范圍。
問題是當使用DriverManagerDataSource
並且通過在LocalSessionFactoryBean
上設置c3p0屬性讓hibernate管理池時,c3p0從未被初始化
所以我切換到ComboPooledDataSource
並使用此處提供的setter方法設置c3p0屬性,而不是在LocalSessionFactoryBean
上設置c3p0屬性,因此您最終會得到以下結果:
@Bean(name="dataSource")
public DataSource dataSource() throws PropertyVetoException {
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
hibernateProperties.put("hibernate.show_sql", false);
hibernateProperties.put("hibernate.generate_statistics", false);
hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
hibernateProperties.put("hibernate.use_sql_comments", false);
//note the "hibernate.c3p0...." properties are no longer in use
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(jobDatabaseProperties.getJobDatabaseDriverClassName());
dataSource.setJdbcUrl(jobDatabaseProperties.getJobDatabaseUrl());
dataSource.setUser(jobDatabaseProperties.getJobDatabaseUsername());
dataSource.setPassword(jobDatabaseProperties.getJobDatabasePassword());
dataSource.setAcquireIncrement(1);
dataSource.setMinPoolSize(5);
dataSource.setMaxPoolSize(100);
dataSource.setMaxIdleTime(20);
return new dataSource;
}
我現在可以看到c3p0在日志中被初始化,並且池中的連接數按預期被控制。
請參閱 http://syntx.io/configuring-c3p0-connection-pooling-with-spring-and-hibernate/上的“ 有彈簧管理池 ”部分
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.