题 http请求的gzipping不正确,无法找到谁在做


我们看到一些非常奇怪的HTTP响应,我们无法弄清楚是做什么的。我们有一个处理JSON请求的应用服务器。有时,响应会被gzip压缩,但使用不正确的标头会阻止浏览器正确解释它。

问题是间歇性的,并随着时间的推移而改变行为。昨天早上它似乎在50%的时间内失败,事实上,似乎与我们的两个负载均衡服务器之一相关。在下午晚些时候,它在1000次中仅失败了20次,并且与应用服务器无关。

两个app服务器运行带有mod_wsgi和Django应用程序堆栈的Apache 2.2。它们具有相同的Apache配置和源代码树,甚至安装在Red Hat上的相同软件包。前面有一个硬件负载平衡器,我不知道品牌或型号。

Akamai也是食物链的一部分,虽然我们删除了Akamai但仍然存在问题。

这是一个很好的请求和响应:

* Connected to example.com (97.7.79.129) port 80 (#0)
> POST /claim/ HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: example.com
> Accept: */*
> Referer: http://example.com/apps/
> Accept-Encoding: gzip,deflate
> Content-Length: 29
> Content-Type: application/x-www-form-urlencoded
> 
} [data not shown]
< HTTP/1.1 200 OK
< Server: Apache/2
< Content-Language: en-us
< Content-Encoding: identity
< Content-Length: 47
< Content-Type: application/x-javascript
< Connection: keep-alive
< Vary: Accept-Encoding
< 
{ [data not shown]
* Connection #0 to host example.com left intact
* Closing connection #0
{"msg": "", "status": "OK", "printer_name": ""}

这是一个糟糕的:

* Connected to example.com (97.7.79.129) port 80 (#0)
> POST /claim/ HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: example.com
> Accept: */*
> Referer: http://example.com/apps/
> Accept-Encoding: gzip,deflate
> Content-Length: 29
> Content-Type: application/x-www-form-urlencoded
> 
} [data not shown]
< HTTP/1.1 200 OK
< Server: Apache/2
< Content-Language: en-us
< Content-Encoding: identity
< Content-Type: application/x-javascript
< Content-Encoding: gzip
< Content-Length: 59
< Connection: keep-alive
< Vary: Accept-Encoding
< X-N: S
< 
{ [data not shown]
* Connection #0 to host example.com left intact
* Closing connection #0
�V�-NW�RPR�QP*.I,)-���A���̼�Ԣ����T��Z�
��/

关于不良反应有两点需要注意:

  1. 它有两个Content-Encoding标头,浏览器似乎使用第一个。因此,他们看到了标识编码标头和gzip压缩内容,因此无法解释响应。

  2. 错误的响应有一个额外的“X-N:S”标题。

也许如果我能找出中间人将“X-N:S”标题添加到回复中,我可以追查罪魁祸首......


5
2018-04-17 14:26




哪个确切版本的Apache和mod_wsgi?是否使用完全相同的版本?它们是最新版本还是旧版本? - Graham Dumpleton
它们是每台机器上完全相同的版本(整个软件包的数量完全相同)。 - Ned Batchelder
Ned最终找到了“X-N:S”响应头的来源。看他的 博客文章 详情。 - ulty4life


答案:


一些额外的线索

根据 http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5

  • 身分 默认(身份) 编码;使用没有 无论如何转变。这个 内容编码仅用于 Accept- Encoding标头,应该是 不能在Content-Encoding中使用 头。

Akamai似乎忽略了这样一个事实,即服务器可以在响应中包含此标头,并且在将编码更改为“gzip”时不会将其删除。

由于上游服务器“应该”不首先添加标头,这是解决此问题的另一种方法。


3
2018-04-21 18:31



我们得到了Akamai的确认,他们正在抓取响应并添加“Content-Encoding:gzip”而不先删除现有的Content-Encoding。我们在代码中确定了添加标识标头的位置,并将其删除。仍然没有关于“X-N:S”的意思! :) - Ned Batchelder
X-N: community.akamai.com/community/web-performance/blog/2016/05/24/...。 “当响应标头具有一定长度时,添加此标头以容纳Netscape中的错误。如果标头的终止\ r \ n \ n开始于字符256,257或258,则Netscape 用过的 显示损坏的图像。 Akamai通过用X-N填充标题来解决这个问题:S。“ - Jason Martin


你的架构是什么样的?

请求路径中的任何反向代理?在apache中加载了哪些模块? apache配置是什么样的?如果你禁用mod_deflate,它仍然会发生吗?是一个PHP脚本处理你的json输出使用ob_start并处理自己的压缩?


0
2018-04-17 16:18





我怀疑在负载平衡器上缓存。尝试在响应中添加反缓存标头,并查看问题是否仍然存在。这可能会增加您的服务器负载。


0
2018-04-17 23:36



这些是JSON帖子,所以我不希望有任何缓存。从Apache日志来看,没有证据表明某些内容正在缓存。 - Ned Batchelder