随机出现的gzip头部信息

13

我在共享主机环境中运行了一个长时间的脚本,输出一堆XML。

有时候(只有偶尔),我的输出中会出现随机的GZIP头,然后输出会被终止。

例如:

0000000: 3c44 4553 435f 4c4f 4e47 3e3c 215b 4344  <DESC_LONG><![CD
0000010: 4154 415b 1fc2 8b08 0000 0000 0000 03c3  ATA[............
0000020: b3c3 8b57 c388 c38c 2b28 2d51 48c3 8bc3  ...W....+(-QH...
0000030: 8c49 5528 2e48 4dc3 8e4c c38b 4c4d c391  .IU(.HM..L..LM..
0000040: c3a3 0200 c291 4464 c383 1900 0000 0d0a  ......Dd........

或者
0000000: 3c2f 5052 4f44 5543 543e 0d0a 1fc2 8b08  </PRODUCT>......
0000010: 0000 0000 0000 03c3 b3c3 8b57 c388 c38c  ...........W....
0000020: 2b28 2d51 48c3 8bc3 8c49 5528 2e48 4dc3  +(-QH....IU(.HM.
0000030: 8e4c c38b 4c4d c391 c3a3 0200 c291 4464  .L..LM........Dd
0000040: c383 1900 0000 0d0a                      ........

或者

0000000: 3c4d 4544 4941 5f55 524c 3e2f 696d 6167  <MEDIA_URL>/imag
0000010: 6573 2f69 6d70 6f72 7465 642f 7374 6f63  es/imported/stoc
0000020: 6b5f 7072 6f64 3235 3339 365f 696d 6167  k_prod25396_imag
0000030: 655f 3531 3737 3439 3436 302e 6a70 673c  e_517749460.jpg<
0000040: 2f4d 4544 4941 5f55 1fc2 8b08 0000 0000  /MEDIA_U........
0000050: 0000 03c3 b3c3 8b57 c388 c38c 2b28 2d51  .......W....+(-Q
0000060: 48c3 8bc3 8c49 5528 2e48 4dc3 8e4c c38b  H....IU(.HM..L..
0000070: 4c4d c391 c3a3 0200 c291 4464 c383 1900  LM........Dd....
0000080: 0000 0d0a                                ....

转换为GZIP似乎没有特定的时间或字节计数,可以在传输1MB或15MB数据后进行切换。

相应行处编译的刀片模板如下:

<DESC_LONG><![CDATA[<?php echo $product->display_name; ?>]]></DESC_LONG>

-

</PRICES>
</PRODUCT>
<?php foreach($product->models()->get() as $model): ?>

-

<MEDIA_URL>/images/imported/<?php echo $picture->local_name; ?></MEDIA_URL>

我快被逼疯了,我试过以下方法:
  • 在服务器上禁用gzip。
  • 运行脚本前执行while(ob_get_level()){ ob_end_clean(); }
  • .htaccess文件中尝试使用SetEnv no-gzip 1SetEnv no-gzip dont-vary等各种排列组合方式。
当我访问其他页面时,没有gzip编码或头出现,所以我认为这可能与输出大小或输出缓冲有关。

当在我的本地机器上运行时,该脚本完美运作。 - Kristoffer Sall-Storgaard
1
能否提供更大的虚假输出样本,从1fc2 8b08字节开始? - Álvaro González
1
系统的输出在0000 0d0a之后终止。 - Kristoffer Sall-Storgaard
1
随机出现的标题让人觉得好像是另一个请求或进程造成的...太糟糕了,因为你在共享主机上,这使得隔离和调试这样的问题变得相当困难。 - AD7six
这能联系起来吗?:https://dev59.com/XW855IYBdhLWcg3wUSkW - Gustavo Rubio
显示剩余11条评论
3个回答

1

这更像是一系列评论,但它太长了,无法放在评论框中。

首先,很可能不是输出缓冲区问题。即使<![CDATA[]]>不在PHP标记内,这并不意味着它不会通过PHP的输出缓冲区。明确地说,任何在.php文件中的内容都将被放置在PHP输出缓冲区中。.php文件中的内容(包括静态内容)在Apache之外进行缓冲,然后在脚本完成时通过此缓冲区返回给Apache。这意味着您的问题必须存在于代码本身中,而没有查看代码就解决问题就像瞎子摸象一样难以实现。

我的建议:

1)在脚本中搜索任何gz函数的实例(gzcompress,gzdeflate,gzdecode等)。我曾经看到过脚本在内容大于特定大小时压缩内容,然后在从数据库中获取内容时动态解压缩内容。如果是这种情况,您可能正在处理一个错误的比较操作。简而言之,压缩和解压缩条件中的逻辑略有偏差,因此未能解压缩部分内容。

2) 在脚本中进行搜索,查看如何获取这些数据。它们全部来自数据库吗?有没有从流中获取的?有没有远程获取的?这些问题可能不直接导致答案,但非常重要。可以安全地假定这些变量已经使用压缩后的数据进行设置,而不应该这样。需要知道压缩发生的位置/原因/方式,才能回答为什么没有解压。

3) 它在一个系统上按预期工作,但在另一个系统上却很重要。我见过这种情况发生的唯一原因是配置不同。您的本地机器使用哪个操作系统?本地数据库有什么不同(如果有),有哪些扩展程序可能在其中一个或两个机器上缺失/存在,可能会导致函数在两个不同的机器上采用不同的过程。

编辑: 此外,虽然概率很小,但您处理的数据是否源自不同服务器的SQL转储?您说它在本地主机上运行正常,但在另一台主机上却不能运行,因此我们知道您正在处理两台机器。曾经有第三台机器吗?如果是这样,它可能已经使用不匹配的版本/格式进行了压缩,或者可能存在编码问题。


1

你最终找到了这些标头来自哪里吗?我的意思是apache还是php?

你可以使用类似以下的方式模拟xml生成器脚本:

echo file_get_contents('your_good_test.xml');

如果您没有看到任何标题,我建议您调试您的XML生成器。您可以尝试在输出之前调用header_remove();
如果您看到标题,您需要调试您的Web服务器。尝试通过重写规则禁用Apache中的gzip:
`RewriteRule . - [E=no-gzip:1]`

无论您使用哪种代理或负载均衡器(nginx、squid、haproxy),都会自动获得一条额外的请求线路。

1
您的gzip压缩与返回主xml正文的服务器输出无关。否则整个xml将被压缩。
这些方法有时会返回GZIP,因为获取项目的源设置为支持gzip,并且未正确请求。
$product->display_name
$product->models()->get()
$picture->local_name

请查看以下内容: - 检查设置头文件的所有Web调用。 - 如果有,请暂时禁用数据库连接的压缩。

为可能返回二进制数据的所有位置添加CDATA标记,以避免主XML正文构建终止。等待带有bin数据的XML,保存bin数据,解压并查看其中内容。 :-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接