【问题标题】:AWS ALB Truncating HTTP responseAWS ALB 截断 HTTP 响应
【发布时间】:2019-04-24 12:07:02
【问题描述】:

我有一个带有目标组的 ALB 和运行 PHP API 的 ECS 集群。

我正在尝试查询 API 以获取 CSV 响应,但如果请求来自 ALB,我会得到截断的结果。

当我通过 SSH 连接到运行集群的 EC2 实例并尝试手动运行 curl(通过负载均衡器)时,响应会被截断:

curl -sSL -D - 'https://my.domain.com/api/export?token=foobar&start_date=01-01-2015&end_date=01-01-2019' \
  -H 'Content-Type: application/json' \
  -H 'cache-control: no-cache' -o /dev/null

我得到了这些标题:

HTTP/2 200 
date: Wed, 21 Nov 2018 20:25:27 GMT
content-type: text/csv; charset=utf-8
content-length: 173019
server: nginx
content-transfer-encoding: binary
content-description: File Transfer
content-disposition: attachment;filename=export.csv
cache-control: private, must-revalidate
etag: "b90d0da7b482da96e1a478d59eedd0d16552fbfd"
strict-transport-security: max-age=2592000; includeSubDomains; preload
content-security-policy-report-only: default-src 'self';
x-frame-options: DENY
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
referrer-policy: origin

curl: (92) HTTP/2 stream 1 was not closed cleanly: INTERNAL_ERROR (err 2)

如果我尝试对容器运行相同的 curl(在本地运行 - 不是通过 ALB)

curl -sSL -D - 'http://localhost:32776/api/export?token=foobar&start_date=01-01-2015&end_date=01-01-2019' \
  -H 'Content-Type: application/json' \
  -H 'cache-control: no-cache' -o /dev/null

回复:

HTTP/1.1 200 OK
Server: nginx
Content-Type: text/csv; charset=utf-8
Content-Length: 173019
Connection: keep-alive
Content-Transfer-Encoding: binary
Content-Description: File Transfer
content-disposition: attachment;filename=export.csv
Cache-Control: private, must-revalidate
Date: Wed, 21 Nov 2018 20:36:55 GMT
ETag: "b90d0da7b482da96e1a478d59eedd0d16552fbfd"
Strict-Transport-Security: max-age=2592000; includeSubDomains; preload
Content-Security-Policy-Report-Only: default-src 'self;
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: origin

当我比较它们时,HTTP 版本有所不同。我尝试在 ALB 中切换到 HTTP1,但仍然遇到相同(或类似)的问题:curl: (18) transfer closed with 130451 bytes remaining to read

另一个区别是Keep-Alive 选项。我不确定这是否是我可以在 ALB 上启用的属性。

当我尝试返回不同的响应(复杂的网页/非常长)时,响应通过 ALB 没有问题(未截断)。根据 ALB 启用 HTTP/1.1 时的错误消息,每次 42568 字节后都会截断响应。

有什么想法吗?

更新

如果我在响应中省略了 Content-Type 标头,它不会被截断。

return new Response($content, Response::HTTP_OK, [
    # Works without this:
    # 'Content-Type' => 'text/csv; charset=utf-8',
    'Content-Transfer-Encoding' => 'binary',
    'Content-Description' => 'File Transfer',
    'Content-Disposition' => "attachment;filename=export.csv",
    'Content-Length' => strlen($content),  
]);

更新 2

将响应 Content-Type 更改为 text/html 会正确返回响应。

【问题讨论】:

    标签: amazon-web-services http amazon-elb


    【解决方案1】:

    您应该在您的 EC2 实例上启用 keep-alive。

    您可以在您的 EC2 的 Web 服务器设置中启用 HTTP keep-alive 实例。 https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#connection-idle-timeout

    还要仔细检查 Content-Length 标头是否准确。此处的尺寸不正确会导致您看到的错误。

    【讨论】:

    • 具体在哪里?负载均衡器的超时设置为120 seconds。您是指运行集群的 ECS EC2 实例吗?容器中的 Web 服务器也启用了 Keep-Alive 选项。
    • 抱歉,错过了 ECS 位。如果您在 Web 服务器上设置了 keep-alive 应该没问题。不知道为什么它被剥离了。您是否还有其他东西,例如防火墙或可以拦截 HTTP 的东西?
    • 我不这么认为,我原来的问题有更新,也许有帮助?
    【解决方案2】:

    所以经过一些愉快的调试后,我在容器的 Nginx 日志中发现了这个:

    nginx stderr | 2018/11/22 01:03:59 [warn] 39#39: *65 an upstream response is 
    buffered to a temporary file /var/tmp/nginx/fastcgi/4/01/0000000014 while reading 
    upstream, client: 10.1.1.163, server: _, request: "GET /api/export?
    token=foobar&start_date=01-01-2015&end_date=01-01-2019 HTTP/1.1", upstream: 
    "fastcgi://unix:/var/run/php-fpm.sock:", host: "my.domain.com"
    

    这基本上可以通过将这两行烘焙到我的 nginx 配置中来解决:

    client_body_temp_path /tmp 1 2;
    fastcgi_temp_path /tmp 1 2;
    

    为什么只在csv 输出中发生这种情况仍然是个谜。

    感谢您的帮助!

    【讨论】:

      猜你喜欢
      • 2013-03-02
      • 2023-03-29
      • 1970-01-01
      • 2015-12-13
      • 1970-01-01
      • 2017-05-26
      • 2018-10-11
      • 2015-04-27
      • 2014-05-15
      相关资源
      最近更新 更多