简体   繁体   English

Kubernetes Nginx入口控制器返回502,但仅用于AJAX / XmlHttpRequest请求

[英]Kubernetes nginx ingress controller returns 502 but only for AJAX/XmlHttpRequest requests

I have a web app running Kubernetes behind an nginx ingress controller, it works fine for request browsing, but any AJAX/XMLHTTPRequest from the browser gets a 502 error from nginx. 我有一个在nginx入口控制器后面运行Kubernetes的Web应用程序,它可以很好地用于请求浏览,但是来自浏览器的任何AJAX / XMLHTTPRequest都会从nginx获取502错误。

I captured the HTTP headers for both regular and AJAX request that they look fine, correct Host header, protocol, etc. I am confused why only XMLHttpRequest requests get the 502 from nginx. 我捕获了常规和AJAX请求的HTTP标头,它们看起来都不错,正确的Host标头,协议等。我感到困惑,为什么只有XMLHttpRequest请求从nginx获取502。 There is no delay/hang, the 502 is immediate. 没有延迟/挂起,502是即时的。 The requests appear to never reaches app, but get rejected by nginx itself. 这些请求似乎永远不会到达应用程序,但是会被nginx本身拒绝。 Switching nginx out for a direct Load Balancer and the problem goes away. 将nginx切换为直接负载均衡器,问题就消失了。

I am going to dig further but I wondered if anyone else using the nginx ingress controller seen this problem before and solved it? 我将进一步进行挖掘,但我想知道是否其他任何使用Nginx Ingress控制器的人之前都曾看到过此问题并已解决?

I picked this error out of the nginx log which suggests the container return a response with a too large header for an nginx buffer. 我从nginx日志中选择了此错误,这表明容器返回的响应对于nginx缓冲区而言具有太大的标头。 However I checked nginx.conf and buffering is disabled: 'proxy_buffering off;' 但是我检查了nginx.conf并禁用了缓冲:'proxy_buffering off;'

2016/10/27 19:55:51 [error] 309#309: *43363 upstream sent too big header while reading response header from upstream, client: 10.20.51.1, server: foo.example.com, request: "GET /admin/pages/listview HTTP/2.0", upstream: "http://10.20.66.97:80/admin/pages/listview", host: "foo.example.com", referrer: "https://foo.example.com/admin/pages"

Strangely you get the 504 error only if XmlHttpRequest requests the URL. 奇怪的是,仅当XmlHttpRequest请求URL时,您才收到504错误。 If I request the same URL with curl it works fine and the response header is as below. 如果我使用curl请求相同的URL,它可以正常工作,并且响应标头如下。 What about the AJAX/XmlHttpRequest of the same URL would make the response headers too large? 相同URL的AJAX / XmlHttpRequest会使响应头太大吗?

HTTP/1.1 200 OK
Server: nginx/1.11.3
Date: Thu, 27 Oct 2016 20:15:16 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 6596
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-Powered-By: PHP/5.5.9-1ubuntu4.19
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: max-age=0, must-revalidate, no-transform, no-cache, no-store
Pragma: no-cache
X-Controller: CMSPagesController
X-Title: Example+Site+-+Pages
X-Frame-Options: SAMEORIGIN
Vary: X-Requested-With,Accept-Encoding,User-Agent
Strict-Transport-Security: max-age=15724800; includeSubDomains; preload

I resolved the issue. 我解决了这个问题。 The reason that only XmlHttpRequests failed was because the application has a special behavior when it saw an XmlHttpRequest request, where it dumped about 3000 bytes of extra headers into the response. 仅XmlHttpRequests失败的原因是因为应用程序在看到XmlHttpRequest请求时具有特殊的行为,该请求将大约3000字节的额外标头转储到响应中。 This made the total header size larger than the default nginx header buffer. 这使得总头大小大于默认的nginx头缓冲区。

nginx chocking on large HTTP header payloads is common, because its default buffer size is smaller than most other web servers, only 4k or 8k. nginx在大型HTTP标头有效载荷上阻塞很常见,因为它的默认缓冲区大小小于大多数其他Web服务器,只有4k或8k。 The solution to the errors was to increase the buffer used for headers to 16k by adding these settings. 解决这些错误的方法是,通过添加这些设置,将用于标头的缓冲区增加到16k。

proxy_buffers         8 16k;  # Buffer pool = 8 buffers of 16k
proxy_buffer_size     16k;    # 16k of buffers from pool used for headers

The nginx documentation is pretty murky and these settings ambiguously named. Nginx文档非常模糊,这些设置含糊不清。 As I understand it there is a pool of buffers for each connection. 据我了解,每个连接都有一个缓冲池。 In this case 8 buffers of 16k each. 在这种情况下,每个有8个16k的缓冲区。 These buffers are used for receiving data from the upstream web server and passing data back to the client. 这些缓冲区用于从上游Web服务器接收数据并将数据传递回客户端。

So proxy_buffers determines the pool. 因此proxy_buffers确定了池。 Then proxy_buffer_size determine host much of that buffer pool is available for receiving the HTTP headers from the upstream server (rounded up to whole buffer size I think). 然后proxy_buffer_size确定主机该缓冲池的大部分可用于接收来自上游服务器的HTTP标头(四舍五入为我认为的整个缓冲区大小)。 A third setting proxy_busy_buffer_size determines how much of the buffer pool can be busy being sent to the client (rounded up to whole buffer size I think). 第三个设置proxy_busy_buffer_size确定可以将多少缓冲池忙于发送给客户端(四舍五入为我认为的整个缓冲区大小)。 By default the proxy_busy_buffer_size is automatically set to the number of buffers in the pool minus 1. 默认情况下, proxy_busy_buffer_size自动设置为池中的缓冲区数减1。

So the proxy_buffers pool must be big enough to fit the proxy_busy_buffer_size and still have enough buffers left over to fit at least the proxy_buffer_size for HTTP headers from the upstream web server. 因此, proxy_buffers池必须足够大以适合proxy_busy_buffer_size并且仍具有足够的缓冲区以至少适合上游Web服务器的HTTP标头的proxy_buffer_size

The net net of that is that if you increase proxy_busy_buffer_size at all you'll probably immediately get the confusing error: "proxy_busy_buffers_size" must be less than the size of all "proxy_buffers" minus one buffer , and then you have to increase the size of the pool. 最终的结果是,如果您完全增加proxy_busy_buffer_size ,您可能会立即得到令人困惑的错误: "proxy_busy_buffers_size" must be less than the size of all "proxy_buffers" minus one buffer ,然后您必须增加游泳池。

And the proxy_buffering off setting you ask? 和您询问的proxy_buffering off设置? Well that does not disable proxy buffering! 好吧,这不会禁用代理缓冲! Rather that is whether nginx will buffer up to the whole response (to the buffer pool or disk) while sending it to the browser, or whether it will buffer only what fits in the the buffer pool. 而是在将nginx发送到浏览器时是否将其缓冲到整个响应(缓冲池或磁盘),还是仅缓冲缓冲池中的缓冲区。 So even if you turn off proxy_buffering proxy buffering still happens. 因此,即使off proxy_buffering代理缓冲仍然会发生。

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size http://nginx.org/zh-CN/docs/http/ngx_http_proxy_module.html#proxy_buffer_size

Maximum on http header values? http标头值的最大值?

I saw a bunch of recommendation for setting large buffer pools, eg big numbers like 8 x 512kb buffers (= 4MB). 我看到了一些建议,建议设置较大的缓冲池,例如8 x 512kb缓冲区(= 4MB)之类的大数字。 There is a buffer pool for each connection , so the smaller you keep the buffer pool, the more connections you can handle. 每个连接都有一个缓冲池,因此,保留的缓冲池越小,可以处理的连接就越多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM