31 | 时代之风(下):HTTP/2内核剖析
31 | 时代之风(下):HTTP/2内核剖析
讲述:Chrono
时长13:08大小12.00M
连接前言
头部压缩
二进制帧
流与多路复用
流状态转换
小结
课下作业
赞 18
提建议
精选留言(52)
- -W.LI-2019-08-071.还是无状态,流状态只是表示流是否建立,单次请求响应的状态。并非会话级的状态保持 2.小帧好,少量多次,万一拥堵重复的的少。假设大帧好,只要分流不用分帧了。 3.每一个请求响应都是一个流,流和流之间可以并行,流内的帧还是有序串行。
作者回复: good。
共 2 条评论45 - djfhchdh2019-08-073、首先要明确造成“队头阻塞”的原因,因为http1里的请求和应答是没有序号标识的,导致了无法将乱序的请求和应答关联起来,也就是必须等待起始请求的应答先返回,则后续请求的应答都会延迟,这就是“队头阻塞”,而http2采用了虚拟的“流”,每次的请求应答都会分配同一个流id,而同一个流id里的帧又都是有序的,这样根据流id就可以标识出同一次的请求应答,不用再等待起始请求的应答先返回了,解决了“队头阻塞”
作者回复: http/1里的请求都是排队处理的,所以有队头阻塞。 http/2的请求是乱序的,彼此不依赖,所以没有队头阻塞。
18 - 何用2019-08-07HTTP/2 底层还是依赖 TCP 传输,没有解决队头阻塞的问题啊,这就是为何 HTTP/3 要基于 UDP 来传输
作者回复: 对,虽然是部分解决,但对于http/1来说已经是一个很大的进步了。
共 2 条评论12 - 何用2019-08-07服务端是不是要为每一个客户端都单独维护一份索引表?连接的客户端多了的话内存不就OOM了嘛
作者回复: 是的,不过动态表也有淘汰机制,服务器可以自己定制策略,不会过度占用内存。
11 - 好好好2020-06-30老师,我还是无法理解HTTP1.X无法实现多路复用的具体原因。如果我在HTTP1.X版本的一个TCP连接下同时发送多个请求,会发生什么情况呢?造成这个情况的具体原因又是什么呢?
作者回复: 1.http协议要求请求-响应必须一来一回,上一个请求没有处理完,下一个请求是不能发出去的。一个tcp连接上的http请求必然是串行。 2.管道模式可以顺序发出多个请求,但响应也必须顺序响应。这些都是http/1.1里规定的。 3.再对比http/2,一个tcp连接里有多个流,每个流就是一个请求,所以多个请求可以并发,“复用”在了一个连接里。
共 4 条评论8 - 想个昵称好难2019-08-07老师您好,打扰您实在是抱歉,想请教您一个问题,您在文中说HTTP/2会在两端维护“Key-Value”的索引表,静态表应该是一摸一样的,那动态表俩边一样吗?如果一样的话,同步是比较难做的事情吧,我看RFC文档中是这么写的,”When used for bidirectional communication, such as in HTTP, the encoding and decoding dynamic tables maintained by an endpoint are completely independent, i.e., the request and response dynamic tables are separate.“, 所以我的理解是,动态表在客户端和服务器各自都有俩个表,一个是用来保存客户端发送的message的header,另外一个是保存服务器发送的header, 我看stackoverflow中也是这么写的,https://stackoverflow.com/questions/53003333/how-does-headers-keep-sync-in-both-client-and-server-side-in-http-2, 如果我有哪个地方理解错了,麻烦下老师指点一下展开
作者回复: 是的,客户端和服务器维护各自的动态表,收发各一张表,但字典里的内容必须是一致的,否则索引号就对不上了。
共 2 条评论8 - 想个昵称好难2019-08-07还有一个问题想请教下老师,您之前在《HTTP的前世今生》上有一段回复是说,只要是HTTP/1.1,就都是文本格式,虽然里面的数据可能是二进制,但分隔符还是文本,这些都会 在“进阶篇”里讲, 不过我看到现在还是有点迷惑,所二进制协议和文本协议的区别是什么呢?可以按照stackoverflow中https://stackoverflow.com/questions/2645009/binary-protocols-v-text-protocols 的回答来理解吗?
作者回复: 指的是协议本身的数据格式,而不是负载(payload)的格式。 你看http/1,请求行、头、body里的分隔符,都是ASCII码。 而http/2,是二进制帧,用字节、位来表示信息,没有ASCII码。 你可以把自己想象成协议的解析器,你看到的协议头是什么格式,文本还是二进制。
7 - djfhchdh2019-08-071、http的“无状态”是指对事务处理没有记忆,每个请求之间都是独立的,这与HPACK算法里的动态表、流状态转换是两回事。HPACK算法里维护动态表是用于头部压缩,而流状态转换只是表示一次请求应答里流的状态,都不会记录之前事务的信息
作者回复: 说的很好,也可以这么表述“语法上有状态,语义上无状态”。
7 - 许童童2019-08-07HTTP/2 的动态表维护、流状态转换很复杂,你认为 HTTP/2 还是“无状态”的吗? 还是无状态的,对上层应用来说,动态表维护、流状态转换这些操作对它不可见。 HTTP/2 的帧最大可以达到 16M,你觉得大帧好还是小帧好? 大帧好,应该小帧需要很多额外的头信息,有数据冗余。小帧可以当出差错时,只转输出错的帧,细粒度控制。 结合这两讲,谈谈 HTTP/2 是如何解决“队头阻塞”问题的。 因为流可以并发,一个流被阻塞了,并不影响其它的流。展开
作者回复: 我个人认为小帧比较好,当然如果在某些特定场景里,比如下载大文件,可以适当加大。
共 4 条评论6 - Luke2019-09-021、一个流中的多个帧是有序的,但是在二进制帧协议中,并没有看到这个序号,请问下老师,这个序号是在哪里?或者一个流中的多个帧是如何保证有序的? 2、如果出现丢帧的情况是如何重传的?
作者回复: 1.由tcp保证帧是顺序到达的,因为tcp是有序的字节流。 2.同样是由tcp实现,具体细节就太底层了,有兴趣可以研究tcp协议。
共 2 条评论5 - sunxu2019-08-07想问一下,nginx前端采用http2, 反向代理到应用服务使用的http1.1, 这种方式对请求响应有提升吗?
作者回复: Nginx作为代理,实际上就把传输链路拆分成了两个部分,下游因为使用了http/2,所以肯定会有性能提升。 而上游还是http/1,所以瓶颈就在这里,但因为后台系统的服务能力都很强,网络也好,所以不会有太大影响。 当然,如果全用http/2就更好了。
5 - Jasmine2021-10-08老师,同一个流内部,相同类型的帧,比如DATA[3]和DATA[3]怎么区分先后顺序呢?
作者回复: 流里的帧是由tcp来传输的,而tcp是有序的字节流,所以http/2流里的帧必然会是按照发送的顺序先后到达,不会是乱序。 所以,在tcp层面来看,帧是乱序的,但在流的层面来看,帧是有序的。
3 - 张欣2021-04-14老师,您好: 1,http2也是依赖于tcp来保证他自己帧数据的完整性么?他自己有检测数据完整性的功能么 2,http2的帧的排序序号也是保存在帧头部里面的么?
作者回复: 1.当然了,它的下层是tcp,传输的可靠性必须由tcp保证。 2.看帧结构,里面只有流id。因为帧是顺序发的,顺序由tcp保证,所以不需要序号。
共 2 条评论3 - Maske2020-06-261.还是无状态,http2虽然实现了多路复用,但是本质没有变,因为服务端永远不会自动记录上次请求的相关数据,客户端的每一次请求都需要表明其身份。 2.小帧好。因为http2的一个一个请求都分解为了一个一个帧,在同一个tcp/ip连接层面上表现为无序收发的,小帧有利于提高并行请求或响应。 3.通过分解一个一个请求或响应报文数据为多个帧,将同一个请求或响应的帧贴上相同的streamid来作为标识,使得在连接层面上变为无序收发,而且这些帧是并行的,因此不需要等待前一个请求响应结束才能进行下一个请求,实现了多路复用。展开
作者回复: 说的非常好。
3 - 钱2020-04-041:HTTP/2 的动态表维护、流状态转换很复杂,你认为 HTTP/2 还是“无状态”的吗? 还是无状态的,因为第二次交互并不需要保留或者知道是否在之前已经有过一次交互了,假设后面的服务是个集群第一次请求和第二次请求负载打到的机器不同也没关系,另外动态表应该可以重新创建吧! 另外,用代号表示语义是不是也是一种空间换时间的运用,虽然只是减少了传输空间增加了两头的存储空间。 2:HTTP/2 的帧最大可以达到 16M,你觉得大帧好还是小帧好? 大帧好还是小帧好,我觉得应该看场景,如果网络不稳定小帧好因为丢失重传的成本低,也可以传输更多的数据帧提高并行度。不过如果网络稳定,帧小必然帧头多对于而数据是放在帧体区的是不是针对大文件下载之类的需求就有些浪费了呢? 3:结合这两讲,谈谈 HTTP/2 是如何解决“队头阻塞”问题的。 HTTP/2的连接好似一座桥,桥上可以过许多的车辆(数据帧),他们可以并发来走,而车队中的车辆是有顺序的她们组成一个车队(一次请求或响应报文),所以,先出发的车队不一定先到,因为车队之间是并行互不阻塞的。展开
作者回复: 说的很对。
3 - book尾汁2019-11-041 http的无状态是针对应用层的吧,多个请求之前不会有影响,http2虽然有维护一些状态的信息,但这是针对流的信息,所以我认为http2也还是无状态的 2 不知道大小帧哪个好,大帧头部占比会少一点,但在TCP层会需要拆分成小帧,可能会多耗点时间,太大的帧TCP发送缓存区也要设的大一点吧 3 http2相比http1.1有了流ID来标识请求响应,因此同一个连接就可以同时进行多个流的传输,但由于TCP的收发窗口的确认机制,并发性还是会受到限制。 总结: http2连接的建立 建立完成TLS连接之后,发送连接前言PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n,这样后面的报文就会使用http2的格式 报文格式: 帧长度 3byte 默认上限为16k 最大为2^24 帧类型 1byte 大致分为数据帧和控制帧,最高可表示256种,可自己扩展 标志位 1byte 携带简单的控制信息 流ID 4byte 其中最高位为0,客户端发起的流id为奇数,服务器发起的流id为偶数,0号流为控制流 请求头字段采用HPACK的方式来进行压缩,有静态表来存储二元组(字段 ,value)和index之间的关系,静态表里找不到的key value,可以放在动态表里。展开
作者回复: 总结的不错。 1.可以说是语义无状态,语法有状态。 2.通常都认为较小的帧比较好,粒度小,流的并行度就高。 3.http/2在tcp层有队头阻塞,所以就出了http/3。
3 - 闫飞2019-08-14哈夫曼编码的使用是HTTP2协议里面一个不容忽视的要素,该编码方式很好地保证了所有信息的平均码长最短而互相不构成前缀关系,易于解码。
作者回复: great。
3 - -W.LI-2019-08-07老师好!TCP网络不好的时候会降速,http2的话是一个帧没收到就会导致TCP降速么?
作者回复: 是的,会发生tcp层的队头阻塞,下一次http/3会讲。
3 - 好好好2020-06-30想请问下老师,我在别的地方看到http1.1有管道机制可以同时发送请求,服务端会根据请求顺序返回内容。那为什么还说http1.x如果同时发送请求,服务端无法区分数据是哪个请求所以实现不了多路复用呢?希望老师解答下。
作者回复: 1.http/1.1的管道虽然可以发多个请求,但仍然是顺序处理,有队头阻塞,所以很少有服务器、浏览器支持,基本上没用。 2.http/1.1既然是顺序请求,那么就只能是串行处理,也就无法像http/2那样多路复用了。 3.多个并发的http/1.1请求,服务器可以根据tcp连接来区分,不可能是“无法区分”的,这个说法不知道是哪里来的,我认为这个是错误的。
2 - 假于物2021-08-04老师,帧头和数据帧对应关系是怎么样的? 1对1还是1对多?
作者回复: 当然是一个帧头只能对应一个帧体了,但流里可以有多个数据帧。
1