nginx 499 产生的原因

什么是 nginx 的 499

499 是 nginx 扩展的 4xx 错误,目的只是用于记录,并没有实际的响应。
看一下 nginx 源码 ngx_http_request.h 对 499 的定义:

/*
* 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

由上述表述可知,nginx 499 代表客户端请求还未返回时,客户端主动断开连接。

什么情况下 nginx 记录 499

通过网上查询相关资料学习与了解,自己总结大致原因就是请求在指定的时间内没能拿到响应而关闭了连接。问题症结点为两处:1、指定的时间;2、程序处理的性能。

时间问题

最开始时,表述过 nginx 499 是客户端主动断开了连接。这里的客户端概念,我的理解是对请求连接过程中的下游服务而言的,例如浏览器与 nginx 之间的连接,浏览器为客户端;nginx 与其分发的服务而言,nginx 是客户端;php 处理程序中发起的 curl 请求而言,php-fpm 可视为客户端。
上述的指定时间内的这个时间,一般是定义的处理超时时间,可能的原因就是这个时间设短了。
以发起 curl 请求为例,数据传输的最大允许时间用 -m 参数来指定。
例如:
curl -m 20 "http://somewebsite.com"
数据传输的最大允许时间超时的话,curl 断开了请求,而 web 服务器如 nginx 还在处理的话,则 nginx 会记录 499;

再如 nginx 作为反向代理时,nginx 将请求分发至对应的处理服务器时,有两对超时参数的设置:proxy_send_timeoutproxy_read_timeout ; fastcgi_send_timeoutfastcgi_read_timeout
两对参数分别对应的是 ngx_http_proxy_module 和 ngx_http_fastcgi_module 模块的参数。两对参数默认的超时时间都是 60 s。在 nginx 出现 499 的情况下,可以结合请求断开前的耗时和这两对设定的时间进行对比,看一下是不是在 proxy_pass 或者 fastcgi_pass 处理时,设置的超时时间短了。

再如 php 操作超时。打开 php.ini 查看 max_execution_timemax_input_time 两个参数。两者分别是 php 程序执行的最长时间和表单提交的最长时间。

如果后端服务中访问了负载均衡的,例如 AWS 上的 Elastic Load Balances 等。出现 nginx 上设置的超时很大,nginx 同样记录了 499 状态,那么有可能就是负载均衡在默认时间(一般是 60 s)后删除了连接。这种情况下,可根据 nginx 的配置,相应的修改负载均衡的配置。

性能问题

性能问题就比较宽泛了,不太便于排除,可能会有的情况:
1、CPU 和内存的使用情况
linux 上,可以用 top 命令查看 CPU 和内存的使用情况。

top - 16:59:03 up 334 days, 23:10,  1 user,  load average: 0.06, 0.08, 0.07
Tasks: 114 total,   2 running, 112 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.5 us,  0.3 sy,  0.0 ni, 98.5 id,  0.7 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2916192 total,   516184 free,  1540972 used,   859036 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   999988 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                     
11475 work      20   0  157680   2188   1520 R   0.7  0.1   0:00.34 top                                                                         
12206 elastic+  20   0 3685272 980.1m    272 S   0.7 34.4   1027:58 java                                                                        
24451 mysql     20   0 1745372 275176   2892 S   0.3  9.4 761:20.55 mysqld                                                                      
    1 root      20   0  232328  46328   1324 S   0.0  1.6  33:03.32 systemd                                                                     
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.80 kthreadd                                                                    
    3 root      20   0       0      0      0 S   0.0  0.0   0:37.02 ksoftirqd/0                                                                 
    5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H                                                                
    7 root      rt   0       0      0      0 S   0.0  0.0   0:20.47 migration/0                                                                 
    8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh                                                                      
    9 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/0                                                                     
   10 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/1                                                                     
   11 root      20   0       0      0      0 R   0.0  0.0 126:24.86 rcu_sched

第三行,cpu状态信息,具体属性说明如下:

0.5% us — 用户空间占用CPU的百分比;
0.3% sy — 内核空间占用CPU的百分比;
0.0% ni — 改变过优先级的进程占用CPU的百分比;
98.5% id — 空闲CPU百分比;
0.7% wa — IO等待占用CPU的百分比;
0.0% hi — 硬中断(Hardware IRQ)占用CPU的百分比;
0.0% si — 软中断(Software Interrupts)占用CPU的百分比。

第四行,内存状态,具体信息如下:

2916192k total — 物理内存总量(2.9GB);
1540972k used — 使用中的内存总量(1.5GB);
516184k free — 空闲内存总量(0.5GB);
859036k buffers — 缓存的内存量 (859M)。

2、php-fpm 等 fastcgi 处理程序进程数不够用
需要理解的参数有: pm、pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_servers。
pm 表示进程数的控制方式,分别为 static (静态)和 dynamic (动态)。

pm = dynamic 如何控制子进程,选项有static和dynamic
pm.max_children:静态方式下开启的php-fpm进程数量
pm.max_requests:php-fpm子进程能处理的最大请求数
pm.start_servers:动态方式下的起始php-fpm进程数量
pm.min_spare_servers:动态方式下的最小php-fpm进程数
pm.max_spare_servers:动态方式下的最大php-fpm进程数量

3、mysql 等数据查询过程缓慢
MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思是运行10S以上的语句。默认情况下,Mysql数据库并不启动慢查询日志,需要我们手动来设置这个参数。具体可参考Mysql 慢查询日志总结

4、程序处理逻辑性能不好
这一项需要查询程序的逻辑处理是否有过多的重复的或者冗余的过程了。:smile:

他人给的解决方案

网上能查询到的解决方案基本就是在 nginx.conf 的 http 块中添加 proxy_ignore_client_abort on;
默认的情况下该参数是关闭的。nginx 官网给的参数说明如下:

Determines whether the connection with a proxied server should be closed when a client closes the connection without waiting for a response.

主要意思就是在客户端主动关闭连接后, nginx 与分发服务器的连接是否保持连接。
如果使用了 proxy_ignore_client_abort on; Nginx 会等待后端处理完(或者超时),然后记录「后端的返回信息」到日志。所以,如果后端返回 200,就记录 200 ;如果后端放回 5XX ,那么就记录 5XX 。
如果超时(默认60s,可以用 proxy_read_timeout 设置),Nginx 会主动断开连接,记录 504。
上述方法,个人认为仅仅是解决了 nginx 记录 499 的问题,并没有从本质上解决客户端没能拿到请求响应的问题,具体还是得从超时时间的设定和程序处理性能的提升上从根本解决问题。


总结参考自
[1]:Linux top 命令
[2]:php-fpm 进程数优化

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容

  • Nginx简介 解决基于进程模型产生的C10K问题,请求时即使无状态连接如web服务都无法达到并发响应量级一万的现...
    魏镇坪阅读 1,980评论 0 9
  • 1. Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单...
    rosekissyou阅读 10,170评论 5 124
  • 《老男孩Linux运维》笔记 隐藏Nginx软件版本号 一般来说,软件的漏洞都和版本有关。因此要尽量隐藏对访问用户...
    Zhang21阅读 3,602评论 0 28
  • 第一章 Nginx简介 Nginx是什么 没有听过Nginx?那么一定听过它的“同行”Apache吧!Ngi...
    JokerW阅读 32,608评论 24 1,002
  • 1.简介:  Nginx:engine X ,2002年,开源,商业版 http协议:web服务器(类似于ht...
    尛尛大尹阅读 1,855评论 0 3