Connection reset by peer 的IOException的异常

本文深入探讨了ConnectionResetByPeer异常的成因,详细解释了长连接、短连接及HTTP的keepalive连接的区别,特别是在HTTP1.1中keepalive机制的作用。分析了Tomcat8对keepalive的支持与配置,以及连接池如何处理keepalive机制,最后阐述了ConnectionResetByPeer异常的具体场景和解决方案。

http客户端发起连接时经常会碰到Connection reset by peer 的IOException,这个异常是由jdk抛出来的。详细介绍下这个异常的发生说明了什么。

1. 对于连接而言,首先区分三种连接种类

一般连接主要分为长连接,短连接和http的keepalive连接。

1.1 长连接:建立完连接后,该连接不再进行释放。

  • 优点

    • 性能较高,不需要重复建立tcp连接或者关闭tcp连接

    • 基本上不会出现CLOSE_WAIT和TIME_WAIT的问题

  • 缺点:一般需要一个连接池来维护长连接(一般有数据库连接池,http的连接池等) 复杂度较高

1.2 短连接:每次请求均需要tcp三次握手建立连接,业务执行,tcp四次挥手关闭连接。

  • 优点:实现简单。

  • 缺点:

    • 性能较差。大部分都是tcp层面上的交互(新建和关闭tcp连接)

    • 系统会出现大量的tcp的状态是:TIME_WAIT 如果没有设置SO_RESUSEADDR ,很容易出现端口被占满的情况。(在关闭完连接时,tcp状态是TIME_WAIT,只有等2个MSL后,才会进行close掉)

1.3 http的keepalive:用于http协议。在http 1.1中,为了解决长连接提出的。

  • 优点:用于维护长连接,提升性能

  • 缺点:需要在header中进行控制,需要交互控制,相对复杂。

2 keepalive机制

提到keepalive, 容易对下面三种机制混淆:

  • keepalived

  • tcp 的 keepalive

  • http 的 keepalive

2.1 keepalived

用途:高可用,一般是和lvs一起使用。

具体可参考:http://outofmemory.cn/wiki/keepalived-configuration

2.2 tcp的keepalive

用途:socket连接的保活。在新建socket的时候,可以设置SO_KEEPALIVE 进行打开。

keepalive主要有三个参数:

  • tcp_keepalive_time: 一个连接需要TCP开始发送keepalive探测数据包之前的空闲时间。以秒为单位

  • tcp_keepalive_probes: 发送TCP keepalive探测数据包的最大数量,默认是9.如果发送9个keepalive探测包后对端仍然没有响应,便发送RST关闭掉连接。

  • tcp_keepalive_intvl: 发送两个TCP keepalive探测数据包的间隔时间,默认是75秒

2.3 http的 keepalive

用途:http的长连接,在http 1.0中使用的为短连接:每一次请求均需要新建tcp连接,http协议数据的发送接收,关闭tcp连接。 该种机制性能很 低,在http 1.1协议中引入了keepalive机制来保持tcp连接。

在http1.0中,全部是短连接,如果想建立长连接,需要在header里面加上keepalive,这样web服务器看到这个字段,不会立马关闭连接。而是将tcp连接维持一段时间。如果需要关闭,则在header中写 keepalive close,来告诉 客户端需要关闭该连接。

在http1.1中,默认会实现keepalive,如果使用的是http1.1协议,header是不需要加上keepalive的。

3. tomcat8对keepalive的实现

3.1 http 1.0实现

tomcat8中,如果发送的是http1.0的协议。 tomcat8返回的均是1.1的协议。并且不管请求的header有没有Connection:keepalive ,均会在返回的header中加上connection:close 。也就是使用的短连接方式

3.2 http 1.1实现

tomcat8主要有两个参数来控制keepalive的机制。keepAliveTimeout 和maxKeepAliveRequests

  • keepAliveTimeout: 默认和soTimeout 值保持一致,该值为20000ms,也就是在这么长时间内没有通信,tomcat会关闭掉该连接。设置为-1 则代表不会关闭该连接。

  • maxKeepAliveRequests :默认为100,也就是在keepAliveTimeout时间内,如果使用次数超过100,则会关闭掉该连接。设置为-1,则代表不会关闭连接。在关闭后,会在返回的header上面加上Connection:close 。

如果需要tomcat保持长连接:可配置 maxKeepAliveRequests = "-1" keepAliveTimeout=-"-1" ,则tomcat8不会关闭掉该连接。

4. 连接池对keepalive的处理

主要需要处理两个地方:

  • 1:maxKeepAliveRequests 连接达到默认的设置次数。则会在header上面加Connection:close。

    • 在接收web服务器返回的数据时,需要检查一下header里面是否有Connection:close,如果close,则需要将该连接从连接池里物理关闭掉。否则容易出现connection reset by peer的异常。

  • 2:keepAliveTimeout 超过该时间没有流量,则会关闭掉连接。

    • tomcat在连接空闲超过该时间后,会主动关闭掉连接。会向客户端发送FIN命令。

如果是IO(同步socket):则在获取连接的时候需要检查一下该socket的连接状态。 因为tcp在底层已经关闭了该连接。 如果不检查的话,则会SocketCloseException的错误。

如果是NIO(异步channel) :则在selector的时候,read数据的时候,会返回-1,然后将该连接从连接池给物理关闭掉。

5. Connection reset by peer异常

异常场景

  • 1: 当我们往一个对端已经close的通道写数据的时候,对方的tcp会收到这个报文,并且反馈一个reset报文,当收到reset报文的时候,继续做select读数据的时候就会抛出Connect reset by peer的异常。该异常为jdk抛出的异常。在native代码里面抛出。

  • 2:尝试和未开放的服务器端口建立tcp连接时,服务器tcp将会直接向客户端发送reset报文

  • 3:ack报文丢失,并且超出一定的重传次数或时间后,会主动向对端发送reset报文释放该TCP连接

连接池出现该异常分析

  • 1:由于客户端在收到Connection:close的header时候并没有物理关闭该连接,而是将该连接返回到了连接池中。

  • 2:下一个请求拿到该连接发送数据,由于tomcat的该socket通道已经关闭,tomcat接收到该连接时,便会回复一个RST。

  • 3:客户端在读取数据(RST的时候,内部会调用(JDK)SocketChannel.read的时候抛出 java.io.IOException(Connection reset by peer)

### 关于 Java `IOException` "Connection Reset By Peer" 的原因及解决方案 #### 原因分析 当遇到 `IOException` 报错提示 “connection reset by peer”,通常意味着客户端尝试读取数据时,服务器端已经关闭了连接。这种情况可能由多种因素引起: - 数据库无法同时处理大量并发连接请求,从而触发连接重置异常[^3]。 - 网络不稳定或防火墙设置不当也可能引发此类错误。 #### 解决方案 针对上述情况,可以采取如下措施来解决问题: ##### 调整数据库配置参数 适当调整数据库的最大连接数限制和其他相关性能参数,确保其能够承受预期的工作负载量。这有助于防止由于资源耗尽而导致的意外断开现象发生。 ##### 实现优雅关闭机制 通过实现自定义的监听器,在应用程序正常退出前执行必要的清理工作,比如释放占用的资源等操作。例如,可以通过添加shutdown listener的方式捕获到JVM停止事件并作出响应: ```java Runtime.getRuntime().addShutdownHook(new Thread(() -> { try { // 执行一些必要的收尾动作 connection.close(); } catch (SQLException e) { logger.error("Failed to close database connection", e); } })); ``` 此外还可以考虑使用更高级别的抽象框架(如Spring Boot),它们往往内置了许多最佳实践的功能模块可以直接利用[^2]。 ##### 设置合理的超时时间 对于长时间未完成的操作设定合适的超时期限,并在程序逻辑中加入相应的异常处理流程。这样即使出现了网络波动等问题也能及时发现并做出恰当反应而不是无限期等待下去。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值