Connection reset by peer原因分析定位

背景
在这里插入图片描述

client和server通过websocket协议通信,长连接保活,server前有nginx做反向代理,client和server是多对多关系;

server端定时给client下发任务,client执行任务并将结果上报给server,client还会定时给server发送心跳保活连接。

现象
系统运行一段时间之后,nginx上error日志频繁报错,如下:

2020/04/15 18:02:51 [error] 374#0: *1917238 send() failed (104: Connection reset by peer) while proxying upgraded connection, client: 172.28.25.222, server: localhost, request: "GET /ws/358/5c5d8dafac7f4586a751ff4c68fb2999/websocket HTTP/1.1", upstream: "http://172.28.72.77:8899/ws/358/5c5d8dafac7f4586a751ff4c68fb2999/websocket", host: "172.28.72.114:8443"
2020/04/15 18:03:03 [error] 374#0: *1913375 send() failed (104: Connection reset by peer) while proxying upgraded connection, client: 172.28.25.214, server: localhost, request: "GET /ws/453/60c9a5af41374f9dbaad4d5444d25c96/websocket HTTP/1.1", upstream: "http://172.28.72.77:8888/ws/453/60c9a5af41374f9dbaad4d5444d25c96/websocket", host: "172.28.72.114:8443"

nginx端频繁重置连接,导致连接不可用,通信异常

分析
抓包
在这里插入图片描述

119是client,117是nginx

从图中看出client给服务端发送了很多 tcp zero window的包,说明客户端已经处理不过来了,告诉对端,不要给我发包了,我不行了;

同时,服务端会定期给客户端发送tcp keepalive链路保活的包,在发送多次zero window后仍然没有有效数据发送,服务端RESET关闭连接,导致服务异常;

在服务器netstat发现如下现象:

client客户端

[apprun@vhost18 ~]$ netstat -tnulpao|grep 443
tcp6  362708      0 172.28.72.119:63132     172.28.72.117:443       ESTABLISHED 32278/java           off (0.00/0/0)
tcp6       0      0 172.28.72.119:63192     172.28.72.117:443       ESTABLISHED 32278/java           off (0.00/0/0)

nginx server服务端

[apprun@newvhost02 ~]$ netstat -anop|grep 443
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      13307/nginx: worker  off (0.00/0/0)
tcp        0 108528 172.28.72.117:443       172.28.72.119:63132     ESTABLISHED 13308/nginx: worker  probe (0.16/0/0)

客户端recev-Q阻塞,表明客户端处理不过来,操作系统接收缓冲区阻塞,程序没有及时消费掉;

nginx服务端send-Q阻塞,不能及时发出去,表明下游程序收不过来,和上述客户端现象表现一致;

同时客户端的系统资源也很充裕,没有任何瓶颈。

解决
查看客户端处理代码逻辑,发现单线程处理,效率低下,改成异步线程池提交处理的方式,问题解决。

总结
在这里插入图片描述

linux操作系统的上述三个参数,跟此次现象有关:

net.ipv4.tcp_keepalive_time = 1800
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5

tcp_keepalive_time,在TCP保活打开的情况下,最后一次数据交换到TCP发送第一个保活探测消息的时间,即允许的持续空闲时间。默认值为7200s(2h)。

tcp_keepalive_intvl,保活探测消息的发送频率。默认值为75s。

发送频率tcp_keepalive_intvl乘以发送次数tcp_keepalive_probes,就得到了从开始探测直到放弃探测确定连接断开的时间,大约为11min。

tcp_keepalive_probes,TCP发送保活探测消息以确定连接是否已断开的次数。默认值为9(次)。

从上述抓包和操作系统三个参数配置,并没有通过包和操作系统参数值对应上,当时环境存在多个client和多个server,抓包数量有限,但是综合情况来看RESET应该是跟这三个操作系统参数有关,但本质原因还是客户端处理不过来,导致数据积压,TCP零窗口。

### macOS 中 'connection reset by peer' 错误解决方案 当在 macOS 上遇到 `connection reset by peer` 的错误提示时,这通常意味着客户端尝试建立连接的过程中服务器突然关闭了连接。此问题可能由多种因素引起,包括但不限于网络配置不当、防火墙阻止特定类型的流量或是应用程序本身的Bug。 对于 Docker 用户而言,在执行 docker pull 命令拉取镜像过程中如果遭遇此类异常,则可能是由于所使用的默认镜像源不可达所致[^1]。针对这种情况的一个简单对策就是切换到更稳定可靠的国内加速器站点来获取所需资源。 而对于采用 my-zsh 终端环境并面临 curl 请求失败情况下的用户来说,调整 `/etc/hosts` 文件的方法未必总是有效的解决途径[^2]。此时可以考虑更新 OpenSSL 版本至最新状态以确保安全协议栈处于良好工作状况;另外确认目标网站是否支持当前版本的安全套接字层(SSL/TLS),必要时可指定较低级别的加密算法进行兼容性访问。 若是 SSH 客户端报告 ssh_exchange_identification: read: Connection reset by peer 类似警告信息的话,那么应该检查服务器侧的权限设定以及日志记录寻找线索[^3]。适当放宽主机策略允许更多范围内的IP地址发起认证请求或许能够缓解部分场景下的通讯障碍现象。 最后,考虑到 Django 应用程序内部逻辑引发的 Errno 54 错误码实例[^4],开发人员应当审视前端页面设计模式避免重复提交表单数据造成不必要的并发冲突事件发生。同时优化后端路由处理器性能表现减少因长时间等待而产生的超时中断风险。 综上所述,面对不同背景条件下所产生的 "connection reset by peer" 故障点,建议采取针对性措施逐一排查直至恢复正常运作为止: - 更换或增加可信度高的镜像仓库链接; - 升级本地依赖库保持同步官方维护进度; - 修改远程服务准入名单适应实际需求变化; - 改善Web应用交互流程提高用户体验质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值