Fra*_*ozo 9 perl plack uwsgi psgi
我正在使用Perl模块的一部分创建一个大型CSV响应.服务器运行在Plack上,我远非专家.
目前我正在使用这样的东西发送回复:
$res->content_type('text/csv');
my $body = '';
query_data (
parameters => \%query_parameters,
callback => sub {
my $row_object = shift;
$body .= $row_object->to_csv;
},
);
$res->body($body);
return $res->finalize;
Run Code Online (Sandbox Code Playgroud)
但是,该query_data函数不是一个快速的函数,并检索大量的记录.在那里,我只是将每一行连接进去,$body并且在处理完所有行之后,发送整个响应.
我不喜欢这两个原因:首先,它需要大量的RAM才能$body被破坏.其次,在该方法完成工作并实际发送响应之前,用户看不到任何响应活动$res->body($body).
我试图在文档中找到答案,但没有找到我需要的东西.
我也试过调用$res->body($row_object->to_csv)我的回调部分,但似乎最终只发送了我做的最后一次调用$res->body,覆盖了所有以前的调用.
有没有办法发送Plack响应来刷新每行的内容,因此用户在收集数据时实时开始接收内容,而不必将所有数据累积到可靠的第一个?
提前感谢您的任何意见!
您不能使用Plack::Response,因为该类旨在表示完整的响应,并且您永远不会在内存中同时拥有完整的响应。您尝试做的事情称为流式传输,即使 Plack::Response 不支持, PSGI 也支持它。
以下是您可以如何实现它(改编自您的示例代码):
my $env = shift;
if (!$env->{'psgi.streaming'}) {
# do something else...
}
# Immediately start the response and stream the content.
return sub {
my $responder = shift;
my $writer = $responder->([200, ['Content-Type' => 'text/csv']]);
query_data(
parameters => \%query_parameters,
callback => sub {
my $row_object = shift;
$writer->write($row_object->to_csv);
# TODO: Need to call $writer->close() when there is no more data.
},
);
};
Run Code Online (Sandbox Code Playgroud)
关于这段代码的一些有趣的事情:
Plack::Response您可以返回一个 ,而不是返回一个对象sub。该子例程将在一段时间后被调用以获得实际响应。PSGI 支持这一点以允许所谓的“延迟”响应。coderef(在本例中为)。$responder如果真实响应不包含“主体”(即通常是 的第三个元素)arrayref,则将$responder返回一个我们可以将主体写入其中的对象。PSGI 支持此功能以允许流式响应。$writer对象有两个方法,write它们close的作用正如它们的名字所暗示的那样。不要忘记调用该close方法来完成响应;上面的代码没有显示这一点,因为它的调用方式取决于query_data您的其他代码的工作方式。$env->{'psgi.streaming'}以确保您的确实如此。| 归档时间: |
|
| 查看次数: |
387 次 |
| 最近记录: |