5

我有一个算法,它等待近 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

浏览器中的响应:

"传输编码: 分块\n状态: 200\n连接: 关闭\n内容类型: text/html; charset=utf-8\n\nChunk 1Chunk 2"

问题: 我得到了所需的响应(Chunk 1,Chunk 2),但在 5 秒后。我想先发送“Chunk 1”,然后在 5 秒后发送“Chunk 2”(更新响应)。是否有任何特定的设置/更改来实现这一点?

更新:

Django = 1.4 蟒蛇 = 2.7

4

4 回答 4

2

他们刚刚在 django 1.5 中添加了StreamingHttpResponse ,并且通过在早期版本 (<= 1.4) 中传递迭代器,您可以流式传输(或“块”)数据。

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)
于 2013-03-18T06:59:14.793 回答
2

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

如何使用 Django 流式传输 HttpResponse

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

于 2013-03-22T11:50:51.700 回答
2

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

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

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

time.sleep(5)

这将使线程(或进程)休眠 5 秒,然后内核可以自由地安排其他任务,或者如果没有其他事情可做,则使 CPU 休眠(节省电力和冷却成本)。

于 2014-01-12T03:37:18.917 回答
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())
于 2019-10-14T15:47:35.483 回答