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

如何解决如何知道 PSGI 非阻塞流编写器何时准备好以兼容 PSGI 的方式接收更多数据?

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

PSGI Specification 非常简短地说明了流式响应:

...响应者必须返回另一个实现 writeclose 方法的对象。 ...

挖掘 Twiggy 代码,它使用 AnyEvent::Handle::push_write 来实现上述 write 方法。如果您继续以比将数据写入网络的速度更快的速度向其提供大量数据,这将耗尽您所有的 RAM。

当然 AnyEvent::Handle 有方法并利用回调来处理缓冲区大小(即 on_drain 事件处理程序指示何时写入缓冲区为空,wbuf_max 以限制写入缓冲区大小)。

然而,使用这些功能将是特定于服务器的,并限制了 PSGI 应用程序的可移植性。 PSGI 规范似乎没有涵盖用于控制/监视异步写入流或访问底层文件句柄/描述符以进行手动检查的 API。

其他人如何以跨 PSGI Web 服务器“兼容”的方式解决内存使用/缓冲或知道异步写入何时完成?任何指针都会很棒。

解决方法

作为跟进,我想我会发布一个我如何解决我的问题的简化版本,以防它对其他人有所帮助。

使用 {handle} 中使用的 AnyEvent::Handle 中的 writer 元素,我手动设置了 on_drainon_error 的回调。

当写缓冲区为空时调用 on_drain。因此处理程序使我的数据生成代码能够继续生成数据。

当调用数据生成回调时,数据将写入响应并禁用/暂停数据生成。

on_drain 处理程序再次启用数据生成时,循环继续。

这可以控制 writer 的内存使用情况,现在使用最少的内存来处理大型流响应。我似乎仍然有一些缓慢的内存泄漏问题,但这可能是我在别处的代码。

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...
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?