3

通过HTTP发送大量数据的三种方法

 11 months ago
source link: https://www.51cto.com/article/769732.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

通过HTTP发送大量数据的三种方法

作者:小技术君 2023-10-13 10:45:18
我们有三种方法可以通过HTTP缩短发送大量数据的时间,它们并不是互斥的。你可以根据用例一起使用所有方法。

在网络的早期时期,人们发送的文件大小仅为几KB。到了2023年,我们享受着高分辨率的MB级别图像,并在几GB的4K(即将是8K)视频中观看。

即使有良好的互联网连接,下载一个5GB的文件仍然需要一些时间。如果你拥有Xbox或PlayStation,你就知道这种感觉。

我们有三种方法可以通过HTTP缩短发送大量数据的时间:

  • 发送分块数据
  • 请求选择范围内的数据

它们并不是互斥的。你可以根据用例一起使用所有方法。

d2cada7719c89abe94c4424bd1739425b7cf6c.jpg
794e98b839288e42002340064839e62f5a42e2.png

1*_un0bHBemgCSDocQmucK5Q.png

要压缩数据,我们需要压缩算法。

在发送请求时,浏览器会包含一个名为Accept-Encoding的头,其中包含支持的压缩算法列表,包括gzip(GZIP)、compress、deflate和br(Brotli)。

接下来,服务器从列表中选择其支持的算法,并在Content-Encoding头中设置算法名称。

当浏览器接收到响应时,它知道如何解析正文中的数据。

在这些算法中,最流行的是GZIP。它是压缩文本数据(如HTML、CSS和JavaScript)的绝佳选择。

Brotli是另一个值得一提的算法。它在压缩HTML方面的性能甚至比GZIP更好。

这些高效的算法有一些限制。

它们对文本的压缩效果很好,但对于压缩图像或视频来说则不足够。毕竟,媒体已经过了优化。

试着在你的计算机上压缩一个视频文件。在压缩之前和之后,你几乎看不到太大的区别。

此外,几乎不可能将一个5GB的视频压缩到几KB而不损失质量。

压缩是好的,但我们需要一个更好的解决方案——将文件分块发送并在客户端组装部分数据。

发送分块数据

74955f7464ae30b716564071407c7bb38e2430.png

1*0WLNkzfgw9faLpTUXkk3tg.png

在版本1.1中,HTTP引入了分块数据以处理大数据情况。

在发送响应时,服务器添加一个头Transfer-Encoding: chunked,让浏览器知道数据是分块传输的。

c7bbe6c522081a6e8690888c6de63a6ad150cf.png

1*Nwlp0QqhEsvWl4fw-x0X7Q.png

每个分块数据都有以下组件:

  • 一个长度块标记,标记当前分块数据的长度
  • 分块数据块
  • 在每个块的末尾的CRLF分隔符

想知道CRLF是什么吗?

e2dc22d278e48baef4f0341b5c0473d77c5650.png

1*s_-5lmT9176ymCAaaGCE2w.png

CR紧接着LF(CRLF,\r\n,或0x0D0A)将光标移动到下一行,然后移到行的开头。 在本文末尾的进一步阅读部分,你可以找到更多详细信息。在这里,你可以简单地将其视为一个分隔符。

服务器继续向浏览器流式传输分块数据。当达到数据流的末尾时,它附加一个包含以下部分的结束标记:

  • 一个长度块,数字为0,末尾为CRLF
  • 一个额外的CRLF

在浏览器端,它等待所有数据块,直到达到结束标记。然后,它移除分块编码,包括CRLF和长度信息。

接下来,它将分块数据组合成一个整体。因此,在Chrome DevTools上,你只能看到组装后的数据,而不是分块数据。

最终,你会收到整个数据的一块。

33fb29a080fc40b40ed143cd95b12daf3f2ebf.png

1*oChWIlysG3PQD3vy8ctVxw.png

分块数据是有用的。然而,对于一个5GB的视频,完整的数据仍然需要一些时间才能到达。

我们能不能获取数据的选定块,并在需要时请求其他块呢?

HTTP说可以。

在选定范围内请求数据

1596afc8451e6ed9d8d5686f356ee2891b9a72.png

1*LOGONes_KpmSN6zXaz9DhA.png

在YouTube上打开一个视频,你会看到一个灰色的进度条正在向前移动。

你刚刚看到的是YouTube在请求选定范围内的数据。

此功能使你可以在时间轴的任何地方跳跃。当点击进度条上的某个位置时,浏览器会请求视频数据的特定范围。

在服务器上实现范围请求是可选的。如果实现了,你可以在响应头中看到Accept-Ranges: bytes。

94d0a5a2684726308e6708ddd8db545397098d.png

1*MWd4AGP8lLRIQw5mketXew.png

这是一个YouTube请求的示例。在任何“playback”请求中,你都可以找到这个头。

范围请求头看起来像`Range:bytes=0-80`,它是从0开始的索引。

这个头是一个设计非常巧妙且具有出色灵活性的头。

假设一个数据总共有100个字节。

  • Range: bytes=20请求从20开始到末尾的范围,等于Range: bytes=20-99。
  • Range: bytes=-20请求数据的最后20个字节,等于Range: bytes=80-99。

如果请求的范围有效,服务器将发送带有Content-Range头的响应,验证数据范围和总长度,例如Content-Range: bytes 70-80/100。

范围请求广泛用于视频流媒体和文件下载服务。

你有没有在互联网中断后继续文件下载?那就是范围请求。

此外,范围请求支持多个范围。

例如,你可以从文件中请求两个范围,如Range: bytes=20-45, 70-80。

多范围体看起来类似于分块数据。每个数据块都有以下部分:

  • 一个边界块,标识不同数据块的边界,以--开始,以CRLF结束
  • 两个头,Content-Type和Content-Range,显示相应数据块的属性,以CRLF结束
  • 一个额外的CRLF,告诉客户端真正的数据即将到来
  • 最后,以CRLF结束的数据块

边界仅仅是一个看起来像3d6b6a416f9b5的随机字符串,标记不同数据块的边界。

最终,体结束于边界块,以--开始,以--和CRLF结束。这个部分告诉浏览器多部分已经结束。

让我们把它全部整合起来。响应体的结构如下所示。

b4e608e35de327bf847768e1023c709b9f4b36.png

HTTP帮助我们通过压缩、分块数据和范围数据传送大量数据。

这里的思想是在需要的时候传送我们需要的数据,然后在需要时发送其他数据。当在设计类似系统时遇到问题时,你可以尝试相同的思路。

通过结合这三种方法,我们可以发送压缩的分块数据范围数据。

责任编辑:赵宁宁 来源: 小技术君

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK