业务需要,为了提供高性能的查询服务,引入了一款高速搜索服务,客户端的链接使用的HTTP,测试环境使用一切正常,但上线后几乎每天都会发生异常Connection reset by peer。
具体场景如下:
两台业务服务器,用客户端(基于HTTPClient,实现了长连接)连接的搜索服务集群(集群有三台机器),客户端与服务器分别部署在不同的网段,异常会有规律的出现: 每天9点左右会发生异常Connection reset by peer. 而且是连续有三个
Connection reset by peer Caused by: java.io.IOException: Connection reset by peer
at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:197)
这个异常到是很好解决,引入重试机制,捕获这个异常后重新发起请求,第二次都会成功,但这是治标不治本,还需要进一步探究问题的根源。
于是乎,查官方文档、比对代码、让运维同事帮着抓包。。。想了多种方法,经过若干天的努力,最终发现这个异常是和keepalive这个关键词相关。
keepalive 分两种:
TCP的keepalive的作用和HTTP中的不同,TPC中主要用来实现连接保活,相关配置主要是net.ipv4.tcp_keepalive_time这个参数,表示如果经过多长时间(默认2小时)一个TCP连接没有交换数据,就发送一个心跳包,探测下当前链接是否有效,正常情况下会收到对方的ack包,表示这个连接可用。