我有一个Java(tomcat)应用程序,它使用MySQL(使用hibernate)作为数据库。
这是一个简单的Java Jsf应用程序,只有三个用户同时使用这个系统(有两种大表,有20k行,通常在冻结时存在)。
系统一直在运行,我需要重新启动Tomcat和MySQL才能再次工作。
在日志中我有:
[WARN] 2017-11-08 16:53:02,438 com.zaxxer.hikari.pool.PoolBase isConnectionAlive - HikariPool-1 - Failed to validate connection com.mysql.jdbc.JDBC4Connection@33dc5260
也:
[WARN] 2017-11-08 17:04:32,200 com.zaxxer.hikari.pool.HikariPool run - HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=1m22s40ms97µs73ns).
和(90倍):
[WARN] 2017-11-08 17:04:35,438 com.zaxxer.hikari.pool.PoolBase isConnectionAlive - HikariPool-1 - Failed to validate connection com.mysql.jdbc.JDBC4Connection@2c365a2e (No operations allowed after connection closed.)
也:
java.lang.OutOfMemoryError: GC overhead limit exceeded
后来我得到了:
java.lang.OutOfMemoryError: Java heap space
但是系统只使用了760Mb。(是的,有很多错误,这就是为什么我很难找到解决方法!)
有什么建议吗?
我在setenv.sh设置了:
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx512m"
export CATALINA_OPTS="$CATALINA_OPTS -server"
当我验证正在使用的内存时,显示:
mysqld = 165.3 MiB
java = 662.0 MiB
我使用Hikari连接池如下:
<property name="hibernate.hikari.maximumPoolSize" value="200" />
<property name="hibernate.hikari.idleTimeout" value="30000" />
<property name="hibernate.hikari.maxLifetime" value="600000" />
<property name="hibernate.hikari.dataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" />
<property name="hibernate.connection.provider_class" value="org.hibernate.hikaricp.internal.HikariCPConnectionProvider" />
MySQL max connections设置为152。
MySQL my.cnf设置:
wait_timeout = 360
interactive_timeout = 420
服务器运行在一个带有1Gb Ram和1个vCPU的DigitalOcean液滴中。这台服务器最好的tomcat+mysql+hiraki配置是什么?
谢谢您!
[编辑]
我删除了XMS512M和XMX512M PARAMS,并将MaimuMoPoLeSIZE降至20,在运行OK服务器数小时后,我得到:
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - HikariPool-1 - Connection is not available, request timed out after 30004ms.
javax.persistence.PersistenceException:
org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
最佳答案
显而易见的问题之一:
java.lang.OutOfMemoryError: GC overhead limit exceeded
表示您没有足够的堆内存,并且JVM花费大量时间进行垃圾收集。
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx512m"
告诉JVM,Tomcat和RunNIG的所有应用程序都应该预留512 MB的内存,并且最多可以分配512兆字节的内存。
从上面的错误可以清楚地看出,512 Mb对于您的应用程序来说是不够的。
供您考虑的选项:
什么
maxThreads
值是在TomcatConnector
中定义的。默认值为200
。每个线程占用内存。只需要3个用户,您可以将其减少到5,以节省内存。hibernate.hikari.maximumPoolSize
看起来也太大了。再次5
就足够了。Hibernate加载的每个@Entity都存储在first level cache中。这会减缓休眠并消耗内存。考虑使用stateless session(如果可能)来减少会话大小。
使用VisualVM或其他分析器获取内存转储,以分析内存的去向。
关于java - Apache Tomcat 8 + MySQL性能问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47186214/