如何在mod_wsgi下控制werkzeug中http分块的使用

时间:2014-03-27 15:14:20

标签: python apache mod-wsgi werkzeug transfer-encoding

在以下环境中:Apache - > mod_wsgi - > python - > WERKZEUG

如何控制是否使用了http ckunking以及块的大小?

跟进:

我担心的是它之间的区别:

response = werkzeug.wrappers.Response()
response.response = very_long_string
return response

和此:

response = werkzeug.wrappers.Response()
response.response = [ very_long_string ]
return response

在第一种情况下,werkzeug遍历字符串并一次发送一个字符。我不知道每个字符是否都是在自己的块中发送的,但我知道它比第二种情况下字符串整体发送的速度慢。

由于分块,这两种情况之间的速度差异是什么?或者它是别的什么?

1 个答案:

答案 0 :(得分:1)

通常,wsgi指定只要应用程序生成响应内容的任何部分,就应该将数据发送到客户端,而不进行缓冲;即,如果你这样做:

CONTENT = "a bit more content\n"

def my_slow_application(environ, start_response):
    start_response("200 OK", [("Content-Type", "text/plain")])
    yield CONTENT
    sleep(1)

值得注意的是,没有Content-Length标头,网关(在您的情况下为apache / mod_wsgi)无法猜测它已找到所有响应内容,并且因为它不允许缓冲,必须使用分块传输编码。

另一方面,请考虑:

def my_slowish_application(environ, start_response):
    start_response("200 OK", [("Content-Type", "text/plain"),
                              ("Content-Length", str(len(CONTENT))])
    yield CONTENT
    sleep(1)

由于应用程序已指定内容长度,并且由于第一个yield ed chunk正好是该长度,因此网关知道将不再有数据;它可能会也可能不会使用分块编码,由它自行决定。同样

def my_fast_application(environ, start_response):
    start_response("200 OK", [("Content-Type", "text/plain")])
    return [CONTENT] * 100

通常不会导致分块;响应是一个列表,其大小有限,因此网关知道它具有整个响应。即使没有使用sum(map(len, app_iter))的应用程序的显式标头,它也可以找到内容长度,然后以网络允许的速度发送响应。


至于如何控制"大"如果客户端连接被阻塞,网关可能会缓冲块;你的应用可能

yield "foo"
sleep(1)
yield "bar"
sleep(1)
yield "baz"

但是如果客户端连接在处理" foo"块,网关可能缓冲bar和baz在一起,当连接准备再次读取时,将它们作为单个块发送。简而言之,您无法控制分块,您可能会强制它发生,并且您可以经常阻止它发生(大多数网关如果他们没有'必须);但它不适合框架。