Tam*_*mpa 91 nginx http-headers uwsgi
我收到了很多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
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个更深入的解释,并希望我的nginx配置为uwsgi没有任何问题.我正在接受它的面子价值......这不是我的问题......客户问题.
谢谢
小智 141
Nginx中的HTTP 499表示客户端在服务器应答请求之前关闭了连接.根据我的经验,通常是由客户端超时引起的.据我所知,这是一个Nginx特定的错误代码.
Mad*_*ern 64
在我的情况下,我不耐烦,最终误解了日志.
实际上真正的问题是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已经死了,或者uWSGi在nginx等待它时死亡.nginx马上就看到了,在这种情况下它会返回499错误.
我通过在客户端(浏览器)发出请求来测试我的设置.在浏览器中没有发生任何事情,它只是一直挂着.在大概10秒(小于超时)之后我得出结论:某些东西不对(这是真的),并从命令行关闭了uWSGI服务器.然后我将转到uWSGI设置,尝试新的,然后重新启动uWSGI服务器.当我关闭uWSGI服务器时,nginx服务器将返回499错误.
所以我一直在调试499错误,这意味着谷歌搜索499错误.但如果我等了足够长的时间,我就会得到504错误.如果我得到504错误,我本来能够更好地理解问题,然后能够调试.
所以结论是,问题在于uWGSI,它一直悬挂着("再等一会儿,再多一点,然后我会为你找到答案......").
我怎么解决这个问题,我不记得了.我想这可能是由很多事情引起的.
mrk*_*rki 18
客户关闭连接并不意味着它是一个浏览器问题!?一点也不!
如果在Web服务器(nginx)前面有一个LB(负载均衡器),可以在AWS或haproxy(自定义)中找到499个错误.这就是LB将充当nginx的客户端.
如果您运行haproxy默认值:
timeout client 60000
timeout server 60000
Run Code Online (Sandbox Code Playgroud)
这意味着如果没有来自nginx的响应,LB将在60000ms后超时.对于需要更多时间执行的繁忙网站或脚本,可能会发生超时.您需要找到适合您的超时.例如,将其扩展为:
timeout client 180s
timeout server 180s
Run Code Online (Sandbox Code Playgroud)
你可能会被设定.
根据您的设置,您可能会在浏览器中看到504网关超时错误,这表示php-fpm出现了问题,但日志文件中的499错误情况并非如此.
小智 17
当您指向499
由 nginx 记录的连接中止时。但通常这是在您的后端服务器太慢时产生的,并且另一个代理首先超时或用户软件中止连接。因此,请检查 uWSGI 是否快速响应,或者 uWSGI / 数据库服务器上是否有任何负载。
在许多情况下,用户和 nginx 之间还有一些其他代理。有些可以在你的基础设施中,比如 CDN、Load Balacer、Varnish 缓存等。其他可以在用户端,比如缓存代理等。
如果您身边有像 LoadBalancer / CDN 这样的代理……您应该将超时设置为首先超时您的后端,然后逐步将其他代理设置为用户。
如果你有:
user >>> CDN >>> Load Balancer >>> Nginx >>> uWSGI
Run Code Online (Sandbox Code Playgroud)
我会建议你设置:
n
到 uWSGI 超时的秒数n+1
秒到 nginx 超时n+2
发送超时到负载均衡器n+3
CDN 的超时秒数。如果您无法设置某些超时(如 CDN),请查找它的超时时间并根据它调整其他超时(n
,n-1
...)。
这提供了正确的超时链。你会发现真的是谁给出了超时并将正确的响应代码返回给用户。
rog*_*ack 14
事实证明,499 确实意味着“客户端中断连接”。
我的客户端“读取超时”设置为 60 秒(并且 nginx 的默认 proxy_read_timeout 也为 60 秒)。所以在我的情况下发生的事情是 nginx 会 error.log 一个upstream 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
使用带有 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)
Run Code Online (Sandbox Code Playgroud)
当然,如果 php-fpm 处理时间较长(例如沉重的 WP 页面),则可能会导致问题。例如,我听说过 php-fpm 崩溃,但我相信可以通过正确配置服务来阻止它们,例如处理对 xmlrpc.php 的调用。
我知道这是一个旧线程,但它与最近发生在我身上的事情完全匹配,我想我应该在这里记录它。设置(在 Docker 中)如下:
症状是应用程序登录提示上出现“502 网关超时”。检查日志发现:
POST
.../login
等等.../login
,最终报超时。499
响应,这当然意味着“主机死亡”。/login
请求根本没有出现(!)在 FPM 服务器的日志中!原来问题是连接数据库验证登录失败。但事实证明,如何弄清楚这一点纯粹是猜测。
完全没有应用程序回溯日志……甚至没有 FPM 收到请求的记录……对我来说是一个完整的(而且是毁灭性的……)惊喜。是的,应用程序应该记录失败,但在这种情况下,FPM 工作进程似乎因运行时错误而死亡,导致499
nginx 做出响应。现在,这显然是我们的应用程序中的一个问题......某处。但我想记录下发生的事情的细节,以造福于接下来面临类似问题的人。
这并没有回答OP的问题,但由于我在疯狂寻找答案后最终来到这里,我想分享我们的发现。
在我们的例子中,事实证明这些 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]
Run Code Online (Sandbox Code Playgroud)
因此,在我们的例子中,我认为使用proxy_ignore_client_abort on
之前的答案中建议的方法是安全的。感谢那!
归档时间: |
|
查看次数: |
204942 次 |
最近记录: |