Perl 如何知道PSGI非阻塞流式写入程序何时准备好以PSGI兼容的方式接收更多数据?
我正在编写一个PSGI中间件,目前正在Twiggy服务器上运行。中间件处理大型(>2GB)动态创建的文件,并利用Twiggy/AnyEvent的异步流能力 关于流式响应,报告非常简短地说: 。。。响应者必须返回另一个实现Perl 如何知道PSGI非阻塞流式写入程序何时准备好以PSGI兼容的方式接收更多数据?,perl,psgi,Perl,Psgi,我正在编写一个PSGI中间件,目前正在Twiggy服务器上运行。中间件处理大型(>2GB)动态创建的文件,并利用Twiggy/AnyEvent的异步流能力 关于流式响应,报告非常简短地说: 。。。响应者必须返回另一个实现write和close方法的对象 通过挖掘Twiggy代码,它使用AnyEvent::Handle::push_write实现上述write方法。但是,如果您继续以比写入网络更快的速度向其提供大量数据,这将消耗您所有的RAM 当然,AnyEvent::Handle有方法并使用回调
write
和close
方法的对象
通过挖掘Twiggy代码,它使用AnyEvent::Handle::push_write
实现上述write
方法。但是,如果您继续以比写入网络更快的速度向其提供大量数据,这将消耗您所有的RAM
当然,AnyEvent::Handle
有方法并使用回调来处理缓冲区大小(即on_drain
事件处理程序指示写入缓冲区何时为空,以及wbuf_max
限制写入缓冲区大小)
但是,使用这些功能将非常特定于服务器,并限制PSGI应用程序的可移植性。PSGI规范似乎没有涵盖用于控制/监视异步写入流或访问底层文件句柄/描述符以进行手动检查的API
其他人如何解决内存使用/缓冲问题,或者如何知道异步写入何时以跨PSGI web服务器“兼容”的方式完成?任何建议都会很好。作为后续,我想我会发布一个关于我如何解决问题的简化版本,以防对其他人有所帮助 使用
writer
中使用的AnyEvent::handle
中的{handle}
元素,我手动设置on\u drain
和on\u error
的回调
写入缓冲区为空时,将调用U漏极上的
。因此,处理程序使我的数据生成代码能够继续生成数据
调用数据生成回调时,将数据写入响应,并禁用/暂停数据生成
当排水管上的处理程序再次启用数据生成时,循环继续
这样可以检查编写器的内存使用情况,现在使用最小内存来处理较大的流式响应。我似乎仍然有一些缓慢泄漏的内存问题,但这可能是深层次的,因为我的代码在别处
sub call {
my ($self,$env)=@_;
#URL/path matching here
my $myASYNCObject; #Complicated async object setup
my $onDrain= sub { #on_drain handler
$myAsyncObject->continue; #tell generation code to continue
};
return sub {
#Boilerplate for streaming response
my $responder=shift;
my $resCode=200;
my $resHeaders=[...];
my $writer=$responder->([$resCode,$resHeaders]);
#Setup callback and start data generation
$myAsyncObject->setCallback=sub{
my $myData=shift;
$writer->write->($myData); #Write the data
$myAsyncObject->pause; #Tell generation code to pause
};
$writer->{handle}->on_drain( #Setup on_drain handler
sub {
$myAsyncObject->continue; #tell generation code to continue
}
);
#Error handlers here...
}
}
FWIW,其他Plack服务器通常只syswrite
将数据直接写入套接字,而不进行缓冲和可能的阻塞,因此它们不会遇到此类问题。这可能是Twiggy中的一个bug。