Nginx频繁报状态码400错误,定位到原因是丢包引起

目录 

一、背景说明

二、访问日志分析

三、TCP抓包分析

四、结论


一、背景说明

最近线上服务发布,完成后一切平静,到下午用户量正常起来后,开始频繁收到Nginx状态码是400的告警,初步确认是偶尔出现,还好还好!

400通常理解为客户端请求错误,一般原因是请求数据中有不合法字符,请求头缺失host头。但这次案例另有原因。详细回顾下定位过程和方法,供大家参考。

二、访问日志分析

服务器的负载均衡LB中状态码正常的日志:

LB侧状态码是400的日志:

 对比发现一个很明显的规律:request_length在400状态码时偏低,upstream_response_time普遍到4s。

看到这个不得不有一个大胆的怀疑是由于Nginx未收到完整请求数据,而标记请求为400。

三、TCP抓包分析

接下来可能需要进行TCP抓包分析看看有没有线索。

到Nginx所在机器,通过tcpdump抓包

sudo  tcpdump -A -i et11 -w tcpdump.data port 1000

et11是网卡名称,1000是nginx接收请求的监听端口,tcpdump.data是包数据保存文件。

利用wireshark进行抓包分析,以其中一条请求400的日志时间结合请求耗时,倒推出该次请求大概的发生时间点。

 图中是一条400的访问日志,推算发生时间大概是在(38分31秒减去4.98秒)38分26秒。

先看一个正常的请求的TCP包序列:

 客户端端口50469与服务器建立连接的通讯过程:

550-552是连接建立的三次握手,553-560完成了一次完整的请求(557忽略),发送请求时,有一个553的分包PDU(TCP segment of a eassembled PDU),555是请求包,559是响应包,状态码是200。

再来定为400时的TCP包序列,补充一点定位到这个请求包的方式是通过包的到达时间,wireshark显示示意如下:

该条请求的包序列如下: 


 2434-2436是建立连接的三次握手,后续接收到的请求包数据只有2437和一个响应客户端的ACK,这就说明,服务器只收到一个请求分包,后续就没再接收到,大概等待5s左右,收到一个RST断开连接的包,此时Nginx就会在日志中记录一条400状态码的请求。

四、结论

至此原因基本定位到是丢包导致,单纯从服务侧很难再继续追踪,后续希望从客户端侧能进一步排查丢包原因,客户端的请求方式是否需要优化。

后续:经客户端确认可能与设置超时时间过短有关,客户端在大并发发送后台请求时,超时又比较短,会存在大量中断请求的情况。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TechingOn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值