HTTPS 为什么慢?拆开 TLS 握手看

0 阅读7分钟

你在地址栏输入一个 HTTPS 网址,按下回车。页面白了一会儿,然后内容才开始出现。

你知道这段等待里有 DNS 查询、有 TCP 三次握手。但还有一段"隐形开销"经常被忽略——TLS 握手。它不传任何业务数据,却是 HTTPS 连接中最重要的"仪式"。

先说结论:TLS 握手本质上只做三件事——协商怎么加密、证明你是你、生成一次性密钥。  所有的"慢"都发生在这三件事的往返里。而 TLS 1.3 的优化不是"魔法加速",是把原本需要两轮对话才能谈妥的事,压缩到一轮里谈完。

一、握手在做什么?一张表看清

把 TLS 握手抽象成三步:

步骤做的事类比
协商参数双方同意用什么加密算法、什么版本两国建交前先商定"用英语还是法语沟通"
身份验证服务器出示证书,客户端核实"你真的是 example.com"大使递交国书,对方外交部核验印章
密钥生成双方各自计算出相同的"会话密钥",后续通信全靠它交换密电码本,之后所有电报用这本加密

三步做完,才开始传真正的 HTML/CSS/JS。

这就是为什么你第一次访问一个 HTTPS 站点时,TTFB(首字节时间)比 HTTP 要高——不是服务器响应慢,而是"安检"要时间。

二、TLS 1.2 的握手:两轮对话

TLS 1.2 的握手需要 2 个完整往返(2-RTT) 。拆开看:

第一轮往返:

• 客户端:"你好,我支持这些加密套件,选一个吧。"(Client Hello)

• 服务器:"我选这个套件,这是我的证书。"(Server Hello + Certificate)

第二轮往返:

• 客户端验证证书 → 生成预主密钥 → 用服务器公钥加密发过去

• 双方各自用"客户端随机数 + 服务器随机数 + 预主密钥"算出会话密钥

• 互发"我准备好了" → 开始加密通信

两轮才谈妥。  如果你的 RTT(一次网络往返时间)是 80ms,光 TLS 握手就要 160ms。加上 TCP 三次握手的 80ms,你的 HTTPS 请求还没发出去,已经过了 240ms。

在移动网络上(RTT 常在 150ms 以上),这个数字会变成 300ms 甚至更多——用户还没看到任何内容,半秒就过去了。

三、TLS 1.3 做了什么?把两轮压成一轮

TLS 1.3 的核心优化思路可以用一句话概括:别等服务器告诉你用什么算法,先猜着传过去。

具体怎么做的:

Client Hello 里直接带上密钥参数——客户端不再等服务器选好算法后才开始密钥交换,而是在第一条消息里就把"我猜你会选 X25519,这是我的 DH 参数"一起发出去

服务器一次性回完所有内容——收到 Client Hello 后,服务器已经拥有计算主密钥所需的一切信息,于是证书、签名、"我准备好了"全部打包在一条回复里发出

结果:1-RTT 搞定。  同样 80ms 的网络,TLS 1.3 只需要 80ms 完成握手,直接省掉一半时间。

为什么猜得准?  因为 TLS 1.3 大幅删减了密码套件的选项——从 TLS 1.2 时代的几十种组合缩减到寥寥数种安全套件。选项少了,猜对概率极高。

这就像去一个只有三道菜的餐厅点餐——你大概率能猜到对方想吃什么,不用再多问一轮。

四、0-RTT:常客免检通道

TLS 1.3 还有一个杀手特性:0-RTT 会话恢复

如果你之前访问过这个网站,双方曾经建立过信任关系,TLS 1.3 允许客户端在第一条消息里就带上加密的应用数据——不用等握手完成。

场景往返次数时间开销(RTT=80ms)
TLS 1.2 完整握手2-RTT160ms
TLS 1.3 完整握手1-RTT80ms
TLS 1.3 会话恢复0-RTT~0ms

这就是物流中的"预清关 + 常客免检"。  集装箱还没到港(请求还没到服务器),货物已经在卸了(应用数据已经在传了)。

但 0-RTT 有个安全代价:它不具备完全的前向保密性,且存在重放攻击风险。所以 0-RTT 只适合幂等请求(如 GET),绝不能用于敏感写操作。

这就是工程中的 trade-off:速度快了,但安全边界收窄了。没有免费午餐。

五、前向保密:不是保险箱,是碎纸机

TLS 1.3 有一个经常被低估的安全升级:强制前向保密(Forward Secrecy)

多数人对加密安全的心智模型是"保险箱"——私钥就是钥匙,藏好钥匙就安全了。但 TLS 1.2 的 RSA 模式有个致命问题:如果攻击者先把你所有加密流量录下来,等哪天你的私钥泄露了,他可以回过头来把历史流量全部解密。

TLS 1.3 的前向保密不是保险箱,更像碎纸机

• 每次会话使用临时的 Diffie-Hellman 密钥对

• 会话结束后,临时密钥立即销毁

• 即使服务器私钥日后泄露,过去的对话也无法被解密——因为解码器已经进了碎纸机

TLS 1.3 不再给你"可选前向保密"的选项——它是强制的。这个设计哲学的转变是:安全不能靠人记得开,要靠协议默认关上不安全的门。

六、对前端意味着什么?

作为前端开发者,TLS 握手不是你能直接写代码优化的东西。但你能做的是减少握手发生的次数和影响

优化手段原理操作
<link rel="preconnect">提前完成 DNS+TCP+TLS,资源请求时握手已就绪对关键 CDN、字体域名使用
减少第三方域名每个新域名都是一次独立的完整握手合并供应商、自托管关键资源
确认 TLS 1.3 已启用从 2-RTT 降到 1-RTT,纯配置收益检查 CDN/WAF 设置
HTTP/2 多路复用单连接承载所有请求,避免多次握手确保没有不必要的域名分片
HTTP/3 (QUIC)传输层和 TLS 握手合并,进一步减少往返评估 CDN 是否支持

一个实用的性能基准(p75 参考):

TLS 握手时间评估
< 100ms✅ 优秀,边缘节点近、TLS 1.3
100–200ms正常,移动网络可接受
200–400ms⚠️ 需关注
> 400ms🔴 可能伤害业务转化

记住一个诊断模式:如果你的 TTFB 高,先看是不是 TLS 握手吃掉了时间。如果是,问题出在网络/连接层,而不是服务器代码。

七、一张图串起全貌

用户输入 URL → DNS 查询(~20ms) → TCP 三次握手(1-RTT)
    ↓
TLS 1.2 握手(2-RTT)  或  TLS 1.3 握手(1-RTT)
    │                          │
    │  Client Hello            │  Client Hello + DH 参数
    │  ← Server Hello+Cert     │  ← Server Hello+Cert+完成
    │  密钥交换→               │
    │  ← 完成                  │  直接开始传数据
    ↓                          ↓
加密传输 HTML/CSS/JS...

TCP + TLS 总开销

• TLS 1.2:3-RTT(TCP 1 + TLS 2)

• TLS 1.3:2-RTT(TCP 1 + TLS 1)

• TLS 1.3 + 0-RTT 恢复:1-RTT(TCP 1 + TLS 0)

每减少一个 RTT,在 80ms 网络上省 80ms,在 150ms 移动网络上省 150ms。对高延迟用户来说,这是真金白银的体验提升。


如果你只想带走一句话,我建议记这个:

TLS 握手的"慢"不是浪费——它是信任的建立成本。TLS 1.3 的贡献不是取消安检,而是让安检流程从"排两次队"变成"排一次队"。

理解了这个,你就能合理预期 HTTPS 的连接开销,也能在正确的层面(preconnect、减少域名、升级 TLS 版本)去优化它。


参考原文:

• Cloudflare Learning Center — What happens in a TLS handshake?

qrcode_for_gh_6a9e7f3719d6_344.jpg