前言
日常业务中会经常碰到Nginx返回499状态码的场景,而499状态码具体含义是什么呢,本文会为大家解答。
定义
首先RFC HTTP文档中并没有定义499状态码,该状态码是Nginx自己定义,具体如下。
/*
HTTP does not define the code for the case when a > client closed
the connection while we are processing its request > so we introduce
own code to log such situation when a client has closed the connection
before we even try to send the HTTP header to it
*/
#define NGX_HTTP_CLIENT_CLOSED_REQUEST 499
而在实际业务中会发现部分用户主动关闭的请求,返回的是状态码200,并不一定是·499,因此Nginx的描述不够详细。
分析
talk is cheap,我们实际模拟一下。
- 使用python代码模拟一个慢的后端,然后配置nginx 转发到该服务(proxy_pass http://XXXX;),nginx监听80端口;
import http.server
import socketserver
from time import sleep
PORT = 8088
class SlowHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
sleep(10) # 等待10秒
http.server.SimpleHTTPRequestHandler.do_GET(self)
Handler = SlowHandler
httpd = socketserver.TCPServer(("", PORT), Handler)
print("Starting at port:", PORT)
httpd.serve_forever()
# http80.py 同路径创建1g下载测试文件
# dd if=/dev/zero of=1g count=1024 bs=1024k
# python3 http80.py
- 模拟两种行为
当服务端正在准备数据并且还未发送数据阶段,收到FIN,日志显示499
当服务端正在准备数据并且还未发送数据阶段,收到FIN,日志显示499
# Server A上启动两个终端
# 终端1
curl -o /dev/null 127.0.0.1/1g
# 终端2(同一时间马上运行)
pkill -9 curl
tail /var/log/nginx/access.log
日志显示499
当服务端正发送数据中,收到FIN,日志显示200
# Server A上启动两个终端
# 终端1
curl -o /dev/null 127.0.0.1/1g
# 终端2(同一时间马上运行)
sleep 10.2 && pkill -9 curl
tail /var/log/nginx/access.log
日志显示200
结论
下载文件过程中,如果Nginx已经开始发送数据给客户端且没有下载完成情况下,客户端主动取消了,状态码为200;
下载文件过程中,如果Nginx还没有发送第一个数据给客户端(可能因为Nginx后端处理过慢),客户端主动取消,状态码为499。