Nginx报错104:Connection reset by peer问题的解决及分析


Posted in Servers onJuly 23, 2022

问题解决

应用部署环境

  • 语言:java
  • 框架:ssm
  • web容器:tomcat
  • 负载:nginx
  • 外层代理:F5

现象

根据客户需求对接一个停车缴费的功能,发布到生产环境之后发现,少量账单同时支付没有问题,一旦同时支付的账单数量超过某个值,就会出现网路连接问题,稳定复现。

解决

过程

首先查看了应用的日志,发现用户提示网络异常的时候,服务端没有任何相关的日志打印,确定请求没有发到服务端

查看Nginx Error日志发现打印了错误信息

2021/09/09 08:38:56 [error] 16299#16299: *240963 readv() failed (104: Connection reset by peer) while reading upstream, client: ****, server: ****, request: "POST ****?formData=E172Rfbkeuw2Z6fFYyg95hUMDmDwaOZT7Mqopwu07lo%3CVxsdDikPopy1XjjtjmvSusJwb7UF3erixZi5Wy099%3CewyDvM3wWhvE8X/z/vxKow2ttM1iHPSmWn...

通过nginx日志发现,虽然是nginx层抛出了错误,但是以日志内容来看,其实nginx已经是将请求的报文完整的接收了下来(这个也是在解决问题之后才反应过来),所以其实问题应该是出在Nginx将请求转给被代理的应用服务的时候。

当时在排查问题的时候,没有考虑到还有一层tomcat,导致哪怕是当时怀疑了问题不在nginx这块,还是不敢相信自己,去网上一顿乱搜。

最终解决

在tomcat/conf/server.xml中,增加Connector中的参数配置maxHttpHeaderSize="65536",增加允许tomcat接收的最大请求头大小

<Connector port="****" protocol="org.apache.coyote.http11.Http11NioProtocol"
               URIEncoding="UTF-8"
                  maxHttpHeaderSize="65536" 
               connectionTimeout="20000"
               acceptCount="500" maxThreads="500"
               redirectPort="****" />

问题分析

连接重置

TCP RST

正常情况,服务端使用socket建立一个服务端监听,客户端通过socket向服务端监听发起连接, 双方经过TCP握手协议之后,数据开始传输,TCP协议规定连接在建立之后,双方只要有一端发起关闭的信号,两端就会走放手协议的流程(四次挥手),不再进行数据传输。但是如果一端发起关闭信号之后,不再接收请求,另外一端依然不进入关闭流程,而是依然不停的发送数据,或者是关闭的一端缓存区的数据没有读完就进行了关闭,这时候,关闭的一端就会返回一个RST的信号,告诉另外一端连接被重置

其他情况的RST

除了上边的一种情况,RST还可能出现在客户端找不到服务端端口,服务端因为各种关闭不接收数据等等场景中,但是无一例外,最终就是一端的数据,没有被另外一端完整读取到 ,比如以下几种情况

  1. 客户端直接找不到想要连接的服务端
  2. 一端早就处于关闭的状态了,另外一端还在傻乎乎的给他传输数据
  3. 一端关闭的时候,没有读完另外一端发过来的数据

Tomcat 的 Connector

其实在一定程度上说,Tomcat和Nginx的作用相同,只不过两者的职责不同,Nginx使用了异步非阻塞高性能的组合,可以代理各种各样的URI资源,而Tomcat代理的是一个一个的Servlet容器,它可以容纳所有遵循Servlet规范的应用,并且统一将它们管理。Connector是其中最重要的一部分,它是一个HTTP连接器,它通过启动一个Socket监听,用来接收不同类型的请求,然后把他们解析成对应的Servlet规范的请求,才会将这些请求分发到不同的Servlet中进行处理。当然,内部做了很多其他的事情包括请求校验拦截,请求转化,请求异步线程处理等等。这里只是简单介绍一下,后续会增加关于tomcat部分的文章

Nginx 104

在我们这个案例的场景下分析,nginx要将拿到的请求转发给tomcat中的应用,需要跟tomcat的Connector建立连接,可以将nginx理解为客户端,将tomcat中的Connector理解为socket服务端。tomcat给Connector一套默认的配置,其中maxHttpHeaderSize默认的值是4096字节,也就是4kb。超过4kb的请求头大小的请求,不进行处理,当然这里也有可能发生两种情况,第一种是Connector一开始就知道nginx发过来的请求头过大,直接不接收,响应回去RST标识,还有一种是Connector没有管请求头的大小,直接去接收,但是因为没有将请求头数据读取完就关闭了,响应了RST。这部分没有细看,但是不论怎么说,都是因为上边说过的,没有正常处理完客户端发送过来所有的数据。

类似问题解决思路

在开始无脑查询的时候,其实有很多答案虽然错误码是104,但是报错的原因是不相同的,解决方案也是各不相同,看到过大概以下几种解决思路

  1. nginx的buffer太小,timeout太小。
  2. 长连接,增加长连接超时时间
  3. 将 http version改到1.1 (其实也是使用长连接解决,因为http1.1默认使用长连接)

虽然个人试其他解决方式的时候,都没有成功,也有可能是因为tomcat Connector 连接器的最大请求头4K大小的这个默认配置从最基础的环节直接给把其他配置砍掉了。但是不论使用何种方式解决,最终来说我们就一个思路(虽然说了很像没说),先找到是哪端没有将数据读取完毕,然后想办法让它正常读取

总结

本片文章根据个人发生的实际生产问题,着手解决并且进行问题分析,通过对nginx104的跟踪,对连接重置的概念有一个更详细的了解。

到此这篇关于Nginx报错104:Connection reset by peer问题的解决及分析的文章就介绍到这了,更多相关Nginx报错104:Connection reset by peer内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!


Tags in this post...

Servers 相关文章推荐
destoon在各个服务器下设置URL Rewrite(伪静态)的方法
Jun 21 Servers
Nginx优化服务之网页压缩的实现方法
Mar 31 Servers
nginx简单配置多个server的方法
Mar 31 Servers
Nginx URL重写rewrite机制原理及使用实例
Apr 01 Servers
Nginx如何配置Http、Https、WS、WSS的方法步骤
May 11 Servers
Nginx实现高可用集群构建(Keepalived+Haproxy+Nginx)
May 27 Servers
使用 Apache Superset 可视化 ClickHouse 数据的两种方法
Jul 07 Servers
Nginx设置HTTPS的方法步骤 443证书配置方法
Mar 21 Servers
tomcat默认最大连接数及相关调整方法
May 06 Servers
nginx 添加http_stub_status_module模块
May 25 Servers
详解ZABBIX监控ESXI主机的问题
Jun 21 Servers
解决Git推送错误non-fast-forward的方法
Jun 25 Servers
centos环境下nginx高可用集群的搭建指南
Nginx如何配置根据路径转发详解
Jul 23 #Servers
Linux中一对多配置日志服务器的详细步骤
Jul 23 #Servers
Nginx如何限制IP访问只允许特定域名访问
Jul 23 #Servers
nginx访问报403错误的几种情况详解
Jul 23 #Servers
在windows server 2012 r2中安装mysql的详细步骤
Nginx报404错误的详细解决方法
Jul 23 #Servers
You might like
终于听上了直流胆调频
2021/03/02 无线电
php分页示例代码
2007/03/19 PHP
php学习笔记 PHP面向对象的程序设计
2011/06/13 PHP
PHP不用递归遍历目录下所有文件的代码
2014/07/04 PHP
php上传功能集后缀名判断和随机命名(强力推荐)
2015/09/10 PHP
PHP实现基本留言板功能原理与步骤详解
2020/03/26 PHP
php+js实现点赞功能的示例详解
2020/08/07 PHP
JavaScript URL参数读取改进版
2009/01/16 Javascript
jQuery生成asp.net服务器控件的代码
2010/02/04 Javascript
纯JS实现的批量图片预览加载功能
2011/08/14 Javascript
js如何获取兄弟、父类等节点
2014/01/06 Javascript
jQuery实现自动与手动切换的滚动新闻特效代码分享
2015/08/27 Javascript
React组件重构之嵌套+继承及高阶组件详解
2018/07/19 Javascript
新手必须知的Node.js 4个JavaScript基本概念
2018/09/16 Javascript
微信小程序中如何计算距离某个节日还有多少天
2019/07/15 Javascript
vue项目在线上服务器访问失败原因分析
2020/08/14 Javascript
ES6学习教程之Promise用法详解
2020/11/22 Javascript
[01:15:00]LGD vs Mineski Supermajor 胜者组 BO3 第一场 6.5
2018/06/06 DOTA
Python下使用Psyco模块优化运行速度
2015/04/05 Python
python正则实现计算器功能
2017/12/14 Python
详解Python的循环结构知识点
2019/05/20 Python
python3中替换python2中cmp函数的实现
2019/08/20 Python
python的faker库用法
2019/11/28 Python
Python创建文件夹与文件的快捷方法
2020/12/08 Python
html5实现的便签特效(实战分享)
2013/11/29 HTML / CSS
如何通过jdbc调用存储过程
2012/04/19 面试题
专升本自我鉴定
2013/10/10 职场文书
应届毕业生就业自荐信
2013/10/26 职场文书
创建省级文明单位实施方案
2014/02/27 职场文书
记账会计岗位职责
2014/06/16 职场文书
居委会个人对照检查材料思想汇报
2014/09/29 职场文书
酒店工程部岗位职责
2015/02/12 职场文书
漂亮妈妈观后感
2015/06/08 职场文书
2016年社区创先争优活动总结
2016/04/05 职场文书
MySQL系列之十二 备份与恢复
2021/07/02 MySQL
如何打开Win11系统注册表编辑器?Win11注册表编辑器打开修复方法
2022/04/05 数码科技