为什么用了CDN,源站请求还是慢?
配置前的检查
折腾CDN keepalive时,我发现最麻烦的往往不是安装,而是配置。你给网站套上了CDN,以为所有流量都由边缘节点扛住,源站可以高枕无忧。但实际表现却不尽如人意:图片加载忽快忽慢,接口响应时而有延迟。排查后你会发现,真正拖后腿的不是边缘节点到用户的最后一公里,而是边缘节点到你的源站服务器之间的回源连接。
CDN节点缓存了大部分静态资源,但动态内容、首次访问的静态文件、缓存过期后的资源,都需要从源站拉取。每次回源都相当于做一次完整的HTTP请求。如果这个过程中每个请求都新建一个TCP连接,反复三次握手、慢启动,那延迟就会成倍增加。解决这个问题的两个核心手段就是Keepalive(TCP长连接)和HTTP/2多路复用(Multiplexing)。本文面向新手,不堆砌术语,带你用最直观的方式理解它们。
进阶阅读:此处可内链到“CDN keepalive性能优化”指南。
首先,回源连接到底长什么样?
实际操作要点
想象一个场景:你(用户)向CDN节点要一个网页,节点发现本地没有缓存,就去你的源站服务器拿数据。这个“去源站拿”的动作,就是一次回源。回源的本质是CDN节点扮演一个普通HTTP客户端,向你的源站发起请求。如果CDN同时有100个用户请求同一个页面,但页面里的10个资源都未命中缓存,那么节点可能会向源站发起10个甚至100个连接(取决于并发策略)。
在HTTP/1.1时代,每个连接同一时刻只能处理一个请求。如果节点需要从源站获取A、B、C三个资源,最简单的做法是建三个连接,或者在一个连接上串行请求——先要A,等A返回了再要B,再要C。串行会导致后面请求等待前面完成,浪费带宽和等待时间。而建多个连接虽然可以并行,但每个连接都要经历TCP三次握手(1.5个RTT)和慢启动,源站还要维持大量连接,消耗资源。
于是,我们需要两种优化:减少连接建立次数和提升单连接的并发能力。
Keepalive:不挂电话,省去重复打招呼
容易忽略的细节
Keepalive的中文常被翻译为“长连接”或“连接保活”。它的核心思想很简单:一个TCP连接处理完一个请求后不立即关闭,而是让它保持开放一段时间,供后续请求复用。
对比两种模式:
- 短连接(HTTP/1.0默认):每次请求都新建TCP连接,请求结束立即关闭。好比每次打电话都要拨号、接通、通话、挂断,下一次再重新拨号。
- 长连接(HTTP/1.1默认支持):第一个请求结束后,连接保持开放,后续请求直接复用这个连接,省去了三次握手和慢启动的时间。好比一次拨号后一直不挂电话,后续有事直接说。
在CDN回源场景下,Keepalive带来的收益很直接:源站和CDN节点之间频繁有多个请求需要交互,如果每个请求都重建连接,网络延迟和服务器CPU开销都会增加。启用Keepalive后,一个TCP连接可以处理成百上千个请求,源站的压力也明显下降。
但Keepalive不是无限期保持连接,需要设置一个超时时间(例如60秒)。超时时间内没有请求,连接会被关闭释放资源。超时时间设得太短,连接频繁重建;设得太长,空闲连接占用资源。通常CDN服务商会在节点侧设置合理的keepalive超时,但作为源站管理员,你也需要确保源站服务器支持并正确配置keepalive参数。
延伸阅读:此处可内链到“CDN keepalive配置案例”相关文章。
HTTP/2多路复用:一条路上跑多辆车——CDN keepalive
容易忽略的细节
Keepalive解决了连接复用的问题,但在同一个连接上,HTTP/1.1仍然只能串行处理请求——一个请求没响应完,下一个请求只能排队等待。这被称为“队头阻塞”(Head-of-Line Blocking)。即便使用多个连接可以并行,但每个连接独立,不能共享拥塞控制和头部压缩,效率仍然受限。
HTTP/2(基于Google的SPDY协议演化而来)引入了一个革命性的特性:多路复用(Multiplexing)。它允许在一个TCP连接上同时发送多个请求和响应,且这些请求互不干扰。原理是HTTP/2将消息拆分为更小的帧(Frame),每个帧打上所属流的ID,不同流的帧可以交错发送。接收端根据帧头部的流ID将帧重新组装成完整的请求或响应。
用一个简单的比喻:HTTP/1.1就像一个单向单车道,一次只能有一辆车(请求)通过,后面的车必须等前面的车到达目的地才能出发。而HTTP/2则是一条多车道高速公路,每辆车有自己的车道标识,可以同时行驶并独立到达目的地。
在CDN回源场景下,多路复用的意义尤为突出。CDN节点通常需要同时从源站获取多个资源(比如一个页面中的JS、CSS、图片等)。使用HTTP/2回源,节点可以在一个Keepalive连接上同时发起多个请求,所有请求并行传输,无需任何等待。尤其当源站服务器支持HTTP/2时,CDN节点会自动尝试使用HTTP/2与之通信(通过ALPN协商)。
想继续深入:此处可内链到“CDN keepalive优化清单”文章。
Keepalive + HTTP/2 Multiplexing:黄金搭档
理解了两者的关系:Keepalive提供了持久的“管道”,而HTTP/2多路复用则让这个管道里可以同时流过多个并行的数据流。没有Keepalive,多路复用的连接会频繁重建,浪费握手时间;没有多路复用,Keepalive连接上只能串行处理,效率大打折扣。两者结合,才能最大化回源效率。
以Nginx作为源站服务器为例,你可以通过以下配置启用Keepalive和HTTP/2:
http {
# 启用HTTP/2支持,并开启keepalive
server {
listen 443 ssl http2;
ssl_certificate /path/to/cert;
ssl_certificate_key /path/to/key;
keepalive_timeout 65;
keepalive_requests 1000;
...
}
}
- keepalive_timeout:设置长连接超时时间(秒),超过这个时间没有请求,连接被关闭。
- keepalive_requests:设置一个长连接最多可以处理多少个请求,防止某个连接被长期滥用。
对于CDN回源,典型建议是 keepalive_timeout 60~120秒,keepalive_requests 1000以上。注意:如果源站使用HTTP/1.1回源且启用keepalive,也可以获得一定收益,但无法并行传输;强烈建议同时开启HTTP/2。
验证配置是否生效
你可以用以下方法验证Keepalive和HTTP/2是否正常工作:
- 抓包分析:使用Wireshark或tcpdump在源站侧抓包,观察多个请求是否共享同一个TCP连接(相同源IP、源端口、目的IP、目的端口)。如果连接一直保持,说明keepalive生效。同时检查HTTP/2的帧类型(如SETTINGS、HEADERS、DATA帧),确认是HTTP/2协议。
- 检查CDN节点回源日志:很多CDN服务商(如Cloudflare、Akamai)的回源日志会标明使用的协议版本(HTTP/1.1或HTTP/2)。如果看到大量HTTP/2记录,说明多路复用正在工作。
- 测试性能:使用压测工具(如wrk、ab)模拟回源请求,对比开启和不开启keepalive+HTTP/2的QPS和延迟。通常开启后QPS可提升数倍,平均延迟降低30%~50%。
注意事项与风险提示
故障定位思路
虽然Keepalive和HTTP/2带来的收益非常诱人,但盲目开启可能引发一些问题:
- 源站资源消耗:长连接会占用服务器文件描述符和内存。如果源站并发连接数很高(比如CDN节点大量回源),需要合理调整内核参数(如net.core.somaxconn、net.ipv4.tcp_max_tw_buckets)以及Nginx的worker_connections。
- HTTP/2后端支持:并非所有CDN节点都支持HTTP/2回源,部分老旧的CDN仍使用HTTP/1.1。你需要确认CDN服务商是否提供回源协议协商选项。主流CDN(如阿里云CDN、腾讯云CDN、Cloudflare)均支持,但可能需要手动开启。
- 超时配置匹配:CDN节点侧也有自己的keepalive超时设置。如果节点超时比源站短,连接可能被源站提前关闭导致错误;反之则浪费资源。建议保持两者接近或让节点略长于源站。
- 回滚方案:如果配置后发现源站负载异常升高或出现大量502/504错误,可以临时关闭keepalive和HTTP/2:在Nginx中注释掉keepalive_timeout和http2参数,重新加载配置。更稳妥的做法是先在一台测试服务器上验证,再推广到生产环境。
相关阅读:此处可内链到“CDN keepalive常见问题”专题。
总结:优化回源连接,让CDN真正快起来与CDN keepalive
我的处理经验
CDN加速不只是“缓存+就近分发”,边缘节点到源站的连接质量直接影响动态内容和首次访问的体验。Keepalive通过复用TCP连接避免了握手开销,HTTP/2多路复用则打破了串行瓶颈,两者叠加让回源性能发生质变。对于新手来说,理解这些概念后,你就能在配置源站时做出更明智的选择,也能看懂CDN服务商给出的优化建议。下一步,你可以动手检查自己的源站是否开启了HTTP/2和长连接,尝试调整参数并观察效果——优化回源连接,往往是最简单但最有效的CDN加速手段之一。真正做好CDN keepalive,靠的不是参数堆砌,而是持续验证。
延伸阅读
