个人博客

现代网络协议栈中最靠近应用侧的,除了应用层协议,就数传输层协议了。传输层有两大协议:TCP、UDP。两个协议最大的区别是:tcp 提供可靠传输,udp 提供不可靠传输。

经过几十年的打磨,tcp 取得了辉煌的成就,目前绝大部分的 Web 应用都建立在 TCP 传输机制之上,除了保证数据一定会送达,tcp 还提供了按序到达、拥塞控制、数据完整性保障等能力。要优化性能,是避不开 tcp 的,这快优化主要是在系统层面做。

如何优化呢 ?

三次握手

每个 tcp 传输都始于三次握手,正常情况下,需要等到握手完成后才能开始传输数据。客户端可以在发送完 ack 后立即发送数据包,但服务端必须要等接收到这个 ack 后,才能开始发送数据,如此一来,数据传输就增加了一个网络往返时间的延迟。

如果我们进行的是大文件传输,或者多个请求共享一个长连接,自然可以通过拉长时间来分摊成本,但在大量短连接的场景,则代价就显得很大了。

针对这个问题,提出了 TCP 快速打开(TFO,TCP Fast Open):允许在握手的 SYN 报文中携带数据。这种方案也有其限制,所以默认是不开启的。

另一种避免三次握手延迟的方案是复用 tcp 连接,如今 http/1.1 默认是长连接机制。

接收窗口(rwnd)

为了预防发送端发送了过多的数据给接收端,导致接收端无法处理,连接的双方在发送报文时均需要通告自己的接收窗口(rwnd)大小,以便对端可以及时调整。第一次连接时,发送的接收窗口大小都是系统设置好的默认值。

即使带宽足够,如果通告的接收窗口过小,也无法充分利用起来。目前结合 TCP 窗口缩放,接收窗口大小已经可以设置到 1G。

拥塞窗口(cwnd)

在 tcp 连接建立之初,不用一包一 ack,可以一口气向网络上发送多少数据呢?这个问题由慢启动算法负责。

根据 慢启动算法(slow start),有一个预设的保守值 — 拥塞窗口大小(cwnd),用来约束初次发送的数据量,该值不会通告给对端,但发送端在发送时会根据 min(rwnd, cwnd) 值来决定可以发送的数据量。目前 cwnd 的值一般会设置为 10 个 tcp 段,这就是前段时间 hackernews 上讨论比较多的 Why-your-website-should-be-under-14kb-in-size 这篇博文的理论依据(10 x 1460 = 14600 bytes ≈ 14 kb)—— 多好的理论联系实际的例子 🤨。

慢启动算法是对网络可用带宽的试探,每次收到一个 ack 拥塞窗口就增长两个大小,一段时间后达到对端的接收能力极限(rwnd)后稳定下来。在使用长连接时,在连接空闲一段时间后,拥塞窗口会因为 SSR(Slow-Start Restart)机制而被重置回最初的默认值(如 10 个 tcp 段),从而开启又一次慢启动过程。在互联网这种不稳定的环境中保守一点是可以理解的,但在网络环境相对稳定的企业内网,则增加了不必要的延迟,可以考虑禁用 SSR 以减少延迟。

队首阻塞

tcp 协议保障报文的顺序,简化了上层的编程模型,但实际传输过程中,报文并不是按序到达的,由于路由路径不同,或者中途有报文丢失,导致序号靠后的报文先到达接收端,先到达的报文需要等待前序报文到达后,才能组装为完整的数据提交给应用,这就引入了不可预知的延迟。

如果无需按序交付、能容忍分组丢失、对网络延迟或抖动要求高,可能 udp 是一种更好的选择。

无招胜有招

解决网络传输问题最好的方法就是 没有网络传输。

砍需求、砍功能点、复用 tcp 连接、非必要不传输数据、压缩必须要传输的数据、把服务器再靠近一点点。


参考:

《Web 性能权威指南》

原文地址:http://www.cnblogs.com/read-the-spring-and-autumn-annals-in-night/p/16886746.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性