记一次线上Connection reset by peer问题排查~  
情况是这样的,我们有一个中心服务器,用来管理好多个子服务器业务,其中就有一台子服务器在连接中心服务器后就断开了。然后中心服务器就抛出Connection reset by peer这个异常。

百度了一下出现这个问题可能的原因:

  • 服务器的并发连接数超过了其承载量,服务器会将其中一些连接关闭;
    如果知道实际连接服务器的并发客户数没有超过服务器的承载量,则有可能是中了病毒或者木马,引起网络流量异常。可以使用netstat -an查看网络连接情况。
  • 客户关掉了浏览器,而服务器还在给客户端发送数据;
  • 浏览器端按了Stop;
    这两种情况一般不会影响服务器。但是如果对异常信息没有特别处理,有可能在服务器的日志文件中,重复出现该异常,造成服务器日志文件过大,影响服务器的运行。可以对引起异常的部分,使用try…catch捕获该异常,然后不输出或者只输出一句提示信息,避免使用e.printStackTrace();输出全部异常信息。
  • 防火墙的问题;
    如果网络连接通过防火墙,而防火墙一般都会有超时的机制,在网络连接长时间不传输数据时,会关闭这个TCP的会话,关闭后在读写,就会导致异常。 如果关闭防火墙,解决了问题,需要重新配置防火墙,或者自己编写程序实现TCP的长连接。实现TCP的长连接,需要自己定义心跳协议,每隔一段时间,发送一次心跳协议,双方维持连接。
  • JSP的buffer问题。
    JSP页面缺省缓存为8k,当JSP页面数据比较大的时候,有可能JSP没有完全传递给浏览器。这时可以适当调整buffer的大小。

问题定位过程:

  1. 由于其它的子服务器都能正常连接,而且我们是内网服务,所以排除了网络波动的原因;并排除防火墙的问题;
  2. 断开的子服务器并没有显示断开连接的代码,所以确定,主动断开连接的原因也可以排除;
  3. 发送的是tcp请求没有JSPbuffer的问题,这个也可以排除掉!
  4. 监控了中心服务器的连接情况,发现中心服务器的连接数,没有达到netty配置的阈值,我们this.bootstrap.option(ChannelOption.SO_BACKLOG, 1024);是这样设置的,所以排除连接数太大的原因;
  5. 那么问题来了,到底是什么原因呢?百思不得其解啊!

经历了漫长的分析过程,内心是一万个为什么啊!怎么弄?郁闷死了。在这个时候,突然发现,每次的断开连接都是在收发特定协议的时候出现的。感觉找到了问题的根源:我们的消息包长度限制了,然后一波操作,直接把netty参数扩大十倍:pip.addLast(new HttpObjectAggregator(655360));一顿重启,解决了!