nginx 499状态码

Posted 大数据从业者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nginx 499状态码相关的知识,希望对你有一定的参考价值。

 

Web服务器在用着nginx,在日志中偶尔会看到有499这个错误。
rfc2616中,400~500间的错误码仅定义到了417,所以499应该是nginx自己定义的。后来想到读读nginx代码,疑问立解。
查看nginx源代码的方法:
1.解压nginx-1.4.7.tar.gz
tar zxf nginx-1.4.7.tar.gz
 
2.查找499关键字:
在nginx源码中grep一下499(现在看源码习惯用grep大法),得到如下结果:
# cd nginx-1.4.7
# grep 499 -r *
发现在src/http/ngx_http_special_response.c文件中有关于499的解释
技术分享图片
 
找到src/http/ngx_http_special_response.c 这个文件,里面定义了不少http错误码以及相应的返回。注意到有下面这样的注释:
技术分享图片
 

可以看到,499对应的是 “client has closed connection”。这很有可能是因为服务器端处理的时间过长,客户端“不耐烦”了。要解决此问题,就需要在程序上面做些优化了。

除了499,nginx还定义了495/496/497/498 这几个Status Codes,相应的意义也在上面的注释中可以看到。开源的东西,可以随时翻看源码,这一点很棒。

 

=========================================================================================================
参考
 

HTTP 499 状态码 nginx下 499错误

    日志记录中HTTP状态码出现499错误有多种情况,我遇到的一种情况是nginx反代到一个永远打不开的后端,就这样了,日志状态记录是499、发送字节数是0。

    老是有用户反映网站系统时好时坏,因为线上的产品很长时间没有修改,所以前端程序的问题基本上可以排除,于是就想着是Get方式调用的接口不稳定,问了相关人员,说没有问题,为了拿到确切证据,于是我问相关人员要了nginx服务器的日志文件(awstats日志),分析后发现日志中很多错误码为499的错误,约占整个日志文件的1%,而它只占全部报错的70%左右(全部报错见下图),那么所有报错加起来就要超过1%了,这个量还是特别大的。

    499错误是什么?让我们看看NGINX的源码中的定义:

ngx_string(ngx_http_error_495_page), /* 495, https certificate error */
ngx_string(ngx_http_error_496_page), /* 496, https no certificate */
ngx_string(ngx_http_error_497_page), /* 497, http to https */
ngx_string(ngx_http_error_404_page), /* 498, canceled */
ngx_null_string,                    /* 499, client has closed connection */

    可以看到,499对应的是 “client has closed connection”。这很有可能是因为服务器端处理的时间过长,客户端“不耐烦”了。

    Nginx 499错误的原因及解决方法
    打开Nginx的access.log发现在最后一次的提交是出现了HTTP1.1 499 0 -这样的错误,在百度搜索nginx 499错误,结果都是说客户端主动断开了连接。
    但经过我的测试这显然不是客户端的问题,因为使用端口+IP直接访问后端服务器不存在此问题,后来测试nginx发现如果两次提交post过快就会出现499的情况,看来是nginx认为是不安全的连接,主动拒绝了客户端的连接.

    但搜索相关问题一直找不到解决方法,最后终于在google上搜索到一英文论坛上有关于此错误的解决方法:
proxy_ignore_client_abort on;
Don’t know if this is safe.
    就是说要配置参数 proxy_ignore_client_abort on;
    表示代理服务端不要主要主动关闭客户端连接。

    以此配置重启nginx,问题果然得到解决。只是安全方面稍有欠缺,但比总是出现找不到服务器好多了。

    还有一种原因是 我后来测试发现 确实是客户端关闭了连接,或者说连接超时 ,无论你设置多少超时时间多没用 原来是php进程不够用了 改善一下php进程数 问题解决 默认测试环境才开5个子进程。

 

499是nginx的Web服务器软件扩展的4xx错误,只是用于记录的目的,没有实际的响应。Nginx 499代表服务端请求还未返回时客户端主动断开连接;还有一种情况就是有人攻击,故意消耗服务端资源。例如我们请求一个费时的python请求,但是客户端等不了,直接把浏览器关了,就会报这个错。不算是特别需要处理的错,单独出现可以不用在意。如果大量出现可以分析下是不是某个请求最近请求时间异常高,适当优化

技术分享图片
 

工具/原料

 
  • nginx

方法/步骤:

 
  1. 1

    proxy_ignore_client_abort的含义。确定在客户端关闭连接时是否应关闭与代理服务器的连接,而不在等待响应。

    技术分享图片
  2. 2

    默认 proxy_ignore_client_abort 是关闭的。此时在请求过程中如果客户端主动关闭请求、客户端网络断开,那么 Nginx 会记录 499。

    技术分享图片
  3. 3

    如果使用了proxy_ignore_client_abort on。那么客户端主动断掉连接之后,Nginx 会等待后端服务器处理完(或者超时),然后记录“后端的返回信息”到日志。因此,如果后端返回200,就记录200 ;如果后端返回5XX ,那么就记录 5XX。如果超时(默认60s,可以用 proxy_read_timeout 和proxy_send_timeout设置),Nginx 会主动断开连接,记录504。

  4. 4

    怎么在配置增加proxy_ignore_client_abort on。首先找到配置文件,然后打开它,找到http下的server下的location,把它加进去。配置文件路径(当你执行 nginx -t 的时候,nginx会去测试你的配置文件语法,并告诉你配置文件是否写得正确,同时也告诉了你配置文件的路径)

    技术分享图片
  5. 5

    注:不建议使用proxy_ignore_client_abort 来处理这个错误。因为这样当有大量瞬间断开的请求时,后端会默默地全部处理,比较浪费资源,而且并发压力比较大时,用这种方法将压垮机器。这个事情交给 php-fpm 自己来处理其实挺合适。因为 PHP 默认当用户断开请求了会中断请求,如果不想自动中断请求,使用 ignore_user_abort() 就好了。

    END

方法/步骤2:

 
  1.  

    尽管NGINX配置了,但60秒后HTTP499错误。Nginx上的超时都设置了很大的值(远远超过60秒)。这可能是云服务器设置问题,以AWS为例。如果部署在AWS上时,60秒后连接不断被丢弃,Nginx访问日志中是499。当将错误日志设置为调试模式时,您将看到类似下面的内容。 不清楚为什么客户端删除连接。

    技术分享图片
  2.  

    解决方案。在AWS上有一个负载均衡器(load balancer),你大部分都用了默认的配置,因此它将在60秒后删除连接。将其更改去配合您的Nginx配置。

    技术分享图片
  3.  



























以上是关于nginx 499状态码的主要内容,如果未能解决你的问题,请参考以下文章

HTTP 499 状态码 nginx下 499错误

nginx-499状态码

nginx 499状态码

HTTP 499 状态码 nginx下 499错误

Nginx状态码499

使用 Google Cloud Kubernetes TCP 负载均衡器的 Nginx 状态码 499