网络层面优化:DNS解析、连接数、HTTP/2与CDN加速
做接口优化,很多人一上来就改代码、调数据库。但我个人的经验是,先看看网络层面。很多时候,慢的根本不是你的代码,而是数据在网络上绕了一大圈。
这一章,我们聊四个最实用的网络优化手段。它们立竿见影。你想想看,一个接口请求,大部分时间都花在哪里?不就是DNS查询、建立连接、传输数据这几步嘛。
1. DNS解析优化:别让域名查询拖慢第一秒
一个请求过来,第一步是DNS解析。说白了,就是把域名翻译成IP地址。如果这一步慢了,后续再快也没用。
为什么会慢? 本地DNS缓存没命中,得去上级DNS服务器递归查询。跨运营商、跨地区,甚至有时候会丢包重试。我在项目中遇到过,某个接口偶尔超时,查了半天是DNS解析花了800多毫秒。
我个人习惯,从这几个角度下手:
| 优化手段 | 原理 | 适用场景 | 延迟降低效果 |
|---|---|---|---|
| DNS预解析 | 页面加载时提前解析后续域名 | Web页面、首屏加载 | 减少100-200ms |
| DNS缓存 | 延长TTL,利用本地缓存 | 所有场景 | 减少80%的DNS查询 |
| HTTPDNS | 绕过Local DNS,直连权威服务器 | 移动端App、全局负载均衡 | 显著提升稳定性 |
实践小贴士
在HTML的head里加上 <link rel="dns-prefetch" href="//api.example.com"> 就行。浏览器会尽早开始解析这个域名。
更激进一点,用 preconnect:<link rel="preconnect" href="//api.example.com">。它不仅做DNS解析,还提前完成TCP握手和TLS协商。
<!-- 示例:DNS预解析配置 -->
<head>
<meta charset="UTF-8">
<title>我的页面</title>
<!-- 提前解析静态资源域名 -->
<link rel="dns-prefetch" href="//cdn.example.com">
<link rel="dns-prefetch" href="//api.example.com">
<!-- 更进一步的预连接 -->
<link rel="preconnect" href="//api.example.com">
</head>
注意避坑
我曾经踩过一个坑:把十几个域名都配了DNS预解析。结果浏览器真的去解析了,反而占用了CPU和网络资源,首屏加载更慢了。嗯,这里要注意——只预解析关键的、马上就要用的域名。一般不超过3个。
2. 减少连接数:TCP握手和TLS握手的开销
HTTP/1.1时代,每个请求基本都要创建新连接。三次握手、四次挥手,加上TLS的证书验证、密钥交换,一次连接下来轻轻松松几百毫秒。
连接开销到底有多大? 我做个测试你就明白了:
| 连接阶段 | RTT消耗 | 大约耗时(RTT=50ms) |
|---|---|---|
| TCP三次握手 | 1.5 RTT | 75ms |
| TLS 1.3握手 | 1 RTT | 50ms |
| HTTP请求/响应 | 1 RTT | 50ms |
| 总计 | 3.5 RTT | 175ms |
这只是创建一个新连接。如果你的接口要连续请求5个资源,按HTTP/1.1的串行方式,时间就是5倍的连接开销。你算算,光握手就快1秒了。
怎么优化? 我建议:
- 启用Keep-Alive:复用TCP连接。Nginx和大多数Web服务器默认都开,但超时时间别设太短。我一般设75秒。
- 域名收敛:把静态资源和API放在同一个域名下,减少跨域连接数。或者用少数几个域名。HTTP/1.1对同一域名有并发限制(通常是6个),域名太多反而增加连接开销。
- 资源合并:CSS Sprite、JS打包、内联小图片。减少请求数,就是减少连接数。
核心观点
连接数每减少一个,就省掉至少 1.5 个 RTT 的时间。对于移动端、弱网环境,这节省的是实实在在的秒级体验。
3. 使用HTTP/2:多路复用解决队头阻塞
HTTP/1.1有个老大难问题:队头阻塞。什么意思?就是一个连接上只能同时处理一个请求。前一个请求没响应,后面的就得排队等着。哪怕服务器已经准备好了,也得等前面的车开走。
HTTP/2的核心改进就是多路复用。一个连接上可以同时跑多个请求和响应,互相不干扰。你发你的,我收我的,数据流交织在一起传输。
我记得有一次优化一个图片列表接口,用HTTP/1.1时,10张图片要开6个连接,但还是因为队头阻塞,总耗时2.8秒。换成HTTP/2后,全用1个连接,多路复用,总耗时一下子降到0.9秒。效果就是这么明显。
| 特性 | HTTP/1.1 | HTTP/2 |
|---|---|---|
| 多路复用 | 不支持 | 支持,一一连接并发 |
| 队头阻塞 | 存在 | 基本解决 |
| 头部压缩 | 明文,无压缩 | HPACK压缩 |
| 服务器推送 | 不支持 | 支持 |
| 连接数 | 通常6+个 | 1个足够 |
实践要点
升级到HTTP/2很简单——你的Web服务器(Nginx、Apache、Caddy)都支持,配置一下证书(HTTPS)和协议启用就行。连代码都不需要改。
但要注意:HTTP/2需要HTTPS。另外,如果你还在用域名分片(把资源分散到不同域名)来提升HTTP/1.1并发,现在可以改回来了。HTTP/2不需要这个,反而会增加连接数。
# Nginx 启用 HTTP/2
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://backend;
}
}
4. CDN加速:把内容搬到离用户最近的地方
网络延迟的根本原因,就是光速有限。数据在光纤里跑,从北京到上海大约20ms,到纽约大约150ms。物理距离决定了延迟的下限。
CDN怎么解决的?在全球部署边缘节点。你的静态资源(JS、CSS、图片、甚至API响应)被缓存到离用户最近的节点上。用户请求直接命中边缘节点,不再需要绕回源站。
我个人建议,只要你的用户分布在多个地区,CDN就是必备品。它不只能缓存静态资源,现在很多CDN还支持动态加速:通过智能路由、TCP优化、私有协议,让动态接口的延迟也降低30%-50%。
CDN优化要点:
- 缓存策略:设置合理的缓存过期时间(Cache-Control、Expires)。对于不常变动的资源,缓存时间可以设长一点(比如30天)。版本号管理更新。
- 预热:大版本上线前,主动把资源推送到CDN节点。避免大量用户首次访问时回源,造成源站压力骤增。
- 动态加速:对于API接口,开启CDN的动态加速功能。它通过优化的路由和连接管理,减少网络抖动和丢包。
- 边缘计算:部分CDN支持在边缘节点运行轻量代码。你可以把简单的API聚合、格式转换、鉴权放到边缘做,进一步减少回源。
关键指标
CDN的命中率是核心监控指标。一般静态资源命中率应达到 95% 以上。低于90%说明缓存策略不完善,需要检查缓存键、过期时间、或者有没有意外绕过了缓存。
一口吃不成胖子,网络优化也是。我个人习惯是:先上CDN和HTTP/2,这俩改动最小、收益最大。如果还有问题,再回来优化DNS和连接数。一步一步来,效果看得见。