背景
springboot web应用,宕机,无法接受响应,性能优化
初步排查
- jps找到对应的java进程 pid
- top -Hp 对应的java进程pid
- 通过这个pid 126,找到对应的线程 (126通过 print(%x))
- jstack 进程pid | grep 7f
- 发现是一个叫VM THREAD的线程cpu高
内存dump
- jmap -dump:format=b,file=heapdump.hprof java进程pid
- jprofile读取hprof文件
- 看到byte[]特别多
- 我们选中byte[] 查看合并的传入应用,发现和mysql相关
都指向了一段代码,查询数据太多
cleanTicketWarnData
代码排查
发现一个sql查了100多万的数据,直接gc了
改进
方案一
用了mybatis stream 方式(游标形式)读取全表数据
上面这个做法不对,应该是handleResult里面去处理
注意点
开启游标在mysql的驱动,需要设置
resultSetType="FORWARD_ONLY" fetchSize="-2147483648"
主要原因,在mysql驱动中是这样写的
/**
* We only stream result sets when they are forward-only, read-only, and the
* fetch size has been set to Integer.MIN_VALUE
*
* @return true if this result set should be streamed row at-a-time, rather
* than read all at once.
*/
protected boolean createStreamingResultSet() {
return ((this.resultSetType == java.sql.ResultSet.TYPE_FORWARD_ONLY) && (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY)
&& (this.fetchSize == Integer.MIN_VALUE));
}
方案二
通过主键,每次1000,减少查询的数量