目录
5.3. 浏览器处理HTML、CSS、JavaScript的流程
1. 概述
带宽、延迟、TCP与特性(三次握手、慢启动、拥塞预防等)、HTTP、优化建议等。
2. 延迟与带宽
2.1. 延迟
定义:消息或分组从信息源发送到目的地所需的时间。
构成
传播延迟 | 消息从发送端到接收端需要的时间,是信号传播距离和速度的函数。 |
传输延迟 | 把消息中所有比特转移到链路中需要的时间,是消息长度和链路速率的函数。 与客户端到服务器的远近无关,例如一个10MB的文件,在1Mbit/s的链路上需要10s,在100Mbit/s的链路上需要0.1s。 |
处理延迟 | 处理分组首部、检查位错误、确定分组目标所需要的时间。 分组到达路由器,路由器必须检测分组的首部,以确定出站路由,并且可能对数据进行检查。 |
排队延迟 | 到来的分组排队等待的时间。 若分组到达的速度超过了路由器的处理能力,分组就必须在入站缓冲区内排队。数据在缓冲区排队等待的时间,当然就是排队延迟。 |
Unix平台使用traceroute,windows平台使用tracert。列出经过的路由节点,每一跳的延迟。
2.2. 带宽
定义:逻辑或物理通信路径最大的吞吐量,由整个链路中最小容量决定。
网络核心的带宽
光纤就是一根光导管,传送光信号。金属线用于传送电信号,但信号损失、电磁干扰大、维护成本高。一般长距离的分组传输都是通过光纤完成的。
通过波分复用技术,光纤可以同时传播很多不同波长的光。一条光纤的总带宽,等于每个信道的数据传输速率乘以可复用的信道数。
网络边缘的带宽
网络边缘的带宽取决于部署技术,如拨号连接、光纤到户等。用户可用带宽取决于客户端与目标服务器之间的最低容量连接。
通过下边图,可以更加直观的理解带宽和延迟。途中服务器侧带宽大,客户端侧带宽小,所以客户端到服务器的带宽就是链路的最大带宽。
在实际应用中,追求的是高带宽和低延迟。
3. TCP/IP
TCP/IP传输协议,即传输控制/网络协议,也叫作网络通讯协议。代表一系列协议构成的协议簇,代表四层体系结构。
OSI七层网络模型,具有七个层次。
应用层 |
表示层 |
会话层 |
运输层 |
网络层 |
数据链路层 |
物理层 |
TCP/IP协议,具有四个层次。
应用层 | 对字节流按照具体协议规范进行解析,请求处理,按照协议规范返回数据。 |
运输层 | 端口 UDP TCP |
网络层 | IP地址 IP |
链路层 | MAC地址 |
IP,因特网协议,负责联网主机之间的路由选择和寻址。
TCP,传输控制协议,面向连接的、可靠的、基于字节流的传输层通信协议,为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。
4. TCP协议
4.1. 传输控制协议
TCP,传输控制协议,负责在不可靠的传输信道之上提供可靠的抽象层,向应用层隐藏了大多数网络通信的复杂细节,比如丢包重发、按序发送、拥塞控制和避免、数据完整等。采用TCP数据流可以确保发送的所有字节可以完整的被接收到,而且达到顺序一样。即TCP专门为精确传送做了优化,但未过多顾及时间。
4.2. 特点
基于字节流 |
面向连接 |
可靠通信 |
网络不佳时降低重传带来的带宽开销 |
通信连接是面向通信的两个端点,不考虑网段和节点 |
4.3. 规定
数据分片 | 发送端对数据进行分片,接收端对分片进行重组,且由TCP确定分片大小和分片与重组。 |
到达确认 | 接收端接收到分片时,根据分片数据序号向发送端发送确认。 |
超时重发 | 发送端发送分片时,启动超时定时器,如果在定时器超时后没有收到确认,则重发分片。 |
滑动窗口 | TCP连接中双方接受缓冲区大小都是固定的,接收方只允许另一方发送接收方缓冲区能接纳的数据。TCP在滑动窗口的基础上增加流量控制,避免快主机导致较慢主机的缓冲区溢出。 |
失序处理 | 作为IP数据包来传输的TCP分片可能在接收端失序,TCP会对接收的分片进行重新排序,将数据以正确的顺序交给应用层。 |
重复处理 | 作为IP数据包来传输的TCP分片可能在接收端产生重复,TCP会进行重复处理,丢弃重复分片。 |
数据校验 | 首部和数据的校验和,检测传输过程中数据变化。如果接收端验证校验和错误,将丢弃分片并不进行确认,导致发送端进行超时重发。 |
4.4. 报文格式规范
4.5. TCP对比UDP
连接角度 | TCP是面向连接的传输控制协议 UDP是无连接的数据包服务 |
可靠角度 | TCP具有高可靠性,保证传输数据的正确性,不出现乱序和丢失。 UDP传输前不建立连接,不检查数据,无确认机制,会出现丢失和乱序。 |
网络开销 | UDP具有较好的实时性,工作效率比TCP高;UDP结构比TCP简单,网络开销小。 |
4.6. 特性
4.6.1. 三次握手
所有TCP连接一开始都要经过三次握手。客户端和服务器在交换数据之前,必须就起始分组序列号、以及其他细节达成一致。处于安全考虑,序列号由两端随机产生。
握手过程分为三个阶段,分别为:
发送端SYN | 客户端选择一个随机序列号x,并发送一个SYN分组,其中可能包括其他TCP标志和选项。 |
接收端SYN ACK | 服务器给x加1,并选择一个随机序列号y,追加自己的标志和选项,然后返回响应。 |
发送端ACK | 客户端给x和y加1,并发送握手期间的最后一个ACK分组。 |
三次握手之后,客户端和服务器之间就可以通信了。这个启动通信的过程适用于所有TCP连接,因此对所有适用TCP的应用具有性能影响,因为每次传输应用数据之前,必须经历一次完整的往返。
三次握手带来的延迟使得每次创建一个新的TCP连接都要付出很大的代价。提高TCP应用性能的关键,在于重用连接。
4.6.2. 四次挥手
TCP连接断开时需要进行四次挥手的过程。
整个过程描述如下:
已建立TCP连接的两端AB,端A执行close,需要向另一端B发送FIN报文,序号为x |
端B接收到FIN报文后,发送ACK报文,确认序号为x+1 |
过一段时间,端B执行close,向另一端A发送FIN报文,序号为y |
端A收到FIN报文后,发送ACK报文,确认序号y+1 |
4.6.3. 拥塞预防与控制
可能是往返时间超过所有主机的最大中断间隔,于是主机会在网络中制造越来越多的数据报副本,使得整个网络陷入瘫痪。最终所有交换节点的缓冲区都被填满,多出来的分组必须删除。目前的分组往返时间已经设置为最大值,主机把每个分组都发送了好几次,结果每个分组的某个副本会抵达目标。这就是拥塞崩溃。
流量控制
流量控制是一种预防发送端过多向接收端发送数据报的机制。否则接收端可能因为忙碌、负载重、缓冲区既定而无法处理。为实现流量控制,TCP连接的每一方都要通告自己的接收窗口rwnd,其中包括能够保存数据的缓冲区空间大小信息。
第一次建立连接时,两端都会使用自身系统的默认配置发送接收窗口rwnd。数据传输过程中,如果其中一端跟不上数据传输,那它可以向发送端通告一个较小的窗口。这个过程贯穿于每个TCP连接的整个生命周期:每个ACK分组都会携带相应的最新的接收窗口rwnd值,以便两端动态调整数据流速,使之适应发送端和接收端的容量和处理能力。
慢启动
发送端和接收端在连接创建之初,谁也不知道可用带宽是多少,因此需要一个估算机制,然后依据网络的不断变化来动态改变速度。
根据交换数据来估算客户端和服务器之间的可用带宽是唯一的方法,也是慢启动算法的设计思路。服务器通过TCP连接初始化一个新的拥塞窗口cwnd变量,将其值设置为一个系统的保守值(Linux中就是initcwnd)。发送端不会通告cwnd变量,即发送端和接收端不会交换这个值。
拥塞窗口的大小cwnd,发送端对 从客户端接收ACK之前 可以发送数据量的限制。
新TCP连接传输的最大数据量取rwnd和cwnd的最小值,服务器每接收到一个ACK,慢启动算法就会告诉服务器可以增加cwnd。慢启动以保守的窗口初始化连接,随后每次往返都会成倍提高传输的数据量,直到超过接收端的流量控制窗口或有分组丢失为止。TCP连接的这个阶段称为指数增长阶段,因此客户端和服务器都在向网络路径的有效带宽迅速靠拢。
下图可以直观的体现出TCP连接之后,每次往返后拥塞窗口成倍增加,当出现丢包后拥塞窗口立即减少,再之后的每次往返后拥塞窗口逐步增加。
包括HTTP在内的很多应用层协议都运行在TCP之上,无论带宽有多大,每个TCP连接都必须经过慢启动阶段,不可能一上来就完全利用连接的最大带宽。
慢启动导致客户端与服务器要经过一定时间(如几十或几百毫秒)才能达到最大速度的问题,对于大型流式下载不显著,但是对于短暂的http连接、小文件传输等非常不利,常常会出现没有到达最大窗口之前连接就终断了。
了解慢启动后,就能理解为什么keep-alive、多路复用可以提升性能了。
慢启动过程数据传输图示
复用连接数据传输图示
针对TCP优化,可以从慢启动考虑,通过系统配置,增大TCP初始拥塞窗口大小。
拥塞预防
当慢启动的指数增长阶段,出现传输的数据量超过接收端流量控制窗口或出现分组丢失后,拥塞预防机制开始介入。
拥塞预防算法把丢包作为网络拥塞的标志,必须减小窗口大小,避免更多的数据报丢失。
重置拥塞窗口后,拥塞预防机制按照自己的算法增加拥塞窗口以尽量避免丢包。某个时刻再次出现丢包,于是这个过程从头开始。拥塞控制和拥塞预防在调整拥塞窗口,进而消除网络中丢包问题,所以TCP连接的吞吐量曲线呈锯齿状。
拥塞预防的算法
- 倍减加增AIMD,出现丢包时,拥塞窗口减半,之后每次往返给窗口增加一个固定值。该算法过于保守。
- 比例降速PRR,改进了丢包后的恢复速度。
带宽延迟积
发送端和接收端理想的窗口大小,一定会随着往返时间和目标传输速率而变化。无论发送端发送的数据还是接收端接收的数据超过了未确认的最大数据量,都必须停下来并等待另一方ACK确认某些分组后才能继续。
BDP带宽延迟积 = 数据链路的容量 * 端到端延迟
利用公式,知道任意两个数,都可以计算出另一个数,如可以计算出BDP做为最优窗口大小。
4.6.4. 队首阻塞
TCP保证发送端的数据发送顺序与接收端的数据接收顺序一致。如果中途有一个分组没有到达接收端,那么后续分组必须保存在接收端的TCP缓存区中,等待丢失的分布重发并到达接收端。这一切发生在TCP层,应用层对TCP缓冲区中排队的分组一无所知,必须等待分组全部到达才能访问。称为TCP队首阻塞。队首阻塞虽然使代码简洁,但是带来了未知的延迟。
下图中,发送端发出3个数据包p1、p2、p3,传输过程中p1丢失,导致接收端只收到p2、p3,由于之前序号的包没有收到,所以收到的包只能放在缓冲区中。接收端发出关于p2、p3的确认,发送端收到确认后知道包已经送达,由于没有收到p1的确认,所以发送端进行重发p1。之后,接收端收到p1。符合发送顺序的数据包,交给应用层使用。
4.7. 优化建议
服务器端 | 使用较新的操作系统 |
增大TCP初始拥塞窗口cwnd,如10 | |
禁用空闲时慢启动重启 | |
启用窗口缩放 | |
TCP快速打开 在某些条件下,允许在第一个SYN分组中发送应用程序数据。 | |
把服务器放到距离客户端近的地方,减少往返时间 | |
应用程序调优 | 减少传输冗余数据 |
发送最少的数据,如压缩 | |
服务器部署到靠近客户端的地方,如CDN | |
重用TCP连接 三次握手、慢启动,都会影响性能 |
5. HTTP
5.1. HTTP1.1
http1.1互联网标准厘清了之前版本很多歧义的地方,而且还加入了很多重要性能优化,如持久连接、分块编码传输、字节范围请求、增强的缓存机制、传输编码及请求管道,此外添加了内容、编码、字符集、语言的协商机制,添加了传输编码、缓存指令、客户端cookie等可以每次请求都协商的字段。
5.2. HTTP2.0
主要目标是改进传输性能,实现低延迟高吞吐量。虽然主版本号增加,但是所有HTTP首部、值,以及使用场景都没有改变。
现有的任何网站和应用,无需做任何修改就可以使用HTTP2.0,即为了使用HTTP2.0的好处而不用修改使用的标签。HTTP服务器必须运行HTTP2.0协议,但是用户不会受到影响。
5.3. 浏览器处理HTML、CSS、JavaScript的流程
HTML文档被解析为DOM即文档对象模型,CSS被解析为CSSOM即CSS对象模型。若js代码穿插在css和html之间,则js的执行会阻塞文档的解析,导致渲染前时间延长。所以采用样式在上、脚本在下的最佳实践。渲染和脚本执行都会受样式表的阻塞,因此必须让css最快下载完。
页面加载时间PLT
简单定义为浏览器中加载旋转图标停止旋转的时间。技术定义为浏览器中onload事件触发事件,当浏览器在文档和所有依赖资源(css、js、图片等)都下载完毕后触发该事件。
5.4. 性能
时间与用户的感觉
必须250ms内渲染页面或者提供视觉反馈,才能保证用户不离开。网络越快,pv越高,粘性越强,转化率越高。
通过资源瀑布图,可以分析性能。如查看HTTP请求各个过程的时间、TCP连接的生命周期时间。例如使用浏览器的开发者工具 。
web应用的执行主要涉及三个任务:取得资源、页面布局和渲染、javascript执行。其中渲染和脚本执行在同一个线程中交替执行,不可能并发修改DOM。所以优化运行时渲染和脚本执行很重要。但是如果网络资源获取很慢,即使渲染和脚本执行进行优化也是无济于事,所以快速获取资源才是最重要的。
TCP握手机制、流量和拥塞控制、由丢包引起的队首拥塞等特性影响性能。大多数HTTP数据流都是小型突发性数据流,而TCP则是为持久连接和大块数据传输进行优化的。网络往返时间在大多数情况下是TCP吞吐量和性能的限制因素。因此,延迟自然成为HTTP的性能瓶颈。
对比下图两个柱状图,可以清晰看出延迟越小页面加载时间越短,且比带宽的效果更加明显。
5.5. 优化应用
无法控制服务器与客户端之间的网络环境,无法控制客户的设备。可以从以下维度进行优化,服务器上的TCP和TLS优化,针对不同物理层特性、不同HTTP协议版本和最佳实践等。
最佳实践
减少DNS查找 | 每一个域名解析都需要一次网络往返,从而增加网络延迟,还会阻塞后续请求。所以要控制页面中域名数量。 |
重用TCP连接 | 尽可能使用永久连接,以消除TCP握手和慢启动的延迟。HTTP1.1默认使用持久连接。 |
减少HTTP重定向 | HTTP重定向很耗时,不同域名的重定向更加耗时,涉及DNS解析、TCP握手等延迟。 |
使用CDN 内容分发网络 | 把数据放到距离用户更近的地方,有效减少TCP连接的网络延迟,增加吞吐量。 |
去掉不必要的资源获取 | |
客户端缓存 | Cache-Control 首部用于指定缓存时间 Last-modified和ETag 首部提供验证机制 注意同时指定缓存时间和验证机制 |
传输压缩过的内容 | 传输前压缩内容,把传输的字节减至最少。 |
减少不必要的请求开销 | 较少请求的HTTP首部数据,比如cookie,节省的事件相当于几次往返的延迟时间。 |
并行处理请求和响应 |
参考
web性能权威指南