你没搞明白HTTP/1.1 pipelining和HTTP/2 stream解决的问题是什么,本身它们两个解决的问题也不完全是同一个问题,更跟底层TCP的传输没有一丝一毫的关系。
HTTP/1.1和HTTP/2都是基于TCP的协议,TCP模型是双向数据流,任何在一个TCP连接上处理超过一个请求的协议都需要解决这样两个问题:
HTTP/1.1的方案中,请求和响应的消息必须在流中占据一段连续的空间,它的格式保证解析方能正确判断出消息体的长度,而请求和响应的对应关系采取自然顺序,第一个对应第一个,第二个对应第二个(排除返回Status 1xx的情况)
HTTP/2的方案使用二进制的分帧格式,每个请求和响应不需要占据相邻的帧,按照STREAM ID将帧划分到不同的请求和响应中,对应关系也通过STREAM ID,这就解除了不同请求响应之间相对顺序的限制。
最传统的HTTP/1.1 Server在每个连接上的工作模式是读取请求(头)、解析请求、处理请求、发送结果四个步骤的循环,而且每个步骤都是阻塞的。这其中,第一步和第四步是IO密集的工作,而第二步和第三步是CPU密集的工作,这就意味着服务器忙着IO的时候CPU在放假,忙着CPU计算的时候IO在偷懒,不利于降低响应延迟和提高服务器整体效率。解决的方案是让这四个步骤重叠起来,负责读取请求的部分读取完上一个请求(包括请求头和body)之后,立即读取下一个请求;负责解析请求的部分实现一边读取一边解析;负责处理请求的部分在处理完上一个请求之后立即继续处理下一个请求,无需等待结果完全发送完成。这样整体请求处理的延迟就可以降低,IO和CPU的操作可以重叠起来。
更进一步,这四步操作中往往处理请求的步骤是最耗时的,如果进一步让上一个请求还没有处理完的情况下,就允许下一个请求进入处理阶段,这样就可以通过并行处理多个请求进一步降低延迟,这个设置一般叫做pipeline深度。增大pipeline深度虽然可能一定程度上降低延迟,但有让同一个连接上的请求的实际执行顺序与输入顺序不同的风险,因而一般默认是不开启的。
读取请求、解析请求的部分则一般没有限制,如果一次发送大量的不含消息体的请求,读取请求的部分可以在一次系统调用中将这些数据全部读回,对HTTP服务的性能也有一定帮助。
这些实现和调用HTTP/1.1服务的技术统称pipelining,它实际上也不是HTTP独有的技术,而是许多协议上都可以使用的。
即使使用了pipelining技术,HTTP/1.1的协议在消息分片设计上仍然有其缺陷,主要问题在于如果前一个请求响应很慢,则后续的请求都会被阻塞,因此实际使用中往往仍然需要对服务器建立并发的多个连接。多个TCP连接的方案主要会产生以下问题:
而HTTP/2的设计就可以实现单个连接的完美复用。
这些都跟TCP本身是否乱序毫无关系,无论是HTTP/1.1还是HTTP/2,数据都是首先提交到TCP流,再由TCP流发送到对端的,当数据提交到TCP流的时候,它传输的顺序就已经完全确定了,HTTP/2的设计是为了让数据在提交到TCP流之前可以自由决定各自的顺序。
被各种朋友嘲笑订阅太低,比如跳舞:哥均订比你高订高,比如香蕉:我有四五万均订,七万高订,比如某表姐:日订阅破十一万人民币,比如三少:我每个月订阅都有好几十万呢,都是零花钱,比如奥斯卡:断更涨订阅,真的涨订阅……
感觉特别屈辱。
最屈辱的是经常有些新人跑过来,兴高采烈的说:蛤蟆哥哥,我均订破万了。你嫉妒的恨不得掐死他……