【问题标题】:unable to do progressive rendering无法进行渐进式渲染
【发布时间】:2016-12-31 03:13:41
【问题描述】:

几年前,我在以前的工作中编写了依赖渐进式渲染的 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" ;

【问题讨论】:

  • 尝试添加Transfer-Encoding: chunked developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
  • 谢谢。但是,它对我不起作用。我尝试了我在stackoverflow.com/questions/17153009/… 中发现的一种变体,在两个块之间休眠,并且禁用了 STDOUT 缓冲,它仍然等到整个文档被接收到。
  • 事情很不对劲。文档说长度是十六进制,它只适用于十六进制,直到当十六进制长度从适用于 25 字节字符串的 19 变为 1a(或 1A)时,你得到一个 26 字节的字符串。然后它会使用“ERR_INVALID_CHUNKED_ENCODING”来解决问题。叹息。

标签: html perl progressive


【解决方案1】:

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

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

只发送无关紧要的内容,比如一堆空格:

print " " x 1024 * 8;

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

当然,您也可以只禁用服务器中的缓冲。你如何做到这一点取决于网络服务器。对于nginx,请看X-Accel-Buffering

【讨论】:

  • 不是这样,但它让我找到了问题所在,我在后续回答中对此进行了详细说明。所以我会感谢你的解决方案。谢谢!!
【解决方案2】:

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

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

我从Prevent output buffering with PHP and Apache找到的

在尝试@ccm 的建议时,似乎缓冲区大小为 1K,这对我来说很好。

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

【讨论】:

    【解决方案3】:

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

    您已经使用$_ 关闭了缓冲,这很好。您无法从脚本中获得更多控制权。即使您想要进行分块传输,连接也需要保持打开状态,这在您的示例中并不是真正需要的。

    是服务器在一段时间后将其关闭。一旦连接断开,网络服务器就不会通过线路发送您的剩余响应,因为该连接已经断开并且 CGI 句柄已分离,因此没有任何内容会读取您的输出来传递它。

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

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

    【讨论】:

    • 谢谢,但我已经知道 Apache 超时,在这种情况下它们不相关。这个例子应该是几秒钟。我用于说明的示例最多为 10 秒,我使用的睡眠时间是为了见证立即渲染是否正常工作。连接保持打开状态 - 它会等到整个文档完成后再显示任何内容。我过去写过 CGI 脚本,Apache 超时设置为 5 分钟或更长时间,一切都很好,我有渐进式渲染。有些事情发生了变化,我不知道是什么。
    猜你喜欢
    • 2019-09-27
    • 2020-02-11
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2018-11-02
    • 2019-09-06
    • 1970-01-01
    • 2018-05-15
    相关资源
    最近更新 更多