【翻译】为什么你的网站大小应该控制在14kB以内
原文:https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/
网站体积更小,加载速度就更快——这一点不足为奇。
但令人惊讶的是,一个14kB的页面可能比15kB的页面加载快得多,说不定能快612毫秒,而15kB和16kB的页面之间,加载速度的差异就微不足道了。
这背后的原因是TCP慢启动算法。本文会介绍这个算法是什么、如何运作,以及为什么你需要关注它。不过首先,我们先快速了解一些基础知识。
什么是TCP?
传输控制协议(TCP)是一种借助互联网协议(IP)来可靠发送数据分组的方式,有时也被称为TCP/IP。
当浏览器请求你的网站(或图片、样式表)时,会通过HTTP发起请求。HTTP建立在TCP之上,一个HTTP请求通常由多个TCP数据包组成。
IP本身只是一种将数据包从互联网上的一个位置发送到另一个位置的系统,它无法检查数据包是否成功到达目的地。
对于网站来说,确认所有数据都已送达至关重要,否则网页可能会出现内容缺失。但在网络的其他用途中,比如直播流,这一点就没那么重要了。
TCP是IP的扩展,它能让浏览器和网站服务器互相告知哪些数据包已成功接收。服务器先发送一些数据包,然后等待浏览器返回确认信息(即ACK),之后再发送更多数据包;如果没收到确认,服务器就会重新发送这些数据包。
什么是TCP慢启动?
TCP慢启动是服务器用来确定一次可以发送多少数据包的算法。
当浏览器首次与服务器建立连接时,服务器并不知道两者之间的带宽有多大。
带宽指的是单位时间内可通过网络传输的数据量,通常以比特每秒(b/s)为单位。用一个常见的比喻来说,带宽就像水管每秒能流出的水量。
服务器不清楚连接能处理多少数据,所以一开始会发送少量且安全的数据量,通常是10个TCP数据包。
如果这些数据包成功到达访客的设备,设备会返回一个确认信息(ACK),告知已收到数据包。
接着,服务器会再次发送数据,这次发送的数据包数量会翻倍。
这个过程会一直重复,直到出现数据包丢失、服务器未收到确认信息为止(此时服务器会继续发送数据包,但速度会减慢)。
这就是TCP慢启动的大致原理,实际中算法会有所不同,但核心逻辑就是这样。
那14kB这个数值从何而来?
大多数网络服务器的TCP慢启动算法一开始会发送10个TCP数据包。
一个TCP数据包的最大容量是1500字节。这个最大值并非由TCP规范设定,而是源自以太网标准。
每个TCP数据包的头部会占用40字节——16字节用于IP,另外24字节用于TCP。
这样一来,每个TCP数据包实际可传输的数据量为1460字节。10×1460=14600字节,约合14kB!
所以,如果你能把网站(或其关键部分)的体积控制在14kB以内,就能为访客节省大量时间——也就是访客与网站服务器之间一次往返的时间。
一次往返的延迟会有多严重?
人们都很没耐心,而一次往返的延迟可能会出奇地长。具体时长取决于延迟本身……
延迟是指数据包从源地址传输到目的地所需的时间。如果说带宽是水管每秒的出水量,那延迟就是一滴水从进入水管到从另一端流出所花费的时间。
举个能体现延迟有多糟糕的有趣例子:
卫星互联网
卫星互联网由环绕地球运行的卫星提供,供偏远地区居民、石油钻井平台、游轮以及航空公司的机上WiFi使用。
为了说明这种糟糕的延迟情况,我们来想象一下:一群石油钻井平台的伙计们忘带骰子了,需要用优秀的(小于14kB的)missingdice.com网站玩《龙与地下城》。
首先,其中一个人用手机请求这个网页……
手机把请求发送到钻井平台的WiFi路由器,再传到平台上的卫星天线——假设这一步花了1毫秒。
然后,卫星天线需要把数据发送到地球轨道上的卫星。
这类卫星通常位于距离地球表面35786公里的地球静止轨道上。光速为299792458米/秒,所以从地球发送消息到卫星需要120毫秒,卫星再把消息发回地面站,又需要120毫秒。
之后,地面站要把请求发送到服务器所在的位置(光在光纤中的传播速度会降至2亿米/秒)。如果地面站到服务器的距离相当于纽约到伦敦的距离,大约需要28毫秒;如果更接近纽约到悉尼的距离,则需要80毫秒——我们取个方便计算的中间值,60毫秒。
接着,服务器处理请求可能需要10毫秒,然后服务器会把响应数据原路返回。
数据先回到地面站,再上传到卫星,接着传回卫星天线,然后到WiFi路由器,最后回到那位石油工人的手机上。
整个路径是:
手机→WiFi路由器→卫星天线→卫星→地面站→服务器→地面站→卫星→卫星天线→WiFi路由器→手机
计算一下,总延迟是10 +(1 + 120 + 120 + 60)× 2 = 612毫秒。
这意味着每一次往返都要多花612毫秒——或许这看起来不算太长,但网站光是获取第一个资源,就可能需要多次往返。
而且,HTTPS在第一次传输前还需要额外两次往返,这样一来延迟就会达到1836毫秒!
对于陆地上的用户,延迟情况如何?
卫星互联网或许是个特意选的极端例子——我选它是因为它能很好地说明问题,而且有点特别——但对于陆地上的用户来说,延迟也可能因为各种原因变得更糟:
- 2G移动网络的延迟通常在300毫秒到1000毫秒之间
- 3G网络的延迟在100毫秒到500毫秒之间
- 信号嘈杂的移动网络,比如在音乐节这种人群异常密集的地方
- 服务器处理大量流量时
- 其他各种问题
不稳定的连接还可能导致数据包丢失,这就需要再一次往返来获取丢失的数据包。
了解了14kB规则后,你能做些什么?
当然,你应该尽可能缩小网站体积——毕竟你关心访客,希望他们有良好的体验。把每个页面的体积控制在14kB以内是个不错的目标。
这14kB包含压缩后的大小,所以实际未压缩的数据可能有50kB左右,这已经很宽裕了。要知道,阿波罗11号的制导计算机内存也才72kB。
只要去掉自动播放的视频、弹窗、Cookie、Cookie同意横幅、社交网络按钮、跟踪脚本、JavaScript和CSS框架,以及所有没人喜欢的冗余内容,你的网站体积可能就已经达标了。
不过,就算你已经尽力想把所有内容塞进14kB却没能做到,这个14kB规则仍然有用。
你可以确保发送给访客的前14kB数据能用来渲染出一些有用的内容,比如关键的CSS、JS代码,以及前几段解释应用使用方法的文字。
注意:14kB规则包含HTTP头部(即使在HTTP/2中,第一次响应的头部也是未压缩的),也包含图片,所以只加载首屏内容,并且让它们体积非常小,或者使用占位符让访客知道正在加载内容。
这条规则的一些注意事项
14kB规则更像是一种经验之谈,而非计算机领域的基本定律:
- 有些服务器已经将TCP慢启动的初始窗口从10个数据包增加到了30个
- 有时服务器通过TLS握手确定可以使用更大的窗口,就会一开始发送更多数据包
- 服务器可以缓存某条路径能处理的数据包数量,下次连接时就会发送更多
还有其他一些注意事项,这篇更深入的文章解释了为什么14kB规则并非在所有情况下都适用。
HTTP/2与14kB规则
有一种观点认为,使用HTTP/2时,14kB规则就不再适用了。我查阅了很多资料(过程差点没烦死),但没发现有证据表明使用HTTP/2的服务器会放弃以10个数据包为起始的TCP慢启动。
HTTP/3与QUIC
和HTTP/2类似,也有人认为HTTP/3和QUIC会让14kB规则失效——但事实并非如此,QUIC同样推荐遵循14kB规则。
原文:https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/
附录
AI解释TCP慢启动
“TCP慢启动”(TCP Slow Start)是传输控制协议(TCP)中一个非常重要的拥塞控制算法。它的核心思想是:当一个TCP连接刚建立时,发送方并不知道网络的实际承载能力,为了避免一开始就发送大量数据导致网络拥塞,它会缓慢地、逐步地增加发送数据的速率。
你可以把这个过程想象成一个人进入一个陌生房间。他不会一进去就大喊大叫,而是会先轻声说话,观察一下房间里的人(网络设备)的反应,确认大家都能听到他说话,然后才慢慢提高音量。
为什么需要慢启动?
- 避免网络拥塞: 建立连接时,发送方对网络的带宽、路由器/交换机的处理能力、接收方的缓存大小等一无所知。如果一开始就全速发送数据,很可能会迅速压垮网络中的某个环节,导致大量丢包,进而引发网络拥塞,影响所有用户。
- 发现网络带宽: 慢启动通过逐步增加发送量,像一个“探测器”,小心翼翼地试探网络的实际承载能力。
- 公平性: 它确保新的连接不会一下子就占用大量带宽,从而更公平地与其他现有连接共享网络资源。
慢启动的工作原理
慢启动主要通过一个叫做拥塞窗口(Congestion Window,cwnd
)的变量来控制发送速率。
-
初始状态:
- 当一个新的TCP连接建立时,
cwnd
会被初始化为一个很小的值,通常是1到10个最大报文段(Maximum Segment Size, MSS)。MSS 是TCP传输的单个数据包的最大大小。这意味着发送方一开始只允许发送少量的数据。
- 当一个新的TCP连接建立时,
-
指数增长阶段:
- 发送方发送这些数据包。
- 每当发送方收到一个确认(ACK),它就会增加
cwnd
的大小。具体来说,收到一个 ACK 就会让cwnd
增加一个 MSS。 - 由于每收到一个 ACK,
cwnd
就会增加,并且一个往返时间(RTT)内通常会收到多个 ACK(例如,如果发送了2个报文段,会收到2个ACK),所以在一个 RTT 内,cwnd
会呈指数级增长。- 例如:
- 初始
cwnd
= 1 MSS - 发送 1 MSS,收到 ACK,
cwnd
变为 2 MSS - 发送 2 MSS,收到 2个 ACK,
cwnd
变为 4 MSS (1 + 2 = 3; 3 + 1 = 4 MSS) - 发送 4 MSS,收到 4个 ACK,
cwnd
变为 8 MSS
- 初始
- 例如:
- 这个指数增长会持续进行,直到达到一个预设的慢启动阈值(Slow Start Threshold,
ssthresh
)。
-
进入拥塞避免阶段:
- 一旦
cwnd
达到或超过ssthresh
,TCP就会退出慢启动阶段,进入拥塞避免(Congestion Avoidance)阶段。 - 在拥塞避免阶段,
cwnd
的增长速度会放慢,变成线性增长:通常每收到一个 RTT 内的所有 ACK,cwnd
才增加一个 MSS。这是为了更谨慎地探测网络,避免过度占用带宽。
- 一旦
-
发生拥塞(丢包)时:
- 如果在慢启动或拥塞避免过程中发生了丢包(通常通过超时或收到重复 ACK 来判断),TCP会认为网络发生了拥塞。
- 这时,
ssthresh
会被设置为当前cwnd
的一半。 cwnd
通常会被重置回初始的较小值(例如1 MSS),然后再次进入慢启动阶段。这就像在路上遇到堵车,司机决定从头再来,小心翼翼地重新加速。
总结
TCP慢启动是一种优雅而高效的机制,它让TCP连接在开始时能够自我调节,逐步适应网络环境,从而有效地避免了网络拥塞,并帮助发送方发现网络的可用带宽。尽管名字叫做“慢启动”,但在没有拥塞的情况下,它的拥塞窗口会呈指数增长,使得连接能够相对快速地达到网络的容量上限。