HTTP/2HTTP2.0是超文本传输??协议2.0,它是下一代HTTP协议。它由互联网工程任务组(IETF)的超文本传输??协议双(httpbis)工作组开发。这是自1999年http1.1发布以来的第一次更新,HTTP/2协议由SPDY演化而来。SPDY已经完成了它的使命,即将退出历史舞台(例如,Chrome在2016年初就结束了对SPDY的支持”;Nginx1.9.5+版本,Apache2.4.16+版本已经全面支持HTTP/2。上图是Akamai的HTTP/2DEMO,通过加载300张图片,比较HTTP/1.1和HTTP/2,首先让我们对HTTP/2有一个直观的体验,然后解释一下有这种感觉的原因,也就是新特性HTTP/2:binaryframingheadercompressionflowcontrolmultiplexingrequestpriorityserverpushbinaryframingbinaryframing层,是HTTP2.0性能增强的核心HTTP1.x在应用层以明文通信,HTTP2.0突破了原有在不改变HTTP1.x的语义、方法、状态码、URL和头字段的情况下性能的限制,在应用层(HTTP)和传输层(TCP)之间增加了一个二进制框架层。HTTP2.0划分了所有将信息传输到更小的消息中es和frames,并对其进行二进制编码,如下图所示,这里引入一个新的通信单元:frame帧是HTTP2.0通信的最小单位,包括帧头、流标识符、优先级值和帧载荷等其中,帧类型又可分为:DATA:用于传输HTTPMessagebodyHEADERS:用于传输头域SETTINGS:用于约定客户端和服务端的配置数据。例如首次设置双向流量控制窗口大小WINDOW_UPDATE:用于调整单个流或单个连接的流量PRIORITY:用于指定或重新指定引用资源的优先级RST_STREAM:用于通知异常终止流的PUSH_PROMISE:服务器推送许可PING:用于计算往返时间并执行“活性”GOAWAY:用于通知对端停止当前连接创建流标志位,为不同的帧定义特定的消息标志类型。例如DATA帧可以使用EndStream:true表示消息通信完成;流标识位表示该帧所属的流ID;优先级值在HEADERS帧中用来表示请求的优先级;R表示保留。下面是抓包的一个HEADERS帧:另外要讲的两个概念:message和streammessage指的是逻辑HTTP报文(request/response),一系列的dataframe组成一个完整的message,比如一系列的DATAframe和一个HEADERS帧组成请求消息。流是链路中可以承载双向消息传输的虚拟通道。每个流都有一个唯一的证书标识符。为了防止两端流ID冲突,客户端发起的流ID为奇数,服务端发起的流ID为偶数。所有HTTP2.0通信都是在TCP连接上完成的,它可以承载任意数量的双向数据流Stream。相应地,每个数据流以消息的形式发送,消息由一个或多个帧组成,可以乱序发送,然后根据每个帧头中的流标识符重新组合。二进制分帧主要是为HTTP2.0的其他特性提供基础。它可以将一个数据分区封装成更小更方便的数据。首先,在单链多资源模式下,降低了服务器的链路压力,内存占用更少,链路吞吐量更大;另一方面,由于TCP链路的减少,改善了网络拥塞状态,减少了慢启动时间。使拥塞和丢包恢复更快。头部压缩HTTP1.x的每次通信(请求或响应)都会携带头部信息来描述资源属性。但是,HTTP2.0使用客户端和服务器之间的头表来跟踪和存储之前发送的键值对。header表在连接过程中一直存在,新加入的键值对会更新到表尾,所以不需要每次通信都携带header,request和responseheaders的定义基本保持不变在HTTP2.0中。另外,HTTP2.0采用了头部压缩技术,压缩算法采用HPACK,使得头部更加紧凑,传输速度更快,有利于移动网络环境。需要注意的是,HTTP2.0的头部压缩与我们常用的gzip等数据包内容压缩并不冲突。流量控制HTTP/2.0“流”的流量控制目标是允许在不更改协议的情况下使用多种流量控制算法。流量控制特定于连接。每种类型的流量控制都在单个跃点中的两个端点之间,而不是在整个端到端路径上。(这里的一跳是指HTTP连接的一跳,不是IP路由的一跳)流量控制是基于WINDOW_UPDATE帧。接收方宣布它打算在每个流和整个连接上接收多少字节。这是一个基于信用的计划。流量控制是定向的,完全由接收方控制。接收方可以为每个流和整个连接设置任意窗口大小。发送方必须遵守接收方设置的流量控制限制。client、server、中间proxy在作为receiver时都独立宣布自己的流控窗口,在作为sender时服从对端的流控设置。流量控制窗口的初始值为65535字节,无论是对于新流还是整个连接。帧类型决定是否对帧应用流量控制。目前只有DATA帧需要进行流控,其他类型的帧不占用流控窗口空间。这确保了重要的控制帧不会被流量控制阻塞。无法禁用流量控制。HTTP/2只定义了WINDOW_UPDATE帧的格式和语义,并没有指定接收方如何决定何时发送帧,发送什么值,也没有指定发送方如何选择发送数据包。实现可以选择任何满足要求的算法。多路复用在HTTP1.1中,浏览器客户端同时对同一个域名有一定数量的请求。超过限制的请求将被阻止,HTTP2.0中的多路复用优化了这一性能。基于二进制框架层,HTTP2.0可以在共享TCP连接的基础上同时发送请求和响应。HTTP报文在不破坏报文本??身语义的情况下被分解成独立的帧,交错发送出去,最后在另一端根据流ID和报头重新组装。让我们比较一下HTTP1.x和HTTP2.0。这里不考虑HTTP1.x的管道机制。HTTP2.0成功解决了HTTP1.x的队头阻塞问题(TCP层的阻塞仍然无法解决),同时不需要多个TCP连接通过管道机制实现并行请求和回应。减少TCP连接数大大提高了服务器性能,同时也消除了不必要的延迟,从而减少了页面加载时间。请求优先级将HTTP报文分成许多独立的帧后,可以通过优化这些帧的交织和传输顺序来进一步优化性能。每个流可以有一个31位的优先级值:0表示最高优先级;2的31次方-1表示最低优先级。客户端明确指定优先级,服务端可以以此优先级作为交互数据的依据。例如,客户端优先级设置为.css>.js>.jpg。服务器按此顺序返回结果,更有利于底层连接的高效利用,提升用户体验。但是在使用请求优先级时,需要注意服务器是否支持请求优先级,是否会造成队头阻塞问题。例如,高优先级的慢响应请求会阻塞其他资源的交互。服务端推送HTTP2.0增加了服务端推送功能,服务端可以根据客户端的请求提前返回多个响应,向客户端推送额外的资源如下图,客户端请求流1(/page.html).服务器推送stream2(/script.js)和stream4(/style.css),同时返回stream1的消息。PUSH_PROMISE帧是服务器打算向客户端推送资源的信号。PUSH_PROMISE帧只包含预推资源的头部。如果客户端对PUSH_PROMISE帧没有意见,服务器在PUSH_PROMISE帧后发送响应DATA帧。如果客户端已经缓存了资源,不需要推送,可以拒绝PUSH_PROMISE帧。PUSH-PROMISE必须遵循请求-响应原则,只有响应请求才能推送资源。PUSH_PROMISE帧必须在返回响应之前发送,以避免客户端出现竞争条件(竞争条件是指在多线程的情况下,不同的执行顺序会导致计算机执行不同正确性的不同结果)HTTP2.0之后。0连接,客户端和服务端交换SETTINGS帧,从而限制双向最大并发数。因此,客户端可以限制推送流的数量,或者通过仅将其设置为0来完全禁用服务器推送。所有推送的资源都必须遵守同源策略。也就是说,服务端不能随便向客户端推送第三方资源,必须经过双方确认。HTTP/2现在已经被大部分浏览器支持,但是HTTP/2在使用过程中需要使用1.0.1e之后的openssl版本。通过nginx-V可以查看nginx的openssl版本。如果版本低,重新编译nginx即可。那么如何在nginx中配置对HTTP/2的支持呢?很简单,只需要在服务器中的listen部分添加http2即可。有很多方法可以测试是否启用了http2。这里介绍三种方法:1.浏览器开发者工具2.Chrome扩展HTTP/2和SPDY指示器3.命令行客户端nghttp另外,HTTP/2服务器推送需要配置nginx才能有效使用。本例将demo.html需要的资源style.css、image1.jpg、image2.jpg通过http2_push命令推送到客户端。在资源少的情况下,我们可以这样使用,但是在资源多的情况下,这种方法就不现实了。自动向客户端推送资源nginx支持拦截链接预加载头的协议。要推送此写入标头中标识的资源,您需要在配置中开始预加载。配置http2_push_preloadon也有问题。对于一般的静态资源,我们都会设置Cache的有效期。当客户端资源在缓存有效期内时,我们强制推送静态资源,只会增加服务器带宽的压力,所以我们需要指定客户端是否需要这些资源,不太可能已经被缓存。可能的方法是客户端服务器在第一次访问时推送客户端,在后续的访问请求中包含cookie。服务端通过cookies来判断是否推送,即有选择地向客户端推送资源。配置方法如下:测试如下:TLS1.3TLS(TransportLayerSecurityProtocol的主要目的是提供数据通信应用程序之间的隐私和完整性。该协议由两层组成:TLSRecordProtocol(TLSRecord)以及TLS握手协议(TLSHandshake),TLS协议已经更新了很多次,目前TLS的低版本,比如SSL3.0/TLS1.0,存在很多严重的漏洞,目前主流支持的TLS协议版本是1.1和1.2,但他们已经落后于时代的需求。2018年8月,IETF终于宣布TLS1.3规范正式发布,标准规范定义在rfc8446中。相比之前的版本,TLS优化内容如下:与上一版本相比,引入了新的密钥协商机制——PSK支持0-RTT数据传输,节省了建立连接时的往返时间。弃3DES、RC4、AES——CBC等加密组件抛弃了SHA1、MD5等散列算法。ServerHello之后的所有握手消息都是加密的。可以看出明文大大减少了。不再允许对加密消息进行压缩,也不再允许双方发起重新协商。DSA证书不允许在TLS1.3中使用。在https中,每次连接的TLS握手是非常耗费资源和时间的。因此,TLS1.3的优化相比上一版本减少了一个RTT的连接建立时间。同样的情况下,节省了很多时间,提高了响应速度。TLS1.3需要openssl1.1.1支持,在nginx上,需要nginx1.13+支持。编译nginx时需要添加编译参数--with-openssl-opt=enable-tls1_3开启TLS1.3支持,在配置中的ssl_protocols中添加TLSv1.3。对应的TLS1.3引入了新的算法,所以ssl_ciphers也需要加入新的算法。默认情况下,出于安全原因,nginx不启用TLS1.3的0-RTT。它可以通过命令ssl_early_dataon启用。ECCECC(Ellipticcurvecryptography,椭圆曲线密码学),一种建立公钥的算法,基于椭圆曲线数学。内置ECDSA公钥的证书一般称为ECC证书,内置RSA公钥的证书一般称为RSA证书。ECC算法的数学理论非常高深复杂,在工程应用中实现难度较大,但单位安全强度较高,破译或破解难度基本呈指数级增长,黑客难以利用通常的蛮力破解方法来破解。RSA算法的特点之一是数学原理比较简单,在工程应用中比较容易实现,但其单位安全强度较低。因此,ECC算法能够以较小的计算能力提供比RSA加密算法更高的安全强度,有效解决了“提高安全强度必须增加密钥长度”的工程实现问题。ECC算法与RSA算法相比有以下优点:更适合移动互联网:ECC加密算法的密钥长度很短(256位),这意味着它占用的存储空间更少,CPU开销更低占用带宽少。随着越来越多的用户使用移动设备完成各种在线活动,ECC加密算法为移动互联网安全提供了更好的客户体验。更好的安全性:ECC加密算法提供了比目前其他加密算法更强的保护,可以更好地防止攻击,使您的网站和基础设施比传统的加密方式更安全,为移动互联网安全提供更好的保障。更好的性能:ECC加密算法需要更短的密钥长度以提供更好的安全性。例如,256位的ECC密钥的加密强度相当于3072位的RSA密钥的级别(目前常用的RSA密钥长度为2048位)。结果是以更少的计算能力为代价获得更高的安全性。经国外有关权威机构测试,Apache和IIS服务器使用ECC算法,Web服务器响应时间比RSA快十倍以上。更高的IT投资回报:ECC有助于保护您的基础设施投资,提供更高的安全性,并快速应对移动设备安全连接的爆炸式增长。ECC的密钥长度增加比其他加密方式慢(一般增加128位,而RSA增加倍数,如:1024-2048--4096),这将延长您现有硬件的使用寿命,让您的投资获得更大的回报.但是,在使用ECC证书时需要注意两个问题:1.并非所有类型的证书都支持ECC。一般需要商用证书增强版支持。2.部分旧设备或浏览器不支持ECC,可能需要ECC+RSAdualBrotli是Google于2015年9月推出的一种无损压缩算法,Brotli使用了LZ77算法的变体,哈夫曼编码,二阶文本建模压缩数据。与其他压缩算法相比,它具有更高的压缩效率。根据谷歌发布的一份报告,Brotli具有以下特点:对于常见的网络资源内容,Brotli的性能比Gzip高17-25%;Brotli压缩级别为1时,压缩比高于Gzip压缩级别9(Highest);Brotli在处理不同的HTML文档时仍然可以提供非常高的压缩率。brotli支持必须依赖HTTPS,nginx支持brotli必须编辑添加brotli模块brotli模块源码地址https://github.com/eustas/ngx_brotli.git,下载后在编译nginx时传入编译参数--add-module=/path/to/ngx_brotli编译添加。添加后,通过在配置文件中添加配置来启用brotli。在开发人员工具中查看标头:立即优化您的HTTPS!
