网络排查案例课
杨胜辉
eBay 资深运维专家,流量系统负责人
22781 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 39 讲
实战三:不用抓包就能做的网络排查篇 (2讲)
网络排查案例课
15
15
1.0x
00:00/00:00
登录|注册

15 | Nginx的499状态码是怎么回事?

应用层请求
时间戳
客户端IP
Header先发,Body后发
核心信息对应
关注可疑TCP流
使用tcpdump和Wireshark
一起交流讨论,共同成长
将知识分享给更多人
消息网关的应用日志会记录什么状态码?
为什么第7个报文的DupAck没有触发快速重传?
公网丢包现象不可完全消除
网络延迟对通信影响显著
超时时间与499报错数量关联
Nginx 499是Nginx自定义状态码
减少报文延迟和丢包
确保网络连接可靠稳定
改善网络链路质量
网络链路质量问题
TCP包丢失导致服务端空闲等待
客户端5秒超时设置
客户端回复RST
服务端回复HTTP 400
客户端发送FIN
HTTP POST请求
TCP握手成功
抓包分析
问题:Nginx服务器记录大量499错误日志
服务端:公有云服务器
客户端:微信消息网关
Nginx独有状态码
不在HTTP RFC中定义
定义:客户端在服务端处理请求前关闭TCP连接
分享与成长
思考题
总结
解决方案
根因分析
TCP流解读
排查方法
排查案例背景
Nginx 499状态码
Nginx 499状态码排查案例

该思维导图由 AI 生成,仅供参考

你好,我是胜辉。
“实战一:TCP 真实案例解密篇”刚刚结束。在过去的十几讲里,我们全面回顾了 TCP 的各种技术细节,从握手到挥手,从重传等容错机制,到传输速度等效率机制,应该说也是对我们的 TCP 知识做了一个全面的“体检”。如果你发现自己对 TCP 的掌握还有不少漏洞,也别着急,可以回头复习一下相应部分的内容,或者在留言区提问,我会给你解答。
从这节课开始,我们要进入网络排查的“实战二:应用层真实案例解密篇”了。今天要给你讲解的是一个关于 Nginx 的排查案例。

Nginx 的 499 状态码是怎么回事?

你肯定听说过 Nginx,或者经常用到它。作为一个高性能的 HTTP 和反向代理服务器,Nginx 不管是用来搭建 Web Server,还是用作负载均衡都很合适,并且它可供配置的日志字段也很丰富,从各类 HTTP 头部到内部的性能数据都有。
不过,你在日常维护 Nginx 时有没有遇到过这种情况:在 Nginx 的访问日志中,存在 499 状态码的日志。但是常见的 4xx 家族的状态码只有 400、401、403、404 等,这个 499 并未在 HTTP 的 RFC 文档中定义,是不是很奇怪?
这个 499 错误日志,在流量较大的场景下,特别是面向 Internet 的 Web 站点场景下还是很常见的 。但如果你遇到过,第一感觉可能会是一头雾水,不知道 499 这个状态码具体是用来干啥的,因为确实跟其他的 400 系列状态码太不同了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了Nginx的499状态码,并通过一个实际案例介绍了如何通过抓包分析方法解决应用层问题。首先介绍了Nginx的特性和499状态码的出现情况,然后通过抓包分析的方法锚定到网络层,将应用层问题与网络层抓包关联起来。作者通过分析抓包文件中的TCP流成功确定了499事件的关键报文,并指出了在抓包分析中的关键技术障碍和解决方法。文章为读者提供了一套对HTTP返回码进行网络分析的方法,对维护Nginx及其他Web服务具有实际帮助。文章还延伸拓展了Nginx 499状态码的相关知识,包括超时时间与499报错数量的关系,网络延迟对通信的影响,以及公网上丢包现象的影响等。最后,作者提出了排查应用层报错日志的方法论,并留下了两个思考题,引发读者思考和讨论。整体而言,本文内容丰富,涵盖了Nginx状态码、网络分析方法和排查思路,适合技术人员深入学习和交流讨论。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络排查案例课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(24)

  • 最新
  • 精选
  • 追风筝的人
    看老师的解密就像福尔摩斯在探案 精彩(改善客户端到服务端的网络质量)

    作者回复: 谢谢你的支持,其实排查就是这样,很有趣,满足了像我这样的人的探索的欲望,从中也学习到新的知识,是一种很不错的“学习方法”~

    2022-03-01
    13
  • 那时刻
    文中的抓包文件显示 POST请求,Packet size limited during capture: HTTP truncated。这个原因是IP包头里Length是348,而实际的包体小于这个值,所有wireshark才有此显示吧? 另外,HTTP 协议就是这样规定的,数据的先后顺序是:先 header(包含 method、URL、headers),后 body。而我测试了下抓包POST请求,在body不大的情况下,body和header在一个数据包里;而body过大的话,产生分片,此时第一个数据包包含了header以及部分body。请问老师,在POST请求里,存在第一个数据包只包含header,而第二个数据包含有body的情况么?

    作者回复: 是的,Packet size limited during capture: HTTP truncated的原因就是你说的这个~ HTTP是先发header后发body(如果有body的话)。header和body是否在不同的TCP分段中(严格来说不是“分片”)取决于应用程序往发送缓冲区里写入的速度。理论上说,TCP不认识HTTP,也不知道哪些数据是header哪些是body,所以header没凑满一个MSS就先发出去也是可能的。

    2022-03-21
    3
  • 那时刻
    请问老师客户端在报文6发送了fin,而服务器在报文8收到http body,这个报文8是由于客户端内核超时重传报文导致的吧? 客户端对于服务器报文10的fin,回复rst,是不是因为报文10的seq number不合法导致的呢?

    作者回复: 关于第一个问题:这确实是一个有点迷惑人的地方,因为没有客户端的代码(特别是5秒超时的时候tcp连接是如何关闭的,用了close还是shutdown,是否有Linger设置等等),我们只能间接的推测,可能是下面这样: 因为http请求数据量不大,可以在初始拥塞窗口里就能一次发送完,所以客户端把HTTP POST的所有报文都一次性发送了出去,但是因为网络问题,没有收到服务端的全部确认,所以有一部分数据滞留在发送缓冲区,并最终由于超时重传和重试机制得以发出(报文8的http body); 到5秒时,应用程序启动了关闭socket的操作,一个FIN报文也进入了发送缓冲区,不过这个报文“运气好”,立刻被成功收到了。 结合上面的情况,就出现了http body反而在FIN后到达的情况。 第二个问题:报文10的seq是正确的,因为服务端还没有http响应,也就是没有真实的数据发送,所以seq还停留在1,这是对的。收到RST的原因,应该还是客户端那头的tcp连接已经被销毁,因为离客户端发起第一个FIN已经过去16秒。虽然16秒还是小于一般TIME_WAIT需要等待的时间(一般是60秒),但是考虑到客户端作为网关,要处理大量的连接,所以可能对TIME_WAIT做了优化(比如控制TW bucket的长度等)。16秒后,客户端认为这个报文已不属于任何连接,所以直接回复RST。而且这个RST没有ack号,这也符合“因为没有连接而回复”的RST的特征。

    2022-02-23
    2
    2
  • 上杉夏香
    有两个问题,想要询问老师。 1、client在包6已经发送FIN,为啥包8还能发送数据呢?FIN不就是意味着发送端不再拥有发送能力了吗?我能想到的答案就是,这个包8是client在发送包6之前就发送的,只不过经过漫长的路由,才到达server端。 2、关于包8被server端标记为『重传』的标志。因为包是在server端抓取的,就算client确实在不断的重发,对于server来说,它不知道。可是它依然标记为『重传』。那么我觉得它一定有做出如此判断的依据,我能想到的答案是:1、时间;2、包6的seq超过包8.但是最终wireshark为何如此做出判断,那就得看它的源代码了?

    作者回复: 你的思考很深入,给你点赞! 1. 这个报文8如你所说,应该是公网上漫游延迟后到达的,这也是TCP状态机设计的时候,考虑TIME_WAIT需要等待2MSL时间的原因,因为难保有一些报文会延迟到达,这种延迟在这里已经达到了十多秒。 2. 如果要确认这个判断逻辑,只能看一下wireshark源码了。我推测是因为FIN都已经到达了,那么序列号在FIN之前的报文已经都到达了(哪怕wiresahrk没有看到这个报文)。在FIN之后到达的报文,就被wireshark认为是重传。

    2022-08-13归属地:上海
    2
    1
  • salt
    6号报文带了Fin 。7号报文回的不是Fin +ack 而是dup ack。这是因为dup ack的优先级更高? 这样设计的原因是什么?

    作者回复: 这个dupAck是因为客户端发的5号和6号报文之间,数据有间隔,所以服务端回复的ack只能“停留”在数据中断处。如果客户端收到这样的三个dupAck就会启动快速重传。当然这里并没有条件做快速重传了,因为没有凑满三个dupAck。如果还有疑问,可以继续回复我~

    2022-04-20
    1
  • 499的排查思路总结(麻烦老师帮忙看看是否正确): 1、前/后端设置超时不对导致。 譬如后端某接口后端需要3秒,而前端设置的请求超时时间小于3秒,那么会导致大量请求被客户端主动关闭,从而引发大量 NGINX 499。一般根据业务重设前端的请求超时时间即可,这种情况下:单独窗口访问接口、LB机器、后端机器、数据库机器等...负载、慢日志可能都是显示都正常的。 该情况一般多见于新对接功能对整体超时时间不熟悉的情况下,感觉倒是不太常见。

    作者回复: 你的总结是对的:)确实是我们和客户都对这个微信网关的超时逻辑不熟悉导致的,不过这也给我们带去了经验的积累,以后遇到这类问题,会先查一下几个环节的超时设置,因为有可能就是它们没对齐导致了问题~

    2022-03-12
    1
  • 蝴蝶
    如果先去看 nginx 的 499 的介绍,是不是就能更快的定位问题了,哈哈

    作者回复: 哈哈好问题。其实关于499的介绍,一开始看的是官方的简单文档,但不足以说明问题,主要两个原因: 1. 这里的CLIENT CLOSED说的不清晰,为什么关闭?没有更具体的信息 2. 我们的客户是需要更加详细的证据的,比如抓包分析。这是更加重要的原因 源码注释里面的信息更加丰富一些,不过也还是需要结合抓包分析,才足够有说服力:)

    2022-11-21归属地:上海
  • 风铃
    老师你好,看了这么多的资料了,有个疑惑的问题,tcpdump 抓包的方式,很多参数,怎么来判断使用哪些参数抓包合理了,希望解答下,感谢

    作者回复: 这个好办,你可以直接看一下第25讲,也就是抓包分析的回顾、拾遗,和提高。那里有我总结的场景和使用细节。不过还是建议把全专栏都看一遍,实操一下~

    2022-11-10归属地:上海
  • Jack
    请教一下老师,wireshark抓到报文之后Follow Tcp Stream显示的都是乱码,这个怎么解决呢

    作者回复: 你抓取的是什么应用的报文呢?如果是没有加密的http,应该能看到明文;如果是TLS,那确实是密文,也就是你说的乱码了:)

    2022-03-29
    2
  • Jack
    root用户登录机器使用wireshark抓包时报这个错误The temporary file to which the capture would be saved ("/tmpy/ wireshark_eth0_20220328155843_EYvwXW.pcapng") could not be opened: Permission denied. 这个怎么解决呢

    作者回复: 你好,可以参考这里的解答:https://osqa-ask.wireshark.org/questions/39864/the-temporary-file-to-which-the-capture-would-be-saved-could-not-be-opened-invalid-argument/ 简单来说是两步:1. 创建一个目录 2. 把TEMP环境变量的值设置为这个目录的绝对路径 你可以试试~

    2022-03-29
收起评论
显示
设置
留言
24
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部