Django返回http早期刷新(chunked response)

时间:2013-03-18 06:46:32

标签: python django http chunked-encoding http-chunked

我有一个算法,等待将近5秒钟来生成响应,我想在发送请求后立即向用户发送一个ack(http 200),告诉他已收到他的请求并等待5秒钟。

生成器功能:

def chunked_res():
    yield "Chunk 1"

    stop = time.time() + 5    # wait for 5 seconds
    while time.time() < stop:
        pass

    yield "Chunk 2"

在某些观点中:

response = HttpResponse ( chunked_res() )
response['Connection'] = 'close'
response['Transfer-Encoding'] = 'chunked'
response['status'] = 200
return response

浏览器响应:

“Transfer-Encoding:chunked \ nstatus:200 \ nConnection:close \ nContent-Type:text / html; charset = utf-8 \ n \ nChunk 1Chunk 2”

问题: 我得到了必要的响应(Chunk 1,Chunk 2),但是在5秒之后。我想首先发送“Chunk 1”然后在5秒后发送“Chunk 2”(更新respose)。是否有任何特定的设置/更改来实现此功能?

更新

Django = 1.4 python = 2.7

4 个答案:

答案 0 :(得分:2)

他们刚刚在django 1.5中添加了StreamingHttpResponse,在早期版本中添加了passing an iterator(&lt; = 1.4),您可以流式传输(或“chunk”)数据。

def chunked_res():
    yield "Chunk 1"

    time.sleep(5)  # wait for 5 seconds

    yield "Chunk 2"


def myview(request):
    g = chunked_res()
    return HttpResponse(g)

答案 1 :(得分:2)

你真的想避免这样做......

stop = time.time() + 5    # wait for 5 seconds
while time.time() < stop:
    pass

这将导致您的进程的CPU使用率在5秒内达到100%,这对于Web应用程序来说是一个巨大的数额。在共享托管环境中,您可能会从托管服务提供商那里收到一封讨厌的电子邮件,如果您有自己的服务器,那么您在循环中占用的那些周期可以有效地部署在处理其他请求中。这样做:

time.sleep(5)

这将使线程(或进程)休眠5秒钟,然后内核可以自由安排其他任务,或者在没有其他事情要做的情况下休眠CPU(节省电力和冷却成本)。 p>

答案 2 :(得分:0)

实际上,解决方案是使浏览器的第一个块大小至少为1024个字符,以便逐步显示。

How to stream an HttpResponse with Django

def chunked_res():
    yield "Chunk 1"
    yield " " * 1024  # Encourage browser to render incrementally (either 1024 or 1024-7{length of "chunk 1"} = 1017)

    time.sleep(5)  # wait for 5 seconds

    yield "Chunk 2"


def myview(request):
    g = chunked_res()
    return HttpResponse(g)

如果您使用 nginx ,则必须设置 proxy_buffering = off,以便服务器在1024数据块准备就绪时刷新响应。 http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size

适用于: HTTP / 1.0和HTTP / 1.1

答案 3 :(得分:0)

请澄清其他答案:对于Django 1.5+,您必须使用StreamingHttpResponse。常规的HttpResponse将收集完整的响应,并在完成后才返回。

from django.http import StreamingHttpResponse

def chunked_res():
    yield "Chunk 1"
    yield " " * 1024  # Encourage server to begin transferring and browser to begin rendering

    time.sleep(5)     # wait for 5 seconds

    yield "Chunk 2"

def myview(request):
    return StreamingHttpResponse(chunked_res())