Apache2和CGI - 如何防止Apache缓冲POST数据?

6

我正在尝试对CGI文件上传提供实时解析并将数据显示在屏幕上,但是Apache2似乎希望在向CGI应用程序发送任何内容之前等待完整的POST请求。

如何强制Apache2停止缓冲传输到我的CGI应用程序的POST请求?

编辑

实际上是CGI的输出被缓冲了。我开始将数据流式传输到临时文件以观察其进度。除此之外,我还有另一个问题。

1)输出被缓冲了。我尝试使用SetEnvIf(和仅使用SetEnv)来定义“!nogzip”,“nogzip”和“!gzip”(在CGI目录中),但没有成功。

2)Apache2似乎直到CGI进程退出才读取CGI的输出?我注意到我的CGI应用程序(无论是否刷新)在大约80K处永久卡住在“fwrite(...,stdout)”行。

编辑

好的,Firefox搞砸了。如果我发送一个150K的文件,那么在80K左右就不会出现CGI锁定。如果文件是2G,则会锁定。因此,Firefox在尝试发送文件时未读取服务器的输出...是否有任何头或备用内容类型可以更改该行为?

编辑

好的,我想在大文件上进行CGI输出锁定实际上并不重要。我不需要回显文件!我正在调试由调试工具引起的问题。:)

我想这样就足够好了。谢谢!

最终注释

只是一条注释...我认为Apache2缓冲输入的原因是我总是得到一个“Content-Length”环境变量。我想Firefox足够聪明以预计算多部分表单上传的内容长度,并且Apache2已将其传递。我以为Apache2正在缓冲输入并自己报告长度。

3个回答

4
你确定问题出在输入缓冲上吗?输出缓冲问题更为常见,如果你的调试方法只是像向响应中打印一样,可能无法区分它们是否来自输入缓冲。
(通常情况下,输出缓冲由未刷新的脚本中的stdout或过滤器引起。通常罪魁祸首是DEFLATE过滤器,它经常用于压缩所有text/响应,无论它们来自静态文件还是脚本。一般来说,压缩脚本的输出是个好主意,但副作用是会导致响应完全缓冲。如果你需要立即响应,你需要关闭它,对于那个脚本或所有脚本,通过将AddOutputFilterByType的应用限制到特定的或使用mod_setenvif设置!nogzip注释。)
同样,如果你正在使用任何输入过滤器(包括DEFLATE),它可能会导致CGI输入被缓冲。但它们的使用范围较小。
编辑:现在,只需注释掉启用deflate过滤器的任何httpd配置。一旦你确信IO没有缓冲,可以有选择性地将其放回去。
我注意到我的CGI应用程序(无论是否刷新)在大约80K的"fwrite(..., stdout)"行上永久挂起。
是的...如果你没有读取所有输入,当尝试写输出时,如果写入太多,就会发生死锁。你可能会在输出调用上阻塞,等待网络缓冲区清除,以便发送新数据,但它们将永远不会清除,因为浏览器正在尝试在开始读取输出之前发送所有数据。
你在这里做什么?一般来说,对于直接表单POST,编写进度信息输出是没有意义的,因为浏览器通常不会显示它。如果你想在普通HTML表单提交中提供上传进度反馈,通常使用诸如通过AJAX连接回传来查看上传进度(这意味着必须共享进度信息,例如在数据库中)或使用Flash上传组件等黑科技。

我尝试了!nogzip命令,但没有太大的成功。如上所述,我现在还有一个标准输出问题。 - darron
既然最终问题是输出问题,而DEFLATE信息非常有用,我将其标记为答案。 - darron
是的,输出并不是必要的。我为了调试而启用了它,这让我有点困扰。整个计划一直都是为了实现 AJAX 反馈。实际上,我将尝试解析并显示文件随时传输的内容...应该会很酷。虽然微小,但很棒。 - darron

0

来自(旧版)Apache HTTP服务器手册:

每次您的脚本执行“flush”以输出数据时,该数据都会被中继到客户端。一些脚本语言(例如Perl)具有自己的输出缓冲区 - 可以通过将$|特殊变量设置为1来禁用它。当然,这会增加传输的数据包总数,这可能会导致最终用户感觉速度较慢。

您是否尝试过刷新STDOUT或检查您使用的语言是否具有可禁用的缓冲区?


是的,我正在每8K间隔刷新STDOUT...但似乎没有任何效果。 - darron

0

这是一个有用的指南,用于在服务器端使用Perl时控制缓冲:

http://perl.plover.com/FAQs/Buffering.html

许多思想和概念也适用于其他编程语言,例如使用缓冲输出和非缓冲输出、原始系统调用来读取和写入数据与自己缓存的 I/O 库。


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