gevent.http.HTTPServer API建议流式传输,而是缓冲整个请求和响应

Bra*_*des 7 python buffer asynchronous http gevent

提供的API gevent.http.HTTPServer似乎支持双向流式传输.请求对象不提供请求体作为简单字符串,而是提供.input_bufferPython可迭代的属性,而在另一个方向,响应的数据可以作为具有三个调用的块传递:

request.send_reply_start(200, 'OK')
request.send_reply_chunk(...)  # as many times as you wish
request.send_reply_end()
Run Code Online (Sandbox Code Playgroud)

但我必须有一些错误配置的东西,因为尽管这个奇妙的无缓冲的API,我的请求处理程序直到最后一块请求POST数据终于到达时才被调用,而在另一方向我没有看到任何标题到达我的客户端套接字直到服务器到达.send_reply_end().是否有一些我必须抛出的开关或一些配置设置,我必须操作以关闭缓冲并查看请求并在它们到达时发送响应,例如gevent通过其支持原始套接字StreamServer

我的应用程序需要支持可能比RAM大的单文件上载和下载,这将需要关闭此缓冲.

这是一个简单的服务器和使用gevent编写的客户端,它应该显示这种行为:

# srv.py

import gevent.http

M100 = 100 * 1024 * 1024

def main():
    print 'Serving on 8088...'
    gevent.http.HTTPServer(('0.0.0.0', 8088), handle).serve_forever()

def handle(request):
    print 'Is request chunked?', request.chunked
    for item in request.input_buffer:
        print 'received body segment of length', len(item), 'bytes'
    request.add_output_header('Content-Type', 'application/octet-stream')
    request.send_reply_start(200, 'OK')
    for i in range(5):
        print 'sending chunk', i
        request.send_reply_chunk(M100 * 'x')
    request.send_reply_end()

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

和:

# cli.py

import requests
import time

M100 = 100 * 1024 * 1024

def gen():
    for i in range(5):
        print 'sending chunk', i
        yield M100 * 'x'
        time.sleep(1)

if __name__ == '__main__':
    r = requests.post('http://localhost:8088/', data=gen(), stream=True)
    for block in r.iter_content(M100):
        print 'received', len(block), 'bytes from download'
Run Code Online (Sandbox Code Playgroud)

谢谢你的指导!

aug*_*rar 0

向服务器发出的请求:查看源代码,看起来在请求完成之前不会调用服务器的处理函数,无论是否以分块方式发送。所以你那里运气不好。

服务器响应:服务器响应可以以流式传输的方式发送,但是您需要在处理程序线程中自愿放弃控制才能使其工作(例如,通过在gevent.sleep()每个块之后调用)。

不幸的是,gevent似乎没有提供一种方法来等待给定块完成发送,然后再开始下一个块,因此,如果生成数据的速度快于发送数据的速度,则可能会遇到内存问题。


请注意,上述信息指的是gevent<1.0使用该libevent库的 ,并且不适用于较新版本的gevent。当前版本gevent不再包含http模块,因此这个问题没有实际意义。