无法进行渐进式渲染

时间:2016-12-31 03:13:42

标签: html perl progressive

多年前,我在先前依赖渐进式渲染的工作中编写了CGI程序,因为这些CGI程序可能需要很长时间(分钟)才能运行,每秒产生一行输出。我发现今天,即使用最简单的例子,我也无法进行渐进式渲染。

我已经看到很多关于这个主题的建议,关于在哪里放置CSS,脚本等等。但是,下面这个简单的例子没有。

我没有看到浏览器可以选择影响渐进式渲染的任何地方。我已经在几个具有多个浏览器(chrome,firefox,opera)的系统/设备上尝试了这一点,所有这些都具有相同的结果。

下面是一个简单的例子,我希望每2秒产生一些输出,但它会在整个文档完成时呈现。 我错过了一些明显的东西吗?

#!/usr/bin/env perl

select(STDOUT); $| = 1;     # don't buffer stdout

print "Content-Type: text/html\; charset=ISO-8859-1\n\n" ;
print "<html> <head> <title> Testing </title> </head> <body>\n" ;

my $message = "<code>" .
    "Why doesn't this render immediately? <br>\n" x 5 .
    "</code>\n" ;

for ( my $i=0 ; $i < 5 ; $i++ ) {
    print "$message\n" ;
    sleep(2) ;
}
print "</body></html>\n" ;

3 个答案:

答案 0 :(得分:2)

您的网络服务器可能正在缓冲响应。 $| = 1;设置STDOUT每次print时自动刷新,消除脚本中缓冲的影响,但您还需要考虑缓冲正在发生的事情在您的网络服务器

没有命令或字符序列来刷新缓冲区,但你可以简单地发送足够数量的数据来填充缓冲区,以便它自己刷新。

只需发送无关紧要的内容,就像一堆空格:

print " " x 1024 * 8;

需要发送多少数据取决于配置在Web服务器中的缓冲区大小。典型的缓冲区大小为4KiB或8KiB,但请注意,如果您的服务器gzips脚本的响应,那么您将需要打印更多(可能大约8MiB的空格字符),以填充服务器的缓冲区,因为缓冲区将填充压缩响应。

当然,您也可以在服务器中禁用缓冲。如何执行此操作取决于Web服务器。对于nginx,请查看X-Accel-Buffering

答案 1 :(得分:1)

来自ccm的回复对我来说不起作用,但它让我找到了解决问题的正确方法。解决方案是将以下内容添加到我的Apache配置中:

SetEnvIfNoCase Request_URI \.cgi$ no-gzip dont-vary

我从Prevent output buffering with PHP and Apache

找到的

在尝试@ccm建议时,看起来缓冲区大小为1K,这对我来说没问题。

非常感谢@ccm让我走上了正确的道路!

答案 2 :(得分:0)

您还需要您的网络服务器来保持CGI脚本运行足够长的时间。默认Apache有1分钟timeout

您已使用$_关闭缓存,这很好。脚本没有更多的控制权。连接需要保持打开状态,即使您想要进行分组传输,在您的示例中并不是真的需要。

服务器在一段时间后将其关闭。一旦连接消失,网络服务器就不会通过线路发送你的响应的剩余部分,因为连接已经消失并且CGI句柄被分离,所以没有任何东西正在读取你的输出以传递它。

结论:将超时设置为更高的值。

轶事:我曾经在一个超时设置大约一个小时的系统上工作,其中一个基于CGI的后台应用程序在一个庞大的MySQL数据库上进行大量的数据库查询,并且需要很长时间。使用该工具的人通常会开始使用咖啡或吃午饭。