【问题标题】:Apache Tomcat 8 + MySQL performance issueApache Tomcat 8 + MySQL 性能问题
【发布时间】:2018-04-21 12:34:59
【问题描述】:

我有一个 Java (tomcat) 应用程序,它使用 MySQL(带有休眠)作为数据库。

这是一个简单的 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 + hiraki 配置是什么?

谢谢!

[编辑]

我删除了 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

【问题讨论】:

  • 也使用 1Gb 的交换内存

标签: java mysql hibernate tomcat hikaricp


【解决方案1】:

明显可见的问题之一:

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 对您的应用来说是不够的。

供您考虑的选项:

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

【讨论】:

  • 它没有用。 =( tomcat 确实开始使用更少的内存,但几个小时后又停止工作。
  • 进行内存转储并进行分析。这里没有灵丹妙药。
猜你喜欢
  • 2016-02-06
  • 1970-01-01
  • 2011-03-21
  • 2014-04-23
  • 2012-01-04
  • 1970-01-01
  • 2011-08-29
  • 2011-10-15
  • 1970-01-01
相关资源
最近更新 更多