4.1 域名接入 CDN:从解析到首次加速

图片社区上线两个月时,我收到第一封真正意义上的用户投诉:一个成都用户说首页图片要刷七八秒才出来,晚上高峰期“半屏都是裂图”。我起初不以为然——服务器在上海,我自己打开首页只要不到 1 秒。直到我借了三个不同地域的测试机各跑了一遍,才真正理解那句话:你觉得快,是因为你就住在机房旁边。

没接 CDN 之前:一份扎眼的延迟对照表

当时的架构很简单:一台上海地域的 CVM 跑后端,图片虽然存在 COS 里,但所有图片请求都通过自定义域名回源到 CVM 上的 Nginx 反代。也就是说,全国用户看图,字节都得绕回上海这一台机器。高峰期 5Mbps 带宽跑满,离上海越远越惨。

下面是我用多地拨测实测的数据(同一张 1.2MB 的详情页大图,晚高峰各测 5 次取中位数):

访问地域 运营商 首屏耗时(无 CDN) 图片完整加载
上海 电信 0.8s 1.9s
广州 电信 1.6s 4.8s
成都 移动 2.4s 7.6s
北京 联通 2.1s 6.9s
西安 电信 2.8s 8.4s

注意:这张表只是我这个规模的样本,不同业务、不同时段差异很大,重点看趋势而不是绝对数字。

西安和成都的首屏直奔 3 秒,完整加载超过 7 秒。做图片站的人都清楚,首屏过 3 秒,跳出率会肉眼可见地往上走。我也想过升级带宽、加机器,但问题的本质是物理距离——上海到西安的光纤再快,也快不过把副本放到西安本地。CDN 恰好就是干这个的:把图片缓存到全国各节点,用户访问时就近返回。图片社区读多写少、内容生成后基本不变,简直是给 CDN 准备的场景。

还有一个判断依据:我的访问日志里,图片类请求占总请求量的八成以上,高峰期 QPS 不高但流量特别大——典型的“重内容、轻计算”负载。这种负载最不需要源站的 CPU,最需要的是把字节搬到离用户近的地方。

加速线路和节点选址有不少讲究,如果想从 DNS、地理位置的角度系统了解站点优化,可以看我另一本站点地理优化实战,那本讲得更细。

接入前的准备:三件小事别落下

真正动手接入前,有三件小事值得先确认,能省掉后面大量返工。

一是域名备案。国内加速要求域名已完成备案,这个前提没什么好商量的。我的图片子域名挂在主站备案下,如果你是完全新的域名,备案周期按天计,别等到上线前一天再做。

二是子域名拆分。我把图片请求统一归到 img.example.com,主站接口和页面留在主域名。这样做有三个好处:缓存规则可以只针对图片做激进配置,证书和防盗链互不干扰,出问题时能单独对图片线路排查,不影响主站。

三是源站准备。源站要保证自身能稳定响应——如果是 CVM 自有源,检查 Nginx 的并发连接数配置和带宽上限;如果是 COS 源,确认存储桶是公有读私有写且访问域名正确。我当时的懒人做法是第一版先用自有源跑通流程,熟悉之后再切 COS 源。

接入三步:添加域名、配置源站、修改解析

CDN 接入流程比预想的短,官方文档入口见内容分发网络 CDN 文档。下面是我实际走过的三步,每一步都有可以提前避坑的地方。

第一步,添加加速域名。填你要加速的域名,我专门划了图片子域名 img.example.com。强烈建议子域名独立,不要把主站和图片混在一个域名下——缓存规则、HTTPS 证书、防盗链都要按业务分别配,混在一起后期全是债。加速业务类型按实际选,网页图片类选对应的图片加速即可;没有大文件下载或视频点播的话,默认配置就够用。

第二步,配置源站。源站类型我对比过两种主流选法:

源站类型 填什么内容 适用场景 我的取舍
自有源站 CVM 公网 IP 或源站域名 动态接口、需要反代 第一版用的它
COS 源 存储桶访问域名 纯静态图片 后来切成它
第三方源站 外部 S3 兼容地址 已有其他存储 本书不涉及

我第一版用自有源站:CDN 回源到 CVM 上的 Nginx。能跑,但图片搬进 COS 之后就切成了 COS 源——回源链路更短,CVM 也不用再扛图片带宽。这里还有个容易忽略的配置叫回源 HOST:CDN 节点回源时带的 Host 头要和源站上配置的站点一致,否则 Nginx 会返回默认站点甚至 404。我第一次配的时候没改回源 HOST,图片接口一直返回主站首页 HTML,排查了半小时才发现是 Host 头对不上。

另外如果你的静态资源还和动态接口混在同一台机器上,Nginx 反代怎么拆,可以参考1Panel 常见问题里的排查思路。

第三步,也是最容易被卡住的一步:修改 DNS 解析。接入完成后控制台会给一个 CNAME 地址,形如 img.example.com.cdn.dnsv1.com,需要到域名解析处把原来的 A 记录改成 CNAME 指向它。

CNAME 不生效:我踩过最多次的坑

配完解析我立刻刷新页面,结果图片全裂——因为 DNS 有缓存,CNAME 根本还没生效。这是接入 CDN 后最高频的故障,没有之一。判断方法很简单,用 dig 或 nslookup 看一眼:

dig img.example.com

如果返回的还是 A 记录里的源站 IP,说明本地 DNS 缓存还没刷新,等 TTL 过期就好;如果应答里出现 cdn.dnsv1.com 字样的 CNAME 跳转,就说明已经切到 CDN 了。我第一次把 TTL 从 600 秒改成 3600 秒,结果多等了半个多小时;第二次学乖了,改解析前先把 TTL 调到最小,切换当天再调回去。

另一个坑是域名未备案。国内 CDN 要求接入的域名已完成备案,没备案的话控制台会直接拒绝,没有任何绕过的办法,老老实实先走备案流程。如果你是从零开始搭一个新项目,想快速搞定的可以看AI 建站指南,里面讲了从域名到上线的完整路径。

再补一个验证 CNAME 生效与否的可靠办法:除了 dig,还可以用 nslookup 直接查指定 DNS 服务器,或者直接用站长工具类的多地 DNS 查询服务。当你自己的本机生效而外地朋友没生效时,是正常的中间递归服务器缓存问题,通常等一个 TTL 周期就好,不需要任何操作。

提示:解析生效后别急着宣布成功,先清一下本地 DNS 缓存再测,Windows 下是 ipconfig /flushdns,否则你看到的可能还是旧结果。

验证加速效果:别只看自己

切换完成后第二天同一时段,我把那张延迟表重跑了一遍:成都首屏从 2.4 秒降到 0.6 秒,西安从 2.8 秒降到 0.7 秒,上海反而略慢了一丢丢——多了一层节点,对源站附近的用户几乎无感。回源带宽从 5Mbps 降到不足 1Mbps,CVM 终于不再当图片搬运工。

验证时有两个小技巧:一是用 curl -I 看响应头里的 X-Cache-Lookup 字段,命中节点缓存和回源返回的内容不一样,能确认请求确实走了 CDN;二是从不同地域拨测,别只盯着一台机器,自己快不算快。

补充一点关于状态码:接入后 CDN 会接管缓存层,但源站的错误(比如 404、500)也会被缓存一小段时间。如果发现某个已修复的页面还持续报错,先想想是不是错误页被节点缓存了,手动刷一下就好,别去重启服务器。

还有一点值得养成习惯:接入后把 CDN 控制台的监控大盘看熟。命中率、回源带宽、状态码分布这几个曲线是以后所有故障的第一现场,平时知道正常时长什么样,出事才能一眼看出不对劲。云监控那篇会细讲告警配置,这里先混个脸熟。

接入成本方面,CDN 按流量计费,我这种量级一个月二三十块搞定,比升带宽便宜得多。顺手分享一下我下单的地方:云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中,新用户首单比列表价低不少,我第一年就是从这里下的手。

延伸阅读