博客图片 CDN 配置指南(腾讯云)

博客图片 CDN 配置指南(腾讯云)
上线日期:2026-09-30 | 服务商:腾讯云 CDN | 面向对象:站长本人(复习用) 本文已脱敏:源站 IP 一律写
<源站IP>,配置时自行代入。
一、为什么要配 CDN?目的是什么
配 CDN 之前,图片是怎么走的:
读者浏览器(全国各地)
└─ 全部请求涌向源站服务器(单台轻量服务器)
└─ nginx → blog-api 读出图片 → 返回
这条链路有三个问题:
-
慢:服务器只有一台、在单个机房。北京读者和广州读者访问速度完全取决于离机房远近,跨省延迟高,图片首屏加载慢。
-
扛不住:每张图都要源站 CPU + 带宽亲自出力。文章被分享到外站带来一波流量、或者遇到爬虫/恶意刷量,源站带宽被打满,连网页本身都会跟着卡死——图片把主站拖垮。
-
重复劳动:同一张图被 1000 个人看 1000 次,源站就傻傻地读 1000 次。明明内容一秒都没变过。
配 CDN 之后:
读者浏览器
└─ 腾讯 CDN 边缘节点(全国分散部署,离读者最近的一个)
├─ 节点已有这张图 → 直接返回(速度极快,源站毫不知情)★90% 的情况
└─ 节点没有 → 回源站取一次,存在节点上,下次就近服务
收益一句话总结:图片加载更快(就近取)、源站更安全(带宽被 CDN 挡住)、源站更省(绝大部分请求不再到达源站)。
为什么不缓存网页、只缓存图片:网页(文章列表/内容)是动态生成、随时可能改,缓存了会出现"发文章半天看不到"的问题;而图片一旦上传内容永远不变(文件名含日期/时间戳),是完美的缓存对象——这也是为什么单独拿一个 cdn. 子域名来托管图片。
二、原理:一个 CNAME 背后的调度
CDN 加速的本质是改 DNS 指向 + 换个更近的服务器替你回答请求:
-
你在腾讯云添加加速域名(如
cdn.mashangan.com),腾讯给你一个"CNAME 目标地址"(形如xxxx.cdn.dnsv1.com)。 -
你在 DNSPod 把
cdn.mashangan.com的解析从 A 记录(直接指向源站 IP)改成 CNAME 记录(指向腾讯的调度地址)。 -
之后读者解析
cdn.mashangan.com时,腾讯的调度系统会根据读者的地理位置/运营商,返回离他最近的边缘节点 IP。 -
读者请求图片 → 边缘节点接住 → 有缓存直接返回,没缓存回源站取一次并缓存(默认 1 小时,由源站响应头
Cache-Control: max-age=3600决定)。
如何确认请求真的到了腾讯边缘(复习用):浏览器 F12 → Network → 点开一张图片 → Response Headers 里找:
响应头
含义
X-Cache-Lookup: Cache Hit
命中边缘缓存(最理想)
Age: 17
这张图已在节点上放了 17 秒
X-NWS-LOG-UUID
腾讯云边缘节点才有的日志 ID(出现即说明到了腾讯)
Server: nginx/1.27.5
源站 nginx 透传过来的(说明是回源取的)
三、配置全流程(控制台逐步导航)
核心难点回顾:腾讯云产品众多,CDN 的配置入口藏得深。以下每一步都给出控制台页面路径。 控制台总入口:https://console.cloud.tencent.com/cdn (或在腾讯云控制台顶部搜索框输入"内容分发网络"/"CDN")
第 1 步:添加加速域名
-
路径:CDN 控制台 → 左侧菜单「域名管理」→ 点「添加域名」
-
表单怎么填:
-
加速域名:
cdn.mashangan.com(子域名随便起,用 cdn 便于识别) -
加速区域:中国境内(要求域名已备案;若提示需要验证域名归属权,按提示到 DNSPod 加一条 TXT 记录即可)
-
加速类型/业务类型:选 CDN 的网页小文件(以图片等小型静态资源为主的业务)
-
源站信息:类型选「自有源」→ 填
<源站IP>,回源协议 HTTP- 为什么回源用 HTTP 不用 HTTPS:回源是"腾讯机房 → 你的服务器"的内段链路,走 HTTP 就行;对读者那一跳(读者 → 腾讯边缘)才是 HTTPS,由第 4 步的证书保证。这样源站压力最小。
-
回源 HOST:默认(加速域名)即可——源站 nginx 已按该域名配好 vhost
-
-
提交后回到「域名管理」列表,状态从"部署中"变为"已启动",同时列表里会显示分配给你的 CNAME 值(形如
cdn.mashangan.com.cdn.dnsv1.com),复制它。
第 2 步:改 DNS 解析(DNSPod 控制台)
-
路径:DNSPod/云解析控制台 → 我的域名 → mashangan.com 行点「记录管理」
-
直达链接:https://console.dnspod.cn (或腾讯云控制台搜"DNS 解析 DNSPod")
-
操作:
-
点「添加记录」:主机记录
cdn、类型 CNAME、记录值粘贴第 1 步复制的调度地址、TTL 默认 -
如果
cdn子域之前有过 A 记录(我们曾用"直指源站"应急),把那条 A 记录暂停(点禁用开关)——同一个主机记录 CNAME 和 A 不能同时生效
-
-
验证解析已切换:本机命令行执行
nslookup cdn.mashangan.com,看到返回的地址是腾讯调度域名映射出的 IP 集群、且 alias 里带cdn.dnsv1.com,即成功(刚改完有几分钟 TTL 缓存,急不得)
第 3 步:验证 HTTP 回源链路已通
此时先用 http:// 试访问一张真实图片(路径格式 http://cdn.mashangan.com/upload/年/月/文件名.png,可在文章页 F12 里随便复制一张图的地址把域名换掉):
-
返回 200 且带
X-NWS-LOG-UUID头 → 调度、缓存、回源全通 ✅ -
返回 404 且 Body 是
NWS_SP之类 → 该域名在腾讯侧被停用(见踩坑 #3) -
整个域 NXDOMAIN → DNS 记录没生效/被删(见踩坑 #3)
第 4 步:HTTPS 配置(★本次最大的坑在这里)
-
路径:CDN 控制台 → 域名管理 → 点你的域名进详情页 → 左侧/顶部 Tab「HTTPS 配置」
-
这个页面里有一排开关,逐个说明:
配置项
怎么填
说明
HTTPS 服务总开关
必须打开
带「付费」标签,按 HTTPS 请求次数计费(很便宜)。不开的话所有 HTTPS 请求一律返回 514 错误页——这是本次踩的最大坑,见踩坑 #1
证书配置
「配置证书」→ 选自有证书 → 把服务器上的证书 pem + key 两个文件内容粘贴/上传
服务器证书位置:源站 nginx 证书目录下的 cdn.mashangan.com.pem/.key(Let's Encrypt 签发,SFTP 下载即可)。也可用腾讯云免费证书(SSL 控制台申请后一键部署)
HTTP 2.0
开启
浏览器多路复用,图片并发加载更快
强制跳转
开启(HTTP → HTTPS)
有人用 http:// 访问时自动 302 到 https://
TLS 版本
1.2 / 1.3 开,1.0 / 1.1 关
老协议有安全漏洞
HSTS
暂不开(要开也从 1 天 max-age 起步)
单向门:浏览器记住后 max-age 内强制走 HTTPS 且无法回退。等 CDN 稳定运行一段时间再开,避免出问题时无法降级
OCSP 装订
可不开
证书状态查询优化,收益极小
第 5 步:HTTPS 全链路验证
-
浏览器直接打开
https://cdn.mashangan.com/upload/...某张图 → 200 即通 -
F12 看 Response Headers:
X-Cache-Lookup/Age/X-NWS-LOG-UUID齐全 ✅ -
http:// 访问同一地址 → 应 302 跳到 https(这是第 4 步"强制跳转"的预期表现,不是故障)
-
项目内验证脚本(本地跑):
python _md2html\_verify_prod_cdn.py(全站页面图片引用普查)、_probe_cdn_headers.py(边缘响应头)
第 6 步(强烈建议当天就做):防刷保险丝
都在域名详情页内:
配置
Tab 位置
填什么
为什么
用量封顶
「高级配置」Tab → 用量封顶
按天设流量阈值(如 10GB),超了自动停止服务并告警
防被盗刷出天价账单,个人博客必开
Referer 防盗链
「访问控制」Tab → Referer 防盗链
白名单 *.mashangan.com,必须同时勾选「允许空 Referer」
防其他网站直接嵌你的图。⚠️ 空 Referer 不勾会全站裂图:本站前端带 no-referrer 策略,图片请求不带 Referer,见踩坑 #5
节点缓存过期
「缓存配置」Tab
保持跟随源站(max-age=3600)即可
图片内容不变,理论上可以设更长,保守从 1 小时起
四、让站内图片真的走 CDN(应用侧切换)
CDN 域名通了只是"路修好了",站内 HTML 里的图片地址还指向源站,需要把引用切过去。本站的做法(2026-09-30 已落地,commit 38c5a89):
-
新增
blog-web/utils/cdnize.ts改写器,在三个数据出口统一把https://cdn.mashangan.com/upload/相对路径(及历史遗留的旧绝对地址)改写为https://cdn.mashangan.com/upload/...:-
useHaloApi.apiFetch—— 覆盖 SSR 首屏 + 客户端 SPA 导航两条取数路径 -
server/api/site-config.get.ts—— 站点 logo -
server/routes/rss.xml.ts—— RSS 摘要
-
-
不改数据库:改写发生在渲染之前,库里存的仍是相对路径;哪天想换 CDN 域名,改一处 env 即可
-
开关:服务器上 halo-web 容器的环境变量
IMG_CDN_BASE: "https://cdn.mashangan.com"(compose 里是映射格式KEY: value,注意缩进对齐,见踩坑 #6) -
回退:删掉该环境变量 →
docker compose up -d --force-recreate --no-deps halo-web→ 图片立即回到相对路径直连源站,1 分钟生效 -
验证:
python _md2html\_verify_prod_cdn.py,预期全站页面 CDN 引用数 > 0、裸https://cdn.mashangan.com/upload/引用数为 0
五、踩坑实录(复习重点)
坑 #1:HTTPS 全部 514(Frequency Capped)——本次耗时最长的坑
-
现象:CDN 域名 DNS 已切、HTTP 访问图片正常 200,但所有 https:// 请求(无论什么路径)一律返回 514 错误页。
-
走了的弯路:先怀疑 DNS 缓存没生效(等 3 分钟,没用)→ 再怀疑证书部署延迟(等 5 分钟,没用)→ 最后是控制台截图对照官方文档才定位。
-
根因:域名详情页「HTTPS 配置」里的 HTTPS 服务总开关没打开。官方说明原文就写着:"HTTPS 服务关闭时,HTTPS 请求将被拒绝访问,响应 514 状态码"。这个开关是付费增值项,默认关闭。
-
教训:CDN 排障先看"总开关类"配置,别先怀疑玄学缓存。514 不是限流(名字里的 Frequency Capped 有误导性),就是 HTTPS 服务没开。
-
知识点:HTTP 能通 + HTTPS 全 514 = 100% 是 HTTPS 开关/证书问题。
坑 #2:http:// 请求返回 302 不是故障
开了「强制跳转」后,HTTP 请求 302 → HTTPS 是预期行为。验证时别把 302 当异常;想测纯 HTTP 链路,去关强制跳转或直接看跳转后的最终响应。
坑 #3:CDN 域名"离奇失效"两种表现(上线前发生过)
-
表现 A:NXDOMAIN——
cdn子域名解析彻底消失。原因:此前的 DNS CNAME 记录不知何时被删(半成品配置)。应急:DNSPod 加一条 A 记录直指源站 IP(源站 nginx 本就配好了该域名的证书和反代,可以独立服务),先恢复访问再慢慢查。 -
表现 B:边缘返回 404 且 Body 带 NWS_SP——解析正常、能到腾讯节点,但腾讯说没这个域名的加速配置。疑似该加速域名在腾讯侧被停用/未生效。同样用 A 记录应急。
-
教训:源站 nginx 一直留着
cdn域名的 vhost + 证书,就是给应急用的;DNSPod 里那条禁用状态的应急 A 记录保留勿删,回退时启用它、暂停 CNAME 即可。
坑 #4:CDN 侧证书不会自动续期
-
服务器上的 Let's Encrypt 证书由 acme.sh 自动续期,但上传到腾讯 CDN 的那份是静态拷贝,acme.sh 管不到。
-
到期日 2026-12-28。到期前(建议 12-14 设日历提醒):确认服务器证书已续签 → SFTP 下载新 pem/key → CDN 控制台 → 域名详情 → HTTPS 配置 → 证书配置 → 更换证书。
-
过期症状:浏览器访问图片报证书过期警告、证书告警邮件。别慌,换证书即恢复,不影响其他域名。
坑 #5:开防盗链必须放行"空 Referer"
本站前端 HTML 带 <meta name="referrer" content="no-referrer">(历史原因,防旧图床防盗链),图片请求一律不带 Referer。若开启 Referer 白名单却拒绝空 Referer,所有站内图片请求都会被 CDN 拒绝 → 全站裂图。白名单 + 允许空 Referer 两者缺一不可。
坑 #6:compose 插环境变量的格式
服务器 docker-compose.yml 的 environment: 是映射格式(KEY: "value",没有 - 前缀)。插入新变量必须用同样格式、缩进对齐;写成列表格式(- KEY=value)会导致 YAML 解析失败,compose 所有操作全挂。改完先 docker compose config 校验再 up(部署脚本 _deploy_haloweb_cdn.py 里已内置校验+自动回滚备份)。
坑 #7:验证手段备忘
-
图片到底走没走 CDN:F12 看图片请求的
X-Cache-Lookup/X-NWS-LOG-UUID响应头 -
全站图片引用普查:
python _md2html\_verify_prod_cdn.py -
边缘响应头细看:
python _md2html\_probe_cdn_headers.py -
HTTP→HTTPS 跳转验证:
python _md2html\_probe_http_redirect.py -
DNS 记录状态:
python _md2html\_check_cdn_golive.py -
部署(含 env 插入+校验+回滚):
python _md2html\_deploy_haloweb_cdn.py
六、费用参考
项
计费方式
量级
CDN 流量
按下行流量计费(约 0.2 元/GB 起,购流量包更省)
个人博客图片量很小,每月几元以内
HTTPS 请求数
按 HTTPS 请求次数极低单价计费
可忽略,但必须开(坑 #1)
防意外三件套:用量封顶(第六步)+ 控制台"费用中心"设告警阈值 + 流量包(可选)。
七、应急回退手册
故障场景
回退动作
生效时间
CDN 边缘异常(5xx/4xx 大面积)
DNSPod:启用应急 A 记录(直指源站)、暂停 CNAME
TTL 内,约 10 分钟
只想站内图片不走 CDN
服务器:删 halo-web 的 IMG_CDN_BASE env → docker compose up -d --force-recreate --no-deps halo-web
1 分钟
证书过期(坑 #4)
CDN 控制台换新证书,无需回退
即时
容器重建后图片 404/502
可能是部署窗口,先强刷;再查 docker kill -s HUP halo-nginx 重新解析 upstream
即时
八、参考链接
-
CDN 控制台(域名管理):https://console.cloud.tencent.com/cdn/domains
-
DNSPod 解析控制台:https://console.dnspod.cn
-
腾讯云 CDN 产品文档中心(搜"HTTPS 配置""用量封顶""Referer 防盗链"):https://cloud.tencent.com/document/product/228
-
从零开始配置 CDN(官方快速入门,与本指南第三节步骤一一对应):https://cloud.tencent.com/document/product/228/3149
