170

我收到了很多 499 NGINX 错误代码。我看到这是一个客户端问题。这不是 NGINX 或我的 uWSGI 堆栈的问题。当获得 499 时,我注意到 uWSGI 日志中的相关性。

address space usage: 383692800 bytes/365MB} {rss usage: 167038976
bytes/159MB} [pid: 16614|app: 0|req: 74184/222373] 74.125.191.16 ()
{36 vars in 481 bytes} [Fri Oct 19 10:07:07 2012] POST /bidder/ =>
generated 0 bytes in 8 msecs (HTTP/1.1 200) 1 headers in 59 bytes (1
switches on core 1760)
SIGPIPE: writing to a closed pipe/socket/fd (probably the client
disconnected) on request /bidder/ (ip 74.125.xxx.xxx) !!!
Fri Oct 19 10:07:07 2012 - write(): Broken pipe [proto/uwsgi.c line
143] during POST /bidder/ (74.125.xxx.xxx)
IOError: write error

我正在寻找更深入的解释,并希望我的 uwsgi 的 NGINX 配置没有问题。我从表面上看。这似乎是一个客户端问题。

4

15 回答 15

218

Nginx 中的 HTTP 499 表示客户端在服务器响应请求之前关闭了连接。以我的经验通常是由客户端超时引起的。据我所知,这是一个 Nginx 特定的错误代码。

于 2013-08-23T20:02:08.030 回答
98

就我而言,我很不耐烦,最终误解了日志。

事实上,真正的问题是 nginx 和 uwsgi 之间的通信,而不是浏览器和 nginx 之间的通信。如果我在浏览器中加载了该站点并等待了足够长的时间,我会得到一个“504 - Bad Gateway”。但是花了很长时间,我一直在尝试,然后在浏览器中刷新。所以我从来没有等待足够长的时间来看到 504 错误。在浏览器中刷新的时候,也就是之前的请求被关闭的时候,Nginx 会在日志中写入 499。

细化

在这里,我假设读者知道的和我开始玩时一样少。

我的设置是一个反向代理,nginx 服务器和一个应用程序服务器,它背后的 uWSGI 服务器。来自客户端的所有请求都将转到 nginx 服务器,然后转发到 uWSGI 服务器,然后以相同的方式发送响应。我认为这就是每个人都使用 nginx/uwsgi 并且应该使用它的方式。

我的 nginx 正常工作,但是 uwsgi 服务器出了点问题。uwsgi 服务器无法响应 nginx 服务器有两种方式(可能更多)。

1) uWSGI 说,“我正在处理,请稍等,您很快就会得到响应”。nginx 有一定的时间,它愿意等待,fx 20 秒。之后,它将以 504 错误响应客户端。

2) uWSGI 死了,或者 nginx 在等待它时 uWSGi 死了。nginx 会立即看到,在这种情况下,它会返回 499 错误。

我通过在客户端(浏览器)中发出请求来测试我的设置。在浏览器中什么也没发生,它只是一直挂着。大约 10 秒后(小于超时时间),我得出的结论是有些事情不对(这是真的),并从命令行关闭了 uWSGI 服务器。然后我会去 uWSGI 设置,尝试一些新的东西,然后重新启动 uWSGI 服务器。在我关闭 uWSGI 服务器的那一刻,nginx 服务器会返回 499 错误。

所以我一直在调试 499 错误,这意味着在谷歌上搜索 499 错误。但如果我等待的时间足够长,我就会收到 504 错误。如果我得到了 504 错误,我将能够更好地理解问题,然后能够进行调试。

所以结论是,问题出在 uWGSI 上,它一直挂着(“再等一会儿,再等一会儿,我会给你答案……”)。

我是如何解决这个问题的,我不记得了。我想这可能是由很多事情引起的。

于 2014-12-07T22:52:49.707 回答
37

“客户端关闭连接”中的“客户端”不一定是Web浏览器!

如果您在您的用户和您的 Nginx 之间使用负载平衡服务(使用 AWS 或haproxy ),您可能会在 Nginx 日志文件中发现 499 错误。在此配置中,负载均衡器服务将充当 Nginx 服务器的客户端和 Web 浏览器的服务器,来回代理数据。

对于haproxy,某些适用超时的默认值是大约 60 秒,用于连接到上游和从上游(Nginx)或下游(Web 浏览器)读取。

这意味着如果代理在大约 60 秒后没有连接到上游进行写入,或者它没有分别从下游(Web 浏览器)或上游(Nginx)接收到任何数据作为 HTTP 请求或响应的一部分,它会关闭相应的连接,至少在 Nginx 一直在处理请求的情况下(耗时太长),这将被 Nginx 视为错误。

繁忙的网站或需要更多时间执行的脚本可能会发生超时。您可能需要找到适合您的超时值。例如将其扩展到更大的数字,例如 180 秒。这可能会为您解决问题。

根据您的设置,您可能会504 Gateway Timeout在浏览器中看到 HTTP 错误,这可能表明 php-fpm 有问题。但是,情况并非如此,您的日志文件中有 499 个错误。

于 2017-05-17T14:49:53.800 回答
19

当您指向499nginx 记录的连接中止时。但通常这是在您的后端服务器太慢时产生的,并且另一个代理首先超时或用户软件中止连接。因此,请检查 uWSGI 是否快速响应,以及 uWSGI / 数据库服务器上是否有任何负载。

在许多情况下,用户和 nginx 之间还有一些其他代理。有些可以在您的基础架构中,例如 CDN、Load Balacer、Varnish 缓存等。其他可以在用户端,例如缓存代理等。

如果您身边有像 LoadBalancer / CDN 这样的代理......您应该将超时设置为首先超时您的后端,然后逐步将其他代理设置为用户。

如果你有:

user >>> CDN >>> Load Balancer >>> Nginx >>> uWSGI

我会建议你设置:

  • nuWSGI 超时秒数
  • n+1到 nginx 超时的秒数
  • n+2秒到负载均衡器超时
  • n+3CDN 超时秒数。

如果您无法设置某些超时(如 CDN),请查找它的超时并根据它调整其他超时(n... n-1)。

这提供了正确的超时链。你会发现真的是谁给出了超时并将正确的响应代码返回给用户。

于 2019-06-23T08:34:59.047 回答
15

原来 499 确实意味着“客户端中断连接”。

我的客户端“读取超时”设置为 60 秒(nginx 的默认 proxy_read_timeout 也为 60 秒)。所以在我的情况下发生的是 nginx 会 error.logupstream timed out (110: Connection timed out) while reading upstream然后 nginx 重试“您配置的后端服务器组中的下一个代理服务器”。那就是如果你有不止一个。

然后它会尝试下一个和下一个,直到(默认情况下)它已经用尽了所有这些。随着每一个超时,它也会将它们从“实时”后端服务器列表中删除。全部用完后,它返回一个504 gateway timeout.

所以在我的例子中,nginx 将服务器标记为“不可用”,在下一个服务器上重新尝试,然后我的客户端60s超时(立即)发生,所以我会看到一个upstream timed out (110: Connection timed out) while reading upstream日志,然后是 499 日志。但这只是时间巧合。

有关的:

如果组中的所有服务器都标记为当前不可用,那么它502 Bad Gateway.也会在 10 秒内返回一个。请参见此处 max_fails和 fail_timeout。记录它会说的日志no live upstreams while connecting to upstream.

如果您的服务器组中只有一个代理后端,它只是尝试是一个服务器,并返回 a504 Gateway Time-out并且不会从“活动”服务器列表中删除单个服务器,如果proxy_read_timeout超过。参见此处“如果组中只有一个服务器,则忽略 max_fails、fail_timeout 和 slow_start 参数,并且永远不会认为这样的服务器不可用。”

真正棘手的部分是,如果您将 proxy_pass 指定为“localhost”,并且您的盒子恰好同时具有 ipv6 和 ipv4“位置版本”(大多数盒子默认情况下),它就会算作您有服务器组中多台服务器的“列表”,这意味着即使您仅列出一台服务器,您也可以进入上述情况,即让它返回“502 for 10s” 。请参阅此处“如果一个域名解析为多个地址,则所有这些地址都将以循环方式使用。” 一种解决方法是将其声明为proxy_pass http://127.0.0.1:5001;(它的 ipv4 地址)以避免它同时是 ipv6 和 ipv4。然后它算作“只有一个服务器”的行为。

您可以调整一些不同的设置,以使这个问题“减少”。就像增加超时或使其在超时时不会将服务器标记为“已禁用”......或修复列表使其仅大小为 1,见上文 :)

另请参阅:https ://serverfault.com/a/783624/27813

于 2019-11-19T00:03:51.803 回答
12

就我而言,当客户端的 API 在收到任何响应之前关闭连接时,我得到了 499。从字面上发送一个 POST 并立即关闭连接。这是通过选项解决的:

proxy_ignore_client_abort on

Nginx 文档

于 2018-10-25T10:45:11.207 回答
5

使用带有 php-fpm 的标准 nginx 配置很容易重现此错误。

在页面上按住 F5 按钮将向服务器创建数十个刷新请求。浏览器在新的刷新时取消每个先前的请求。就我而言,我在客户的在线商店日志文件中发现了数十个 499。从 nginx 的角度来看:如果在下一次刷新请求之前尚未将响应传递给客户端,则 nginx 会记录 499 错误。

mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:32 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:35 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:35 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)

当然,如果 php-fpm 处理时间较长(如沉重的 WP 页面),它可能会导致问题。例如,我听说过 php-fpm 崩溃,但我相信可以阻止它们正确配置服务,例如处理对 xmlrpc.php 的调用。

于 2018-06-19T08:06:51.423 回答
4

我知道这是一个旧线程,但它完全符合我最近发生的事情,我想我会在这里记录它。设置(在 Docker 中)如下:

  • nginx_proxy
  • nginx
  • php_fpm 运行实际的应用程序。

症状是应用程序登录提示出现“502 网关超时”。检查发现的日志:

  • 该按钮通过 HTTP 工作POST/login...等等...
  • nginx-proxy 得到/login请求,最终报超时。
  • nginx返回了一个499响应,当然意思是“主机死了”。
  • /login请求根本没有出现(!)在 FPM 服务器的日志中!
  • FPM 中没有回溯或错误消息... nada,零,zippo,无。

原来问题是连接数据库验证登录失败。但如何弄清楚这一点纯属猜测。

完全没有应用程序回溯日志……甚至没有 FPM 收到请求的记录……对我来说是一个完整的(并且是毁灭性的……)惊喜。是的,应用程序应该记录故障,但在这种情况下,看起来 FPM 工作进程因运行时错误而死亡,从而导致499来自 nginx 的响应。现在,这显然是我们应用程序中的一个问题……某处。但我想记录下发生的事情的细节,以帮助下一个面临这种情况的人。

于 2020-07-31T18:16:56.207 回答
4

这并没有回答 OPs 的问题,但是由于我在疯狂地寻找答案后最终来到这里,所以我想分享我们的发现。

在我们的例子中,事实证明这些 499 是预期的。例如,当用户在某些搜索框中使用预先输入功能时,我们会在日志中看到类似的内容。

GET /api/search?q=h [Status 499] 
GET /api/search?q=he [Status 499]
GET /api/search?q=hel [Status 499]
GET /api/search?q=hell [Status 499]
GET /api/search?q=hello [Status 200]

因此,在我们的案例中,我认为它可以安全使用proxy_ignore_client_abort on,这在之前的答案中提出了建议。感谢那!

于 2020-02-26T16:14:25.437 回答
3

...从谷歌搜索来到这里

我在这里其他地方找到了答案-> https://stackoverflow.com/a/15621223/1093174

这是为了提高我的 AWS 弹性负载均衡器的连接空闲超时!

(我已经使用 nginx/apache 反向代理设置了一个 Django 站点,并且一个非常非常真正的日志后端作业/视图正在超时)

于 2016-03-15T05:33:41.337 回答
2

一旦我得到499“请求已被防病毒软件禁止”作为 AJAX http 响应(卡巴斯基安全软件通过轻度启发式分析误报,深度启发式分析正确地知道没有任何问题)。

于 2015-06-16T08:09:06.340 回答
1

就我而言,我的设置如下

AWS ELB >> ECS(nginx) >> ECS(php-fpm).

我为 ECS(php-fpm) 服务配置了错误的 AWS 安全组,因此 Nginx 无法访问 php-fpm 任务容器。这就是我在 nginx 任务日志中收到错误的原因

499 0 - elb-healthchecker/2.0

健康检查被配置为检查 php-fpm 服务并确认它已启动并返回响应。

于 2020-03-23T11:32:56.837 回答
0

这种行为的原因之一可能是您使用httpforuwsgi而不是socket. 如果您直接使用,请使用以下命令uwsgi

uwsgi --socket :8080 --module app-name.wsgi

.ini 文件中的相同命令是

chdir = /path/to/app/folder
socket = :8080
module = app-name.wsgi
于 2016-06-13T19:17:05.663 回答
0

我遇到了这个问题,原因是浏览器上的 Kaspersky Protection 插件。如果您遇到这种情况,请尝试禁用您的插件,看看是否能解决您的问题。

于 2016-09-18T18:12:21.043 回答
-1

就我而言,我已启用ufw,但我忘记公开我的上游端口._。

于 2020-03-21T12:46:14.273 回答