java - Apache Tomcat 8 + MySQL 性能问题

标签 java mysql hibernate tomcat hikaricp

我有一个 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 最大连接数设置为 152。

MySQL my.cnf 设置:

wait_timeout = 360
interactive_timeout = 420

服务器在具有 1Gb Ram 和 1 个 vCPU 的 DigitalOcean Droplet 中运行。此服务器的最佳 Tomcat + MySQL + Hikari 配置是什么?

我删除了 Xms512m 和 Xmx512m 参数并将 maximumPoolSize 减少到 20,服务器运行正常几个小时后,我得到:

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 和它正在运行的所有应用程序最初应该保留 512 Mb 的内存,并且它们最多可以分配 512 Mb 的内存。

从上面的错误可以看出,512 Mb 显然对您的应用来说不够。

供您考虑的选项:

  • 在您的 Tomcat Connector 中定义了什么 maxThreads 值。默认为 200。每个线程占用内存。如果只有 3 个用户,我希望您可以将其减少到 5 个以节省内存。
  • hibernate.hikari.maximumPoolSize 似乎也太大了。同样,5 应该足够了。
  • Hibernate 加载的每个@Entity 都存储在first level cache 中.这会减慢 Hibernate 的速度并消耗内存。考虑使用 stateless session (如果可能)减少 session 大小。
  • 使用VisualVM或其他一些分析器进行内存转储以分析您的内存去向。

关于java - Apache Tomcat 8 + MySQL 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47186214/

相关文章:

mysql - 如何从 hibernate+spring 应用程序将 csv 文件导入 mysql?

java - 如何从 Java 中的 Hibernate 查询结果中获取列名?

java - ExoPlayer onResume() 恢复播放状态

mysql - 如何模拟外键到多个相似表的分布?

hibernate - 急于加载时,Grails条件查询将返回同一对象的多个副本

mysql - MySQL 分区在 SELECT 的 EXPLAIN 计划中是否可见......?

mysql - mysql中带有if条件的group_concat

java - 将 1 张以上的图像合并为 gif

Java.sql.SQLException : ORA-08103: object no longer exists cursor in stored procedure

java - 使用 Java 库的随机访问结构化存档文件格式