HTTP性能极限优化 |
您所在的位置:网站首页 › 响应报文格式怎么写好呢 › HTTP性能极限优化 |
无论你在做前端、后端还是运维,HTTP都是不得不打交道的网络协议。它是最常用的应用层协议,对它的优化,既能通过降低时延带来更好的体验性,也能通过降低资源消耗带来更高的并发性。 可是,学习HTTP不久的同学,很难全面说出HTTP的所有优化点。这既有可能是你没好好准备过大厂的面试:-),也有可能你没有加入一个快速发展的项目,当产品的用户量不断翻番时,需求会倒逼着你优化HTTP协议。 这篇文章是根据我在2019年GOPS全球运维大会上海站的演讲PPT,重新提炼文字后的总结。我希望能从四个全新的维度,带你覆盖绝大部分的HTTP优化技巧。这样,即使还不需要极致方法去解决当前的性能瓶颈,也会知道优化方向在哪,当需求来临时,能够到Google上定向查阅资料。
第一个维度,是从编码效率上,更快速地把消息转换成更短的字符流。这是最直接的性能优化点。 一、编码效率优化如果你对HTTP/1.1协议做过抓包分析,就会发现它是用“whitespace-delimited”方式编码的。用空格、回车来编码,是因为HTTP在诞生之初追求可读性,这样更有利于它的推广。 然而在当下,这种低效的编码方式已经严重影响性能了,所以2009年Google推出了基于二进制的SPDY协议,大幅提升了编码效率。2015年,稍做改进后它被确定为HTTP/2协议,现在50%以上的站点都在使用它。 然而这些新技术到底是怎样提升性能的呢?那还得拆开了看,先从数据的压缩谈起。你抓包看到的是数据,它并不等于信息。数据其实是信息和冗余数据之和,而压缩技术,就是尽量地去除冗余数据。 再来看无损压缩,你肯定用过gzip,它让http body实现了无损压缩。肉眼阅读压缩后的报文全是乱码,但接收端解压后,可以看到发送端的原文。然而,gzip的效率其实并不高,以Google推出的brotli做对比,你就知道它的缺陷了: 说完对body的压缩,再来看HTTP header的压缩。对于HTTP/1.x来说,header就是性能杀手。特别是当下cookie泛滥的时代,每次请求都要携带几个KB的头部,很浪费带宽、CPU、内存!HTTP2通过HPACK技术大幅度降低了header编码后的体积,这也是HTTP3的演进方向。 HPACK到底是怎样实现header压缩的呢? HPACK通过Huffman算法、静态表、动态表对三种header都做了压缩。比如上图中,method GET存在于静态表,用1个字节表示的整数2表达即可;user-agent Mozilla这行头部非常长,当它第2次出现时,用2个字节的整数62表示即可;即使它第1次出现时,也可以用Huffman算法压缩Mozilla这段很长的浏览器标识符,可以获得最多5/8的压缩率。 静态表中只存放最常见的header,有的只有name,有的同时包括name和value。静态表的大小很有限,目前只有61个元素。 Huffman编码在winrar等压缩软件中广为使用,但HPACK中的Huffman有所不同,它使用的是静态huffman编码。即,它统计了互联网上几年内的HTTP头部,按照每个字符出现的概率,重建huffman树,这样,根据规则,出现次数最多的a、c、e或者1、2、3这些字符就只用5个bit位表示,而很少出现的字符则用几十个bit位表示。 说完header,再来看http body的编码。这里只举3个例子:1、只有几十字节的小图标,没有必要用独立的HTTP请求传输,根据RFC2397的规则,可以把它直接嵌入到HTML或者CSS文件中,而浏览器在解析时会识别出它们,就像下图中的头像: 3、在表单中,可以一次传输多个元素,比如既有复选框,也可以有文件。这就减少了HTTP请求的个数。 可见,http协议从header到 body,都有许多编码手段,可以让传输的报文更短小,既节省了带宽,也降低了时延。
编码效率优化完后,再来看“信道”,这虽然是通讯领域的词汇,但用来概括HTTP的优化点非常合适,这里就借用下了。 二、信道利用率优化信道利用率包括3个优化点,第一个优化点是多路复用!高速的低层信道上,可以跑许多低速的高层信道。比如,主机上只有一块网卡,却能同时让浏览器、微信、钉钉收发消息;一个进程可以同时服务几万个TCP连接;一个TCP连接上可以同时传递多个HTTP2 STREAM消息。
最后,就像经济学里说的,资源总是稀缺的。有限的带宽下,如何公平的对待不同的连接、用户和对象呢?比如下载页面时,如果把CSS和图片以同等优先级下载就有问题,图片晚点显示没关系,但CSS没获取到页面就无法显示。另外,传输消息时,报文头报并不承载目标信息,但它又是必不可少的,如何降低这些控制信息的占比呢? 我们先从多路复用谈起。广义上来说,多线程、协程都属于多路复用,但这里我主要指http2的stream。因为http协议被设计为client先发request,server才能回复response,这样收发消息,是没办法跑满带宽的。最有效率的方式是,发送端源源不断地发请求、接收端源源不断地发响应,这对于长肥网络尤为有效: 再来看网络错误的恢复。在应用层,lingering_time通过延迟关闭连接来避免浏览器因RST错误收不到http response,而timeout则是用定时器及时发现错误并释放资源。 在传输层,通过timestamp=1可以让TCP更精准的测量出定时器的超时时间RTO。当然,timestamp还有一个用途,就是防止长肥网络中的序列号回绕。 网络错误还有很多种,比如报文的次序也是无法保证的。打开tcp_sack可以减少乱序时的重发报文量,降低带宽消耗。 实际上对于网络错误恢复,最精妙的算法是拥塞控制,它可以全面提升网络性能。有同学会问,TCP不是有流量控制,为什么还会发生网络拥塞呢?这是因为,TCP链路中的各个路由器,处理能力并不互相匹配。 自1982年TCP诞生起,就在使用传统的拥塞控制算法,它是发现丢包后再刹车减速,效果很不好。为什么呢?你可以观察下图,路由器中会有缓冲队列,当队列为空时,ping的时延最短;当队列将满时,ping的时延很大,但还未发生丢包;当队列已满时,丢包才会发生。 当Linux内核更新到4.9版本时,原先的CUBIC拥塞控制算法就被替换为Google的BBR算法了。从下图中可以看到,当丢包率达到0.01%时,CUBIC就没法用了,而BBR并没有问题,直到丢包率达到5%时BBR的带宽才剧烈下降。
最后看下TCP的报文效率,它也会影响之上的HTTP性能。比如开启Nagle算法后,网络中的小报文数量大幅减少,考虑到40字节的报文头部,信息占比更高。
说完相对微观一些的信道,我们再来从宏观上看第三个优化点:传输路径的优化。 三、传输路径优化传输路径的第一个优化点是缓存,浏览器、CDN、负载均衡等组件中,缓存无处不在。
传输路径的第二个优化点是慢启动。系统自带的TCP协议栈,为了避免瓶颈路由器丢包,会缓缓加大传输速度。它的起始速度就叫做初始拥塞窗口。
当然,修改起始窗口很简单,下图中是Linux下调整窗口的方法。
再来看传输路径上,如何从拉模式升级到推模式。比如index.html文件中包含,在HTTP/1中,必须先下载完index.html,才能去下载some.css,这是两个RTT的时间。但在HTTP/2中,服务器可以通过2个stream,同时并行传送index.html和some.css,节约了一半的时间。
解决队头阻塞的办法就是绕开TCP,使用UDP协议实现HTTP,比如Google的GQUIC协议就是这么做的,B站在几年前就使用它提供服务了。
最后,再从网络信息安全的角度,谈谈如何做优化。它实际上与编码、信道、传输路径都有关联,但其实又是独立的环节,所以放在最后讨论。 四、信息安全优化互联网世界的信息安全,始于1995年的SSL3.0。到现在,许多大型网站都更新到2018年推出的TLS1.3了。
HTTP的性能优化手段众多,从这四个维度出发,可以建立起树状的知识体系,囊括绝大部分的HTTP优化点。 编码效率优化包括http header和body ,它可以使传输的数据更短小紧凑,从而获得更低的时延和更高的并发。同时,好的编码算法也可以减少编解码时的CPU消耗。 信道利用率的优化,可以从多路复用、错误发现及恢复、资源分配这3个角度出发,让快速的底层信道,有效的承载慢速的应用层信道。 传输路径的优化,包括各级缓存、慢启动、消息传送模式等,它能够让消息更及时的发给浏览器,提升用户体验。 当下互联网中的信息安全,主要还是建立在TLS协议之上的。TLS1.3从安全性、性能上都有很大的提升,我们应当及时的升级。 希望这些知识能够帮助你全面、高效地优化HTTP协议! |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |