业务反馈系统偶发卡顿,经过筛查复现卡顿时间的日志发现了日志内容如下:
居然有928秒的接口,发现的时候简直不敢相信自己的眼睛。首先怀疑接口存在性能问题,或者存在高并发的调用导致服务响应变慢,但是这个928秒也还是有些夸张。
结果翻查代码发现只有一个非常简单的sql查询,并且数据库的慢查询日志没有慢查询。翻查日志上下文发现,并没有高并发访问。并在尝试压测此接口时,发现远远达不到 928s 响应的情况,所以至此可以确定,是其它环境问题。
在上网寻找解决方案时,发现相关内容:
连接池 执行SQL超时15分钟
https://blog.csdn.net/u014155356/article/details/82865451
我们的网络通信过程如下:
Java服务器 <-> 防火墙 <-> 数据库服务器
防火墙会定时与不定时的删除 TCP 会话,在会话删除后,Java服务器使用连接池的连接发送数据库查询请求,过程如下:
- Java服务器建立连接池,经由防火墙与数据库建立三次握手的请求
- 此时防火墙认可这些连接,会正常转发这些请求
- 某时刻,防火墙删除此连接,不会发送 ASK 与 FIN 包
- Java服务器使用此连接发送数据库请求
- 防火墙收到请求后发现此连接无效,丢弃网络包,并且不会发送 ASK 包
- Java服务器在2*RTT后判定网络包丢失,因为没收到 SDK,所以默认判定网络发生拥塞
- 在系统设定的退避时到达后,再次发送重试包,如此循环,退避时间会随着重试次数的增加而增加
- 当重试次数到达系统设定上限后,(Linux 默认次数为15次),重新发起三次握手连接。
我截取的网络日志验证了上述描述内容。
本地测试重试时间为18s,服务器为928s,此时间与系统设定有关上网查找了重试次数与所需时间的关系表。
为了解决此问题,上网查找了 Linux 可以修改,/proc/sys/net/ipv4/tcp_retries2 参数来减少重试次数,当网络环境较好时,可以减少到 5~6 次。
以上就是这十五分钟数据库做的事情,正常来说服务器会定时访问数据库来保持连接的存活性,可能防火墙存在问题,导致连接误杀,只有等网络部门解决后才能从根本上解决此问题。
by 费城的二鹏 2020.05.14 长春
网友评论