在长链接上,服务器可能会给浏览器发送一个包含多个资源的字节流应答,浏览器也有可能在请求流中携带多个资源。请求和应答时,必须在包头中说明本包的字节 数,这样接收者能够根据这个值截断流读取有效数据。而实际情况是,服务器和浏览器在组包的时候并不能确切得知道本包的字节数。比如,Servlet在应答 请求的时候,并不必须等到所有事务处理都完成,而是可以先返回准备好的几个字节,等其他事务处理完了再返回这些迟到的事务产生的数据。这种情况需要让接收 者知道如何截取数据,如果包头没有包的字节数数据的话。在HTTP1.0时代,服务器端只好把 content-length 字段留空,然后继续返回字节流。数据发送完成后,简单关闭连接,在结尾处加一个-1表示文件流结束了。HTTP1.1使用了一个特殊的头字段 transfer-encoding:chunked 来标识本次流传输是分块进行的,每一块的长度以16进制的形式写在块头,回车符之前。每次以分块模式传输的数据,最后一块的的字节数为0。
4、
缓存处理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。此外,HTTP1.1还加入了缓存处理(强缓存和协商缓存),新的字段如cache-control,支持断点传输,以及增加了Host字段(使得一个服务器能够用来创建多个Web站点)。
三、HTTP2.0
HTTP2.0大幅度的提高了web性能,在HTTP1.1完全语义兼容的基础上,进一步减少了网络的延迟。实现低延迟高吞吐量。对于前端开发者而言,减少了优化工作。
1、二进制分帧
在不改变HTTP1.x的语义、方法、状态码、URL以及首部字段的情况下,HTTP2.0是怎样突破HTTP1.1的性能限制,改进传输性能,实现低延迟高吞吐量的呢?关键之一就是在应用层(HTTP)和传输层(TCP)之间增加一个二进制分帧层。
在整理二进制分帧及其作用的时候我们先来铺垫一点关于帧的知识:
-
帧:HTTP2.0通信的最小单位,所有帧都共享一个8字节的首部,其中包含帧的长度、类型、标志、还有一个保留位,并且至少有标识出当前帧所属的流的标识符,帧承载着特定类型的数据,如HTTP首部、负荷、等等。
-
消息:比帧大的通讯单位,是指逻辑上的HTTP消息,比如请求、响应等。由一个或多个帧组成
-
流:比消息大的通讯单位。是TCP连接中的一个虚拟通道,可以承载双向的消息。每个流都有一个唯一的整数标识符
HTTP2.0中所有加强性能的核心是二进制传输,在HTTP1.x中,我们是通过文本的方式传输数据。基于文本的方式传输数据存在很多缺陷,文本的表现形式有多样性,因此要做到健壮性考虑的场景必然有很多,但是二进制则不同,只有0和1的合,因此选择了二进制传输,实现方便且健壮。
在HTTP2.0中引入了新的编码机制,所有传输的数据都会被分割,并采用二进制格式编码。
服务器推送有一个很麻烦的问题。所要推送的资源文件,如果浏览器已经有缓存,推送就是浪费带宽。即使推送的文件版本更新,浏览器也会优先使用本地缓存。一种解决办法是,只对第一次访问的用户开启服务器推送。下面是 Nginx 官方给出的示例,根据 Cookie 判断是否为第一次访问:
server { listen 443 ssl http2 default_server; ssl_certificate ssl/certificate.pem; ssl_certificate_key ssl/key.pem; root /var/www/html;http2_push_preload on; location = /demo.html { add_header Set-Cookie "session=1"; add_header Link $resources; }}map $http_cookie $resources {"~*session=1""";default"</style.css>; as=style; rel=preload";}
服务器推送可以提高性能,大概会比HTTP/1.1快了几百毫秒,提升程度也不是特别多,而且,也不建议一次推送太多资源,这样反而会拖累性能,因为浏览器不得不处理所有推送过来的资源。只推送 CSS 样式表可能是一个比较好的选择。
5、主动重置链接
HTTP消息被送出之后,我们就很难中断它了。当然,通常我们可以断开整个TCP链接(但也不总是可以这样),但这样导致的代价就是需要重新通过三次握手建立一个新的TCP连接。比如,很多app客户端都有取消图片下载的功能场景,对于http1.x来说,是通过设置tcp segment里的reset flag来通知对端关闭连接的,这种方式会直接断开连接,下次再发请求就必须重新建立连接。http2.0引入RST_STREAM类型的frame,使用它来让客户端在已有的连接中发送重置请求,这样可以在不断开连接的前提下取消某个request的stream,即中断或者放弃响应。当浏览器进行页面跳转或者用户取消下载时,它可以防止建立新连接。
四、HTTP3.0
HTTP 3.0,也称作 HTTP over QUIC。核心是 QUIC (读音quick)协议,由 Google 在 2015 年提出的 SPDY v3 演化而来的新协议,传统的 HTTP 协议是基于传输层 TCP 的协议,而 QUIC 是基于传输层 UDP 上的协议,可以定义成:HTTP3.0 基于 UDP 的安全可靠的 HTTP2.0 协议,主要有以下特性:
-
基于 UDP 减少了 TCP 三次握手及 TLS 握手时间
-
解决多路复用丢包时的线头阻塞问题
-
优化重传策略
-
流量控制
-
连接迁移
QUIC协议基于UDP实现摒弃了五元组的概念,使用64位的随机数作为连接的ID,并使用该ID表示连接。基于QUIC协议之下,我们在日常wifi和4G切换时,或者不同基站之间切换都不会重连,从而提高业务层的体验。
如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!