2012-07-17 140 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