如何解决在Rails中将大型PUT或POST请求正文读取为流,而无需缓冲到磁盘
我正在用Rails 6进行API用例的实验。用户会发布大型请求,这些请求将由Rails接收并流到另一个地方。这可能会与JRuby一起运行,但是现在我正在使用MRI Ruby进行测试。 Web服务器是Puma(开箱即用的导轨安装)。
在上载请求流时,是否有任何方法可以读取请求主体,或者Rails是否需要等待整个请求上载才能访问它?
使用此Curl命令:
curl -i -X PUT -T data.bin "http://localhost:3000/welcome/stream"
这个简单的控制器:
def stream
puts "The stream was called"
io = request.body
until io.eof?
io.read(1024*1024)
puts "Read 1MB"
end
head 200,content_type: "text/html"
end
似乎整个请求都在Rails对其进行访问之前在某个地方上演,因为我的任何put出现在控制台上都需要很长时间。
稍作搜索,似乎是Web服务器(Puma,Unicorn等)缓冲了数据,并且仅在接收到所有数据后才调用Rails。
无论如何,有没有开始读取流的内容,或者避免对其进行缓冲?
是Rack还是Puma进行缓冲?如果是这样,它将在哪里缓冲数据?
解决方法
是Rack还是Puma进行缓冲?如果是这样,它将在哪里缓冲数据?
服务器会收集整个流,然后再将其传递给Rack / Rails ...,这样您就无法在主体完全上传之前开始处理请求。
进行此设计的理由很充分,因为服务器将使用可用线程来轮询IO而不是进行阻塞,从而使您的应用程序可以在后台执行IO操作的同时处理其他请求。
否则,当您的应用程序在不完整的流上调用read
时,IO将阻塞线程(并扩展为服务器),从而导致并发性失败。
无论如何,有没有开始读取流的内容,或者避免对其进行缓冲?
您可以实现自己的服务器(不建议使用),也可以使用AJAX / WebSockets(更常见的方法)上传点点滴滴。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。