首页 文章

Kubernetes nginx ingress控制器返回502但仅适用于AJAX / XmlHttpRequest请求

提问于
浏览
0

我有一个在nginx入口控制器后面运行Kubernetes的Web应用程序,它适用于请求浏览,但是来自浏览器的任何AJAX / XMLHTTPRequest都会从nginx获得502错误 .

我捕获了常规和AJAX请求的HTTP标头,它们看起来很好,正确的主机标头,协议等等 . 我很困惑为什么只有XMLHttpRequest请求从nginx获取502 . 没有延迟/挂起,502是立即的 . 请求似乎永远不会到达应用程序,但被nginx本身拒绝 . 将nginx切换为直接负载均衡器,问题就消失了 .

我要进一步挖掘,但我想知道是否有其他人使用nginx入口控制器之前看到过这个问题并解决了它?

我从nginx日志中选择了这个错误,这表明容器返回一个响应,其中一个nginx缓冲区的标头太大 . 但是我检查了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"

奇怪的是,只有当XmlHttpRequest请求URL时才会出现504错误 . 如果我使用curl请求相同的URL它工作正常,响应标头如下所示 . 那个相同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

1 回答

  • 1

    我解决了这个问题 . 只有XmlHttpRequests失败的原因是因为应用程序在看到XmlHttpRequest请求时有一个特殊的行为,它将大约3000字节的额外标头转储到响应中 . 这使得总标头大小大于默认的nginx标头缓冲区 .

    大型HTTP头有效负载上的nginx chocking很常见,因为它的默认缓冲区大小比大多数其他Web服务器小,只有4k或8k . 错误的解决方案是通过添加这些设置将用于标头的缓冲区增加到16k .

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

    nginx文档非常模糊,这些设置含糊不清 . 据我所知,每个连接都有一个缓冲池 . 在这种情况下,每个16k的8个缓冲区 . 这些缓冲区用于从上游Web服务器接收数据并将数据传递回客户端 .

    所以 proxy_buffers 确定了游泳池 . 然后 proxy_buffer_size 确定主机的大部分缓冲池可用于从上游服务器接收HTTP头(我认为四舍五入到整个缓冲区大小) . 第三个设置 proxy_busy_buffer_size 确定缓冲池可以忙于发送到客户端的数量(我认为四舍五入到整个缓冲区大小) . 默认情况下, proxy_busy_buffer_size 会自动设置为池中缓冲区数减1 .

    所以 proxy_buffers 池必须足够大以适应 proxy_busy_buffer_size 并且仍然有足够的缓冲区以至少适合来自上游Web服务器的HTTP头的 proxy_buffer_size .

    净值是,如果你增加 proxy_busy_buffer_size ,你可能会立即得到令人困惑的错误: "proxy_busy_buffers_size" must be less than the size of all "proxy_buffers" minus one buffer ,然后你必须增加池的大小 .

    你问的 proxy_buffering off 设置?好吧,这不会禁用代理缓冲!而是nginx是否会在将其发送到浏览器时缓冲到整个响应(缓冲池或磁盘),或者它是否只缓冲适合缓冲池的内容 . 所以即使你转向 off proxy_buffering 代理缓冲仍然会发生 .

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

    Maximum on http header values?

    我看到了一堆关于设置大型缓冲池的建议,例如:大数字,如8 x 512kb缓冲区(= 4MB) . 每个连接都有一个缓冲池,因此保留缓冲池越小,您可以处理的连接越多 .

相关问题