2012-07-17 72 views
0

我想分享一個奇怪的例子。在生產我們的應用程序拋出OOM異常,我們採取了堆轉儲,並開始分析,後來我們發現與com.mchange.v2.c3p0.stmt.PerConnectionMaxOnlyStatementCache實例的問題。該對象的大小約爲堆大小的50%。該應用程序正在運行數十億用戶和服務器一次又一次地下降。c3p0緩存對象的性能問題:

此應用程序在tomcat上運行,其中tomcat連接器允許最多300個併發請求,以下是c3p0配置。

jdbc.hibernate.c3p0.minPoolSize=2 
jdbc.hibernate.c3p0.maxPoolSize=150 
jdbc.hibernate.c3p0.maxIdleTime=0 
jdbc.hibernate.c3p0.maxStatementsPerConnection=50 
jdbc.hibernate.c3p0.numHelperThreads=6 

從堆監視工具我們得到以下信息:「com.mchange.v2.c3p0.stmt.PerConnectionMaxOnlyStatementCache」的

一個實例通過「org.apache.catalina.loader.WebappClassLoader @裝0x82f1c58「佔用72 970 824(57,75%)字節。存儲累積在「com.mchange.v2.c3p0.stmt.PerConnectionMaxOnlyStatementCache」的一個實例被加載「org.apache.catalina.loader.WebappClassLoader @ 0x82f1c58」

請請告知: - 可以採取什麼原因這個實例佔用如此巨大的內存? 我們是否正確運行正確的c3p0配置? 重載應用程序的推薦配置是什麼?

在此先感謝

+1

你說你正在使用Tomcat。爲什麼你使用自己的C3P0而不是Tomcat的連接池? – jpkrohling 2012-07-17 08:34:09

+0

嘗試設置這些參數 2012-07-17 08:39:22

回答

-1

嘗試BoneCP了高性能的連接池,解決了C3P0和Apache DBCP的許多性能導向的問題。

+0

感謝您的回覆!但不幸的是,我們無法改變應用程序使用BoneCP,應用程序在太多的客戶端上運行。 我們需要找到解決辦法。 Tomcat的設置是如下 maxHttpHeaderSize = 「8192」 maxThreads = 「500」 minSpareThreads = 「50」 maxSpareThreads = 「1000」 enableLookups = 「假」 redirectPort = 「8443」 acceptCount = 「150」 connectionTimeout =「20000」 disableUploadTimeout =「true」 – user1451493 2012-07-17 09:14:15

2

您已設置maxStatementsPerConnection = 50和maxPoolSize = 150。這意味着語句高速緩存在任何時候都可能有多達7500個開放語句,包括驅動程序與語句相關的任何資源的內存佔用量。你基本上要求c3p0使用大量的內存,理論上說內存的成本相對於準備語句的性能成本是低的。

首先,這可能根本不是真的,在這種情況下,語句緩存通常是輸家,您不應該使用它。您應該將您的應用程序與maxStatements和maxStatementsPerConnection設置爲零的基準進行比較,以測試您是否實際從Statement緩存中獲益,如果尚未。對於在PreparedStatement對象中緩存大量解析和準備的驅動程序,語句緩存可以是一個很大的幫助。但是您需要在緩存的內存佔用空間與預緩存語句的性能優勢之間進行權衡。很明顯,即使語句高速緩存對您的性能有所幫助,您已經超過了好處超過成本的地步。

您的應用程序中150條準備好的語句中有多少經常使用?你能否把這個數字縮小一點,最好小得多,希望更少使用的語句能夠從緩存中退出並且很好地解決掉它們?或者,您可以單獨保留該號碼,但將maxStatementsPerConnection與全局maxStatements設置(設置爲小於您當前使用的隱式7500的設置)相結合。如果將maxStatementsPerConnection和maxStatements組合在一起,每個連接將被允許在池很小時達到maxStatementsPerConnection,但是當池變大並且內存佔用變成危險時,全局語句限制將導致較近期使用的語句啓動退出緩存以保留內存。

我希望這有助於!

+0

嗨Steve,謝謝 – user1451493 2012-07-18 08:03:55

0

這是因爲你給了maxIdleTime = 0

將maxIdleTime設置爲非零值允許C3P0從池中移除連接並釋放數據庫資源。

時maxIdleTime設置爲0

這永遠不會發生。

所以我相信你的連接都不會從池中移出。 這就是爲什麼它一直在堆大小。

更多參考click here