15 | Nginx的499状态码是怎么回事?
该思维导图由 AI 生成,仅供参考
Nginx 的 499 状态码是怎么回事?
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了Nginx的499状态码,并通过一个实际案例介绍了如何通过抓包分析方法解决应用层问题。首先介绍了Nginx的特性和499状态码的出现情况,然后通过抓包分析的方法锚定到网络层,将应用层问题与网络层抓包关联起来。作者通过分析抓包文件中的TCP流成功确定了499事件的关键报文,并指出了在抓包分析中的关键技术障碍和解决方法。文章为读者提供了一套对HTTP返回码进行网络分析的方法,对维护Nginx及其他Web服务具有实际帮助。文章还延伸拓展了Nginx 499状态码的相关知识,包括超时时间与499报错数量的关系,网络延迟对通信的影响,以及公网上丢包现象的影响等。最后,作者提出了排查应用层报错日志的方法论,并留下了两个思考题,引发读者思考和讨论。整体而言,本文内容丰富,涵盖了Nginx状态码、网络分析方法和排查思路,适合技术人员深入学习和交流讨论。
《网络排查案例课》,新⼈⾸单¥59
全部留言(24)
- 最新
- 精选
- 追风筝的人看老师的解密就像福尔摩斯在探案 精彩(改善客户端到服务端的网络质量)
作者回复: 谢谢你的支持,其实排查就是这样,很有趣,满足了像我这样的人的探索的欲望,从中也学习到新的知识,是一种很不错的“学习方法”~
2022-03-0113 - 那时刻文中的抓包文件显示 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-213 - 那时刻请问老师客户端在报文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-2322 - 上杉夏香有两个问题,想要询问老师。 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归属地:上海21 - salt6号报文带了Fin 。7号报文回的不是Fin +ack 而是dup ack。这是因为dup ack的优先级更高? 这样设计的原因是什么?
作者回复: 这个dupAck是因为客户端发的5号和6号报文之间,数据有间隔,所以服务端回复的ack只能“停留”在数据中断处。如果客户端收到这样的三个dupAck就会启动快速重传。当然这里并没有条件做快速重传了,因为没有凑满三个dupAck。如果还有疑问,可以继续回复我~
2022-04-201 - 简499的排查思路总结(麻烦老师帮忙看看是否正确): 1、前/后端设置超时不对导致。 譬如后端某接口后端需要3秒,而前端设置的请求超时时间小于3秒,那么会导致大量请求被客户端主动关闭,从而引发大量 NGINX 499。一般根据业务重设前端的请求超时时间即可,这种情况下:单独窗口访问接口、LB机器、后端机器、数据库机器等...负载、慢日志可能都是显示都正常的。 该情况一般多见于新对接功能对整体超时时间不熟悉的情况下,感觉倒是不太常见。
作者回复: 你的总结是对的:)确实是我们和客户都对这个微信网关的超时逻辑不熟悉导致的,不过这也给我们带去了经验的积累,以后遇到这类问题,会先查一下几个环节的超时设置,因为有可能就是它们没对齐导致了问题~
2022-03-121 - 蝴蝶如果先去看 nginx 的 499 的介绍,是不是就能更快的定位问题了,哈哈
作者回复: 哈哈好问题。其实关于499的介绍,一开始看的是官方的简单文档,但不足以说明问题,主要两个原因: 1. 这里的CLIENT CLOSED说的不清晰,为什么关闭?没有更具体的信息 2. 我们的客户是需要更加详细的证据的,比如抓包分析。这是更加重要的原因 源码注释里面的信息更加丰富一些,不过也还是需要结合抓包分析,才足够有说服力:)
2022-11-21归属地:上海 - 风铃老师你好,看了这么多的资料了,有个疑惑的问题,tcpdump 抓包的方式,很多参数,怎么来判断使用哪些参数抓包合理了,希望解答下,感谢
作者回复: 这个好办,你可以直接看一下第25讲,也就是抓包分析的回顾、拾遗,和提高。那里有我总结的场景和使用细节。不过还是建议把全专栏都看一遍,实操一下~
2022-11-10归属地:上海 - Jack请教一下老师,wireshark抓到报文之后Follow Tcp Stream显示的都是乱码,这个怎么解决呢
作者回复: 你抓取的是什么应用的报文呢?如果是没有加密的http,应该能看到明文;如果是TLS,那确实是密文,也就是你说的乱码了:)
2022-03-292 - Jackroot用户登录机器使用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