我在共享托管环境中有一个长时间运行的脚本,它输出一堆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>
我在我的智慧结束时,我尝试了以下内容:
while(ob_get_level()){ ob_end_clean(); }
.htaccess
中,我尝试了SetEnv no-gzip 1
,SetEnv no-gzip dont-vary
及其各种排列。当我访问其他页面时,没有出现gzip编码或标题,所以我认为这是输出大小或输出缓冲区。
答案 0 :(得分:1)
您是否最终找到了这些标头的来源?我的意思是apache或php?
您可以使用以下内容模拟xml生成器scipt:
echo file_get_contents('your_good_test.xml');
如果你看不到任何标题,我建议调试你的xml生成器。您可以尝试在输出前调用header_remove();
。
如果看到标题,则必须调试Web服务器。尝试通过重写规则禁用apache中的gzip:
`RewriteRule . - [E=no-gzip:1]`
每当你有任何代理或平衡器(nginx,squid,haproxy)时,你会自动再获得一条射击线。
答案 1 :(得分:1)
你的gziping与返回主xml主体的服务器输出无关。否则整个xml将被压缩。
这些方法有时会返回GZIP,因为这些方法的来源设置为支持gzip并且没有正确询问。
$product->display_name
$product->models()->get()
$picture->local_name
查看这些内容。 - 检查所有设置标题的地方的网络电话。 - 暂时禁用数据库连接的压缩(如果有)。
为可以返回二进制数据的所有位置添加CDATA标记,以避免主xml正文构建终止。等待带有bin数据的xml,保存bin数据,解压缩并查看内部数据。 : - )
答案 2 :(得分:1)
这是一组评论,但评论框太长了。
首先,这很可能不是输出缓冲区问题。尽管<![CDATA[
和]]>
不在PHP标记内,但这并不意味着它不会通过PHP的输出缓冲区。要清楚,.php文件中的任何内容都将放在PHP输出缓冲区中。 .php文件中的内容(包括静态内容)在Apache之外缓存,然后在脚本完成时通过此缓冲区传递回Apache。这意味着您的问题必须存在于代码本身内,这是一个无需查看代码即可解决的问题。
我的建议:
1)在脚本中进行搜索以查找gz函数的任何实例(gzcompress,gzdeflate,gzdecode等)。我已经看到脚本压缩内容(如果它大于特定大小),然后在从数据库中取出时动态解压缩内容。如果是这种情况,您可能会处理错误的比较操作。简而言之,压缩和解压缩条件下的逻辑稍微偏离,因此无法解压缩某些内容。
2)在脚本中进行搜索,以查看如何获取此数据。这一切都来自数据库吗?它有没有来自流?是否有任何遥控器?这些问题可能不会直接导致答案,但至关重要。可以安全地假设这些变量是在不应该被压缩的数据的情况下设置的。它需要知道压缩发生的位置/原因/方式,以便回答为什么它没有被解压缩。
3)重要的是它在一个系统上按预期工作,而在另一个系统上工作。我见过这种情况的唯一时间总是由于配置的差异。您的本地计算机使用什么操作系统?本地数据库(如果有的话)有什么区别,哪些扩展可能会丢失/出现在另一个上,可能导致函数在两台不同的机器上回退到不同的过程。
编辑: 此外,这是一个小机会,但您是否正在处理来自不同服务器的SQL转储的数据?你说它可以在你的本地主机上运行,但不能在不同的主机上运行,所以我们知道你在处理两台机器。在某些时候有三分之一吗?如果是这样,它可能是使用不匹配的版本/压缩形式压缩的,或者可能是编码问题。