“search1”是AWS弹性搜索服务 . 它有一个访问策略,只允许来自所选IP地址的流量 . 我的理解是AWS在VPC面前将其实现为ELB,我无法访问 .

"esproxy"是AWS EC2实例,用作search1的代理 . 在esproxy上, nginx 配置为要求(https)基本身份验证,并且任何具有该身份验证的内容都会被代理到search1 .

有用 . 一段时间,几小时或一天 . 然后每个请求开始给出"504 Gateway Time-out"错误 . nginx 仍然立即响应以发出401 auth所需的错误,但是使用auth需要两分钟才能恢复超时 . 当发生这种情况并重新启动 nginx 时,这两方似乎都没有太多负载 . 实际上,通过代理的流量并不重,每天点击几千次 .

试图理解这个问题,我尝试使用 openssl ,如 telnet

openssl s_client -connect search1:443
[many ssl headers including certs shown rapidly]
GET / HTTP/1.1
Host: search1

HTTP/1.1 408 REQUEST_TIMEOUT
Content-Length:0
Connection: Close

这个408超时需要大约一分钟才能回到我身边 . Aha ,我想, this particular server is having issuses. 然后我尝试了另一台主机的 openssl 测试 . 同样的延迟 .

然后我想我自己, hey, curl works to test https, too, now that I know the ssl layer is snappy. 好吧, curl 访问工作,即使 nginxopenssl 同时从esproxy超时 .

所以我想, maybe something about the headers? curl has different headers than I'm typing into openssl.

我修改了一个低级别的http / https工具,让我轻松发送特定的 Headers . 我发现它似乎没有缺少或额外的 Headers ,但行结尾 . nginx (和 apache )不关心你是否使用DOS样式的行结尾(对HTTP规范正确)或Unix样式(不正确) . search1实例(弹性搜索本身或ELB)显然非常关心 .

在不了解 nginx 的情况下,我有以下几个问题:

  • 我的代理超时源是否是一堆现有的连接遇到了错误的请求行结尾?

  • 我该怎么说?

  • 可能不是因为超时不同(一到两分钟) .

  • 默认情况下 nginx 代理请求的行结尾是否正确?

  • 如果没有,可以强迫吗?

  • AND if the line endings is a red herring ,我怎么能得到 nginx 来帮助我解决这个问题?我在日志中看到的只是"upstream timed out (110: Connection timed out) while reading response header from upstream",这并没有提高我对该问题的理解 .

我在调试中发现了这个问题:nginx close upstream connection after request我已经修复了 nginx conf以使用1.1代理,如前所述 . 相关配置:

upstream search1 {
  server search1-abcdefghijklmnopqrstuvwxyz.us-east-1.es.amazonaws.com:443;

  # number of connections to keep alive, not time
  keepalive 64;
}

location / {
  proxy_set_header   X-Forwarded-For $remote_addr;
  proxy_set_header   Host "search1-abcdefghijklmnopqrstuvwxyz.us-east-1.es.amazonaws.com"
  # must supress auth header from being forwarded
  proxy_set_header   Authorization "";

  # allow keep-alives on proxied connections
  proxy_http_version 1.1;
  proxy_set_header Connection "";

  proxy_pass         https://search1;
}