Perl 如何知道PSGI非阻塞流式写入程序何时准备好以PSGI兼容的方式接收更多数据?

Perl 如何知道PSGI非阻塞流式写入程序何时准备好以PSGI兼容的方式接收更多数据?,perl,psgi,Perl,Psgi,我正在编写一个PSGI中间件,目前正在Twiggy服务器上运行。中间件处理大型(>2GB)动态创建的文件,并利用Twiggy/AnyEvent的异步流能力 关于流式响应,报告非常简短地说: 。。。响应者必须返回另一个实现write和close方法的对象 通过挖掘Twiggy代码,它使用AnyEvent::Handle::push_write实现上述write方法。但是,如果您继续以比写入网络更快的速度向其提供大量数据,这将消耗您所有的RAM 当然,AnyEvent::Handle有方法并使用回调

我正在编写一个PSGI中间件,目前正在Twiggy服务器上运行。中间件处理大型(>2GB)动态创建的文件,并利用Twiggy/AnyEvent的异步流能力

关于流式响应,报告非常简短地说:

。。。响应者必须返回另一个实现
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。