在以下环境中: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遍历字符串并一次发送一个字符。我不知道每个字符是否都是在自己的块中发送的,但我知道它比第二种情况下字符串整体发送的速度慢。
由于分块,这两种情况之间的速度差异是什么?或者它是别的什么?
答案 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在一起,当连接准备再次读取时,将它们作为单个块发送。简而言之,您无法控制分块,您可能会强制它发生,并且您可以经常阻止它发生(大多数网关如果他们没有'必须);但它不适合框架。