通常,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 块正是该长度,网关知道不会有更多数据出现;它可以自行决定使用或不使用分块编码。同样地
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 缓冲在一起,当连接准备好再次读取时将它们作为单个块发送。简而言之,你无法控制分块,你可能会强制它发生,你可以经常阻止它发生(大多数网关如果没有必要不会分块);但不适合装帧。