准备知识 Nginx支持QUIC/HTTP3的实现路径和实践思考 | InfoQ公开课 https://www.infoq.cn/video/VPK3Zu0xrv6U8727ZSXB?utm_source=in_album&utm_medium
HTTP/2 协议虽然大幅提升了 HTTP/1.1 的性能,然而,基于 TCP 实现的 HTTP/2 遗留下 3 个问题:
旁白:没看懂 搜索http2网上都说他好呀 https 特点 https://blog.csdn.net/zhuyiquan/article/details/52585941】
而 HTTP/3 协议恰恰是解决了这些问题:
所以现在学习 HTTP/3 正当其时,这将是下一代互联网最重要的基础设施。
HTTP/3 协议到底是什么?就像 HTTP/2 协议一样,HTTP/3 并没有改变 HTTP/1 的语义。
那什么是 HTTP 语义呢?
在我看来,它包括以下 3 个点:
HTTP/1 语义不变的情况下,更改了编码格式,
这由 2 个原因所致:首先,是为了减少编码长度。下图中 HTTP/1 协议的编码使用了 ASCII 码,用空格、冒号以及 \r\n 作为分隔符,编码效率很低。
HTTP/2 协议基于 TCP 有序字节流实现,因此应用层的多路复用并不能做到无序地并发,在丢包场景下会出现队头阻塞问题。
如下面的动态图片所示, 服务器返回的绿色响应由 5 个 TCP 报文组成, 而黄色响应由 4 个 TCP 报文组成,
当第 2 个黄色报文丢失后, 即使客户端接收到完整的 5 个绿色报文,
但 TCP 层不允许应用进程的 read 函数读取到最后 5 个报文,并发也成了一纸空谈。
青铜:表示理解不了,为此进行查缺补漏
TCP为了提高传输效率, 发送数据的时候, 并不是直接发送数据到网路, 而是先暂存到系统缓冲, 超过时间或者缓冲满了, 才把缓冲区的内容发送出去, 这样, 就可以有效提高发送效率. 所以会造成所谓的粘包, 即前一份Send的数据跟后一份Send的数据可能会暂存到缓冲当中, 然后一起发送。
应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文, 接收方UDP对下方交上来的UDP用户数据报 ,在去除首部之后就原封不动的交付给上层的应用程序,一次交付一个完整报
udp 没有拆分包文。
$ ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 129 128 *:80 *:*
If the backlog argument is greater than the value in /proc/sys/net/core/somaxconn, then it is silently
truncated to that value; the default value in this file is 128. In kernels before 2.4.25, this limit was
a hard coded value, SOMAXCONN, with the value 128.
nstat -az | grep -E 'TcpExtListenOverflows|TcpExtListenDrops'
如果 syn queue 满了并且没有开启 syncookies 就丢包,并将 ListenDrops 计数器 +1。
如果 accept queue 满了也会丢包,并将 ListenOverflows 和 ListenDrops 计数器 +1。
为了满足TCP协议不丢包。TCP协议有如下规定:
1. 数据分片:发送端对数据进行分片,接受端要对数据进行重组,由TCP确定分片的大小并控制分片和重组
2. 到达确认:接收端接收到分片数据时,根据分片数据序号向发送端发送一个确认
3. 超时重发:发送方在发送分片时设置超时定时器,如果在定时器超时之后没有收到相应的确认,重发分片数据
4. 滑动窗口:TCP连接的每一方的接受缓冲空间大小固定,接收端只允许另一端发送接收端缓冲区所能接纳的数据,TCP在滑动窗口的基础上提供流量控制,防止较快主机致使较慢主机的缓冲区溢出
5. 失序处理:作为IP数据报来传输的TCP分片到达时可能会失序,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层;
6. 重复处理:作为IP数据报来传输的TCP分片会发生重复,TCP的接收端必须丢弃重复的数据;
7. 数据校验:TCP将保持它首部和数据的检验和,这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收
如何解决HTTP队头阻塞
对于HTTP1.1中管道化导致的请求/响应级别的队头阻塞,可以使用HTTP2解决。HTTP2不使用管道化的方式,而是引入了帧、消息和数据流等概念,
每个请求/响应被称为消息,每个消息都被拆分成若干个帧进行传输,每个帧都分配一个序号。每个帧在传输是属于一个数据流, 而一个连接上可以存在多个流,各个帧在流和连接上独立传输,到达之后在组装成消息, 这样就避免了请求/响应阻塞。
当然,即使使用HTTP2,如果HTTP2底层使用的是TCP协议,仍可能出现TCP队头阻塞。
想要在应用程序当中避免TCP队头阻塞带来的影响,只有舍弃TCP协议。比如google推出的quic协议,在某种程度上可以说避免了TCP中的队头阻塞,因为它根本不使用TCP协议,而是在UDP协议的基础上实现了可靠传输。而UDP是面向数据报的协议,数据报之间不会有阻塞约束。
通过这个文字了解一点 我们在谈论HTTP队头阻塞时,我们在谈论什么?
https://cloud.tencent.com/developer/news/123577
https://juejin.cn/post/6844903853985366023
https://xzchsia.github.io/2020/08/31/tcp-seq-ack/
https://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/
https://segmentfault.com/a/1190000016375111 【翻译版本】
https://juejin.cn/post/6844903809995505671
在IoT时代,移动设备接入的网络会频繁变动,从而导致设备IP地址改变。
对于通过四元组(源IP、源端口、目的IP、目的端口)定位连接的TCP协议来说, 这意味着连接需要断开重连,
所以上述2个RTT的建链时延、TCP慢启动都需要重新来过。
而HTTP3的QUIC层实现了连接迁移功能,允许移动设备更换IP地址后, 只要仍保有上下文信息(比如连接ID、TLS密钥等),就可以复用原连接。
https://time.geekbang.org/column/article/266962
不同分支上的子问题,不能相互依赖,需要各自独立。因为一旦包含了依赖关系,子问题和父问题之间就失去了可以被“归并”的意义。在软件开发领域,我们把这个概念称为“耦合度”和“内聚度”,这两个度量概念非常重要。
如何将拆分后的各个节点再次连接起来,从模式上来说,主要是去中心化与中心化之分
不管系统的规模发展到多大,合理的拆分,加上合适的连接方式, 那么至少会是一个运转顺畅、协作舒服的系统, 至少能够正常发挥分布式系统应有的价值。
维基百科对“分布式系统”的宏观定义是这样的:
分布式系统是一种其组件位于不同的联网计算机上的系统, 然后通过互相传递消息来进行通信和协调。
为了达到共同的目标,这些组件会相互作用。
现在, 我们搞清楚了,看待一个“分布式系统”的时候,内在胜于表象。
以及,只要涉及多个进程协作才能提供一个完整功能的系统, 就是“分布式系统”。