• http2.0/http3.0/rpc


    目录

    http1.x

    http2.0

    相较于http1.0的改进点

    http3.0

    QUIC如何解决队头阻塞问题的?

    QUIC如何做流量控制的?

    QUIC如何做拥塞控制的?

    QUIC更快的建立连接?

    RPC和http有什么区别

    protobuf压缩


    http1.x

    1. 冗余的header:每个请求都会带上冗余重复的Header,导致传输的体积很大
    2. http是无状态的协议,每个请求没有做特殊的标识:无法通过一个TCP链接并发的发送多个请求,只能等上一个请求的rsp返回了,才能发送下一个请求。(只能串行的发送)
      1. 因为http1.x是基于”文本“的协议,请求的内容打包在header/body中,内容通过CRLF来分割,同一个TCP链接中,无法区分req/rsp是属于哪个请求
      2. 于是http1.x提出了pipeline:允许请求方一口气的发送多个请求,但是有一个严重的弊端,需要对应的rsp按照req的顺序严格排列(因为每个请求没有唯一的标识,所以不按照顺序排列就无法区分rsp是属于哪个req)。==> 若前面的req迟迟不来,后面的请求都会要等待
        • Chrome浏览器,一个域名,只能有6个TCP链接在同时工作

    http2.0

    相较于http1.0的改进点

    1. header压缩
      1. 静态字典:常见的头部名称,如,get/post/cookie等
      2. 动态字典:比如一个req过来,会将字段保存在动态字典中,再一个req,若发现相同的字段,无需传递,只需要使用动态字典中的标识
    2. 流/帧 + 多路复用
      1. http2.0提出了流的概念,每个请求对应一个流,每个流都有唯一的ID,用来区分不同的req/rsp
      2. 基于流的概念,又提出了帧:一个请求的数据被分成多个帧,方便进行数据传输。每个帧都属于某一个流ID
      3. 多路复用:在一个TCP链接上,可以同时发起无数个请求,并且响应可以同时返回
    3. 请求划分优先级
      1. 多路复用带来的一个问题是,在共享连接的基础上会存在一些关键请求被阻塞,SPDY 允许给每个请求设置优先级,这样重要的请求就会优先得到响应
    4. 服务端推送
      1. 在HTTP1.x中,访问一个页面,浏览器首先获取HTML资源,然后在解析页面时增量地获取其他资源,服务器必须等待浏览器发出请求后才下发页面内资源。而服务器实际上是知道页面内资源有哪些的,如果服务器能够在浏览器显式请求资源之前就将资源推送到浏览器,页面加载速度将会大大提示,这也是本篇的主旨。
      2. 简单来讲,就是当用户的浏览器和服务器在建立链接后,服务器主动将一些资源推送给浏览器并缓存起来,这样当浏览器接下来请求这些资源时就直接从缓存中读取,不会在从服务器上拉了,提升了速率

    http2.0存在的问题:http2.0只是通过多路复用技术解决了http层面上的队首阻塞,但是tcp层面的毫无办法TCP 的队头阻塞并没有彻底解决。TCP 为了保证可靠传输,有一个“超时重传”机制,丢失的包必须等待重传确认

    TCP队头阻塞
            我们都知道,TCP是一种可靠传输,这个可靠就是体现在它能够“按序到达”,然后再被上层接收,这里的按序到达指的是最终顺序是按序排列的,也就是说每当有一个或几个Packet丢失的时候,会等待它到达后合并,然后再向上交付。

           因此,很容易可以理解,当一个流的第一个数据包丢失了,那么即使后面的数据包都到达了,后面的这些数据包也不能被处理,而是要等第一个数据包到了之后才能被上层接收处理,那么这个时候不止是第一个数据包需要额外等待一个或多个RTT,后面的第二个Packet、第三个Packet......都需要同样多等待那么多时间才能处理,但实际上他们是按时到达了的,这也就是所谓的TCP队头阻塞

    http3.0

    http3.0彻底弃用了TCP协议,改用可靠的UDP协议(QUIC

    TCP协议存在的缺点:其实也不能怪 TCP 协议,它本来设计目的就是为了保证数据的有序性

            1. TCP建立连接的延迟

            2. TCP存在队头阻塞问题:

                    1. 发送窗口的队头阻塞:TCP 发送出去的数据,都是需要按序确认的,只有在数据都被按顺序确认完后,发送窗口才会往前滑动。

                    

                    案例:客户端发送了第 5~9 字节的数据,但是第 5 字节的 ACK 确认报文在网络中丢失了,那么即使客户端收到第 6~9 字节的 ACK 确认报文,发送窗口也不会往前移动。这就是发送窗口的头部阻塞问题

                    2. 接收窗口的队头阻塞:接收窗口什么时候才能滑动?当接收窗口收到有序数据时,接收窗口才能往前滑动,然后那些已经接收并且被确认的「有序」数据就可以被应用层读取。(但是,当接收窗口收到的数据不是有序的)

                    案例:比如收到第 33~40 字节的数据,由于第 32 字节数据没有收到, 接收窗口无法向前滑动,那么即使先收到第 33~40 字节的数据,这些数据也无法被应用层读取的。只有当发送方重传了第 32 字节数据并且被接收方收到后,接收窗口才会往前滑动,然后应用层才能从内核读取第 32~40 字节的数据

    QUIC如何解决队头阻塞问题的?

    1. 在一条 QUIC 连接上可以并发发送多个 HTTP 请求 (Stream)。

    2. 但是,QUIC 给每一个 Stream 都分配了一个独立的滑动窗口,这样使得一个连接上的多个 Stream 之间没有依赖关系,都是相互独立的,各自控制的滑动窗口

         

    QUIC如何做流量控制的?

    TCP 流量控制是通过让「接收方」告诉「发送方」,它(接收方)的接收窗口有多大,从而让「发送方」根据「接收方」的实际接收能力控制发送的数据量 。在前面说到,

            1. TCP 的发送窗口在收到对已发送数据的顺序确认 ACK后,发送窗口才能往前滑动,否则停止滑动。

            2. TCP 的接收窗口在收到有序的数据后,接收窗口才能往前滑动,否则停止滑动;

            QUIC 是基于 UDP 传输的,而 UDP 没有流量控制,因此 QUIC 实现了自己的流量控制机制。不过,QUIC 的滑动窗口滑动的条件跟 TCP 有所差别的。QUIC实现了2中级别的流量控制:stream、connection。

    1. stream级别的流量控制

            回想一下 TCP,当发送方发送 seq1、seq2、seq3 报文,由于 seq2 报文丢失了,接收方收到 seq1 后会 ack1,然后接收方收到 seq3 后还是回 ack1(因为没有收到 seq2),这时发送窗口无法往前滑动。

            是,QUIC 就不一样了,即使中途有报文丢失,发送窗口依然可以往前滑动,具体怎么做到的呢?我们来看看。        

    ① 最开始,接收方的接收窗口初始状态如下:

            

    ② 接着,接收方收到了发送方发送过来的数据,有的数据被上层读取了,有的数据丢包了,此时的接收窗口状况如下:

             

            可以看到,即使中间有数据包丢失了,也不会影响后面数据的接收。接收窗口的左边界取决于接收到的最大偏移字节数,此时的接收窗口 = 最大窗口数 - 接收到的最大偏移数,这里就跟 TCP 不一样了。

            那接收窗口触发的滑动条件是什么呢?看下图:

                    

            当图中的绿色部分数据超过最大接收窗口的一半后,最大接收窗口向右移动,同时给对端发送「窗口更新帧」。当发送方收到接收方的窗口更新帧后,发送窗口也会往前滑动,即使中途有丢包,依然也会滑动,这样就防止像 TCP 那样在出现丢包的时候,导致发送窗口无法移动,从而避免了无法继续发送数据

            在前面我们说过,每个 Stream 都有各自的滑动窗口,不同 Stream 互相独立,队头的 Stream A 被阻塞后,不妨碍 StreamB、C的读取。而对于 TCP 而言,其不知道将不同的 Stream 交给上层哪一个请求,因此同一个Connection内,Stream A 被阻塞后,StreamB、C 必须等待。

            总结:QUIC 协议中同一个 Stream 内,滑动窗口的移动仅取决于接收到的最大字节偏移(尽管期间可能有部分数据未被接收),而对于 TCP 而言,窗口滑动必须保证此前的 packet 都有序的接收到了,其中一个 packet 丢失就会导致窗口等待。 

    2. connection级别的流量控制

            而对于 Connection 级别的流量窗口,其接收窗口大小就是各个 Stream 接收窗口大小之和。

    Connection 流量控制

    上图所示的例子,所有 Streams 的最大窗口数为 120,其中:

            Stream 1 的最大接收偏移为 100,可用窗口 = 120 - 100 = 20

            Stream 2 的最大接收偏移为 90,可用窗口 = 120 - 90 = 30

            Stream 3 的最大接收偏移为 110,可用窗口 = 120 - 110 = 10

    那么,整个 Connection 的可用窗口 = 20 + 30 + 10 = 60

    QUIC如何做拥塞控制的?

            QUIC 协议当前默认使用了 TCP 的 Cubic 拥塞控制算法(我们熟知的慢开始、拥塞避免、快重传、快恢复策略),同时也支持 CubicBytes、Reno、RenoBytes、BBR、PCC 等拥塞控制算法,相当于将 TCP 的拥塞控制算法照搬过来了,QUIC 是如何改进 TCP 的拥塞控制算法的呢?

            QUIC 是处于应用层的,应用程序层面就能实现不同的拥塞控制算法,不需要操作系统,不需要内核支持。这是一个飞跃,因为传统的 TCP 拥塞控制,必须要端到端的网络协议栈支持,才能实现控制效果。而内核和操作系统的部署成本非常高,升级周期很长,所以 TCP 拥塞控制算法迭代速度是很慢的。

            而 QUIC 可以随浏览器更新,QUIC 的拥塞控制算法就可以有较快的迭代速度

            TCP 更改拥塞控制算法是对系统中所有应用都生效,无法根据不同应用设定不同的拥塞控制策略。但是因为 QUIC 处于应用层,所以就可以针对不同的应用设置不同的拥塞控制算法,这样灵活性就很高了。

    QUIC更快的建立连接

            对于 HTTP/1 和 HTTP/2 协议,TCP 和 TLS 是分层的,分别属于内核实现的传输层、openssl 库实现的表示层,因此它们难以合并在一起,需要分批次来握手,先 TCP 握手(1RTT),再 TLS 握手(2RTT),所以需要 3RTT 的延迟才能传输数据,就算 Session 会话服用,也需要至少 2 个 RTT。

            HTTP/3 在传输数据前虽然需要 QUIC 协议握手,这个握手过程只需要 1 RTT,握手的目的是为确认双方的「连接 ID」,连接迁移就是基于连接 ID 实现的。

            但是 HTTP/3 的 QUIC 协议并不是与 TLS 分层,而是QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的“记录”,再加上 QUIC 使用的是 TLS1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商,甚至在第二次连接的时候,应用数据包可以和 QUIC 握手信息(连接信息 + TLS 信息)一起发送,达到 0-RTT 的效果

            如下图右边部分,HTTP/3 当会话恢复时,有效负载数据与第一个数据包一起发送,可以做到 0-RTT:

            

    RPC和http有什么区别

    1. RPC是方法,http是传输协议。其实两者不是一个类型,没有什么可比性
    2. 传输协议
      1. RPC:tcp协议、http协议
      2. http:http协议
    3. 传输效率
      1. RPC ①如果使用自定义的TCP协议,可以让请求头的信息更少 ②使用http2.0协议,传输效率也很高
      2. http:请求头中包含很多无用的信息,比如refer,keepalivetime,last-modify等信息。在流量大的时候,每次请求多几个字节,影响效率
    4. 性能
      1. RPC:可以基于thrift或pb来实现二进制传输
      2. http:也可以使用pb,但是目前主流的浏览器大部分是使用json文本传输

    protobuf压缩

    optional uint64 id = 1;

    序列号 + 类型 = 序列号<<3 | 类型

    id保存的值:采用base128压缩

    GRPC原理

  • 相关阅读:
    倒计时9天|Zabbix中国峰会15位重磅嘉宾抢先看!
    java计算机毕业设计石家庄市居家养老服务平台源程序+mysql+系统+lw文档+远程调试
    CSS中的 5 类常见伪元素详解!
    -贪吃蛇-
    vue3 props传值默认类型
    回收羽绒羽毛检测
    微信支付 APP端 第三弹 申请退款
    如何压缩jpg图片的大小?可以一键压缩图片的软件有哪些?
    logback--进阶--02--Logger,Appenders 和 Layouts
    Java(六)——常用类Math类
  • 原文地址:https://blog.csdn.net/weixin_36750623/article/details/126852498