【问题标题】:gevent.http.HTTPServer API suggests streaming, but instead buffers entire requests and responsesgevent.http.HTTPServer API 建议流式传输,而是缓冲整个请求和响应
【发布时间】:2013-01-23 01:05:27
【问题描述】:

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

request.send_reply_start(200, 'OK')
request.send_reply_chunk(...)  # as many times as you wish
request.send_reply_end()

但是我一定是有一些错误配置,因为尽管有这个奇妙的无缓冲 API,我的请求处理程序直到 last 请求 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()

还有:

# 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'

感谢您的指导!

【问题讨论】:

  • 我刚刚尝试了这段代码,它运行良好并且流式传输良好。 :\
  • 没关系,我明白了。在客户端完成流式传输之前,服务器不会“流式传输”。跛脚。
  • 这还有问题吗?

标签: python http asynchronous buffer gevent


【解决方案1】:

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

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

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


请注意,以上信息是指gevent<1.0,它使用libevent 库,不适用于gevent 的更新版本。当前版本的gevent 不再包含http 模块,所以这个问题没有实际意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    相关资源
    最近更新 更多