【问题标题】:Is http stream actually implemented by http chunk?http流实际上是由http chunk实现的吗?
【发布时间】:2019-12-16 02:39:41
【问题描述】:

起初,我以为http流实际上是实现http块。

所以我做了一个测试来学习。

这是一个 Django 视图

def test_stream(request):

    return StreamingHttpResponse(func)

func 返回可迭代 这是使用 curl 访问视图的输出

curl -vv -raw http://172.25.44.238:8004/api/v1/admin/restart_all_agent?cluster_id='dd5aef9cbe7311e99585f000ac192cee' -i
Warning: Invalid character is found in given range. A specified range MUST 
Warning: have only digits in 'start'-'stop'. The server's response to this 
Warning: request is uncertain.
* About to connect() to 172.25.44.238 port 8004 (#0)
*   Trying 172.25.44.238...
* Connected to 172.25.44.238 (172.25.44.238) port 8004 (#0)
> GET /api/v1/admin/restart_all_agent?cluster_id=dd5aef9cbe7311e99585f000ac192cee HTTP/1.1
> Range: bytes=aw
> User-Agent: curl/7.29.0
> Host: 172.25.44.238:8004
> Accept: */*
> 
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< X-Frame-Options: SAMEORIGIN
X-Frame-Options: SAMEORIGIN
* no chunk, no close, no size. Assume close to signal end

< 

some http response body.

* Closing connection 0

从输出中您可以看到没有分块的标头。看来Http流和chunk没有关系。

问题来了

  • http 流是通过http chunk 实现的吗?
  • 如何在 django 中返回分块响应?

【问题讨论】:

  • func() 是否返回一个可迭代对象?
  • 不正确的引用,将第一个撇号移到http://的开头
  • 实现实际上是由你的wsgi服务器完成的,你用什么来测试这个(如果是mod_wsgi,是哪个版本)? func() 应该是yield.
  • @OlegRusskin 是的,函数返回一个可迭代对象
  • @dirkgroten 是的。 func 返回可迭代,我正在使用 uwsgi 2.0.18 运行 django。

标签: django http curl http-streaming http-chunked


【解决方案1】:

不,流媒体与分块没有任何关系。你可以有一个或没有另一个。

流式响应的优点是您不需要一次将整个响应作为字符串加载到内存中。

这篇博客文章很好地解释了用例是什么:https://andrewbrookins.com/django/how-does-djangos-streaminghttpresponse-work-exactly/

它还涵盖了返回分块响应所需的内容,我将对此进行总结:

  • 使用StreamingHttpResponse 类,但提供一个可迭代的(列表、生成器...)作为第一个参数而不是字符串。
  • 不要设置Content-Length 标头。
  • 您需要使用一个网络服务器来为您分块响应。 Django 本身不会这样做,manage.py runserver 也不会发生这种情况(例如,uvicorn 和 gunicorn 会这样做)
from django.urls import path
from django.http import StreamingHttpResponse

def generator():
    for i in range(0, 100):
        yield str(i) * 1024 * 1024

def chunked_view(request):
    return StreamingHttpResponse(generator(), content_type='text/plain')

urlpatterns = [path('chunked', chunked_view)]

使用uvicorn myapp.asgi:application 运行 Django 应用程序。

curl -v http://127.0.0.1:8000/chunked &gt; /dev/null 在响应标头中显示transfer-encoding: chunked。

【讨论】:

  • “流式响应的优点是您不需要一次将整个响应作为字符串加载到内存中。”分块也有这个优势,因为响应是分段返回给客户端的。那么,如果我们有流,为什么我们需要分块呢?或者这两种技术有什么区别?
猜你喜欢
  • 2014-01-05
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
  • 2021-12-24
  • 2017-04-06
  • 2012-03-03
  • 2014-06-08
相关资源
最近更新 更多