给图床部署cdn腾讯云的edgeone并排查Cache-Control max-age 3600的问题
正篇
最近发布了徒步反穿武功山,以及自驾皖浙赣的游记文章,点我直达 ,我分享到了 v2ex 以及 linux.do ,各路网友都说图床太慢了。由于原文图片数量的确较多,我的图床部署在家里,然后只有 VPS 的6Mbps小水管,在并发不大的时候阅读文章还行(图片加载的速度还OK,并且有配置懒加载,所以体验还行),但是昨天发了帖子之后有几波流量激增。于是我寻找办法:
- 准备使用活菩萨 cloudflare,但是要整体迁移域名解析到 cf,因为我这个域名有经过备案,并且数量众多,而且还要兼顾国内访问速率,我就放弃了 cloudflare 方案
- 准备在源图床那边创建新的存储策略,当前是存储在本地磁盘的,然后想想又要买对象存储,又放弃
- 最后发现了腾讯云的 edgeone,开通试试一个月只要4.8元,实付款4.7,最近微信支付很多借记卡、信用卡减免活动
最终我买了一个月的 edgeone,只花费4.7元~
现在部署好了 cdn,访问速度大大增加。当前时间点 2025-08-19 10:30:42 edgeone 流量情况
我这篇文章不算是教程吧,只能是个人的心路历程,我也不想写保姆级教程,太费事了。在此就简单讲讲过程和原理。
- 首先购买了一个月的 edgeone 产品,需要绑定站点,首先绑定根域名,也就是
940304.xyz
然后经过认证 - 域名认证方式是:添加 TXT 类型记录,主机记录和对应的值都是 edgeone 给出的,我的域名托管在 dnspod,需要在 dnspod 那边改
- 也可以不认证根域名,每个二级域名都分别认证
- 通过CNAME 方式接入 CDN,需要先停止解析或删除之前的 image 主机名的 A记录(DNS A记录),然后添加 image 主机名的 CNAME 记录(因为同一个主机名A记录和 CNAME记录只能有一个条)
- 创建成功后就等待 edgeone 下发 cdn 配置,等待部署生效即可
我顺利的部署成功,也看到 edgeone 流量页面产生了非常多的数据,当前我博客中的多图文章访问体验肯定就好很多了。
但是后面我发现一个问题,就是图片资源访问后返回头当中的 Cache-Control 始终是 max-age=3600
,这说明 cdn 边缘节点只会缓存这张图片一个小时,如果用户在一个小时之后访问同链接会无法击中缓存,导致cdn节点回源获取原始文件,这势必会增加很多源站的流量,我的公网VPS以及家里服务器的流量都会增大,设置CDN的效果就大为下降了,而且我这就是图床程序,资源是静态的,不需要长时间变动。一般情况下图片资源都会设置30天后过期,也就是 max-age=2592000
(单位s),于是我开启了排查。
在部署 edgeone 之前,我的图床架构是这样的
在部署 edgeone 之后,我的图床架构变成这样
在任意有网络机器执行 curl -I https://image.940304.xyz/i/2025/05/21/682dd7d3137c3.jpg
发现返回 Cache-Control: max-age=3600
,我开启了漫长的排查,总结下来就是
1、在VPS上修改 nginx 配置,显式增加 Cache-Control 的返回头,设置成 public, max-age=2592000
,但是无果
2、在以上基础上,区分单独的匹配图片的 location,因为之前是一个反向代理 location /
就能搞定
配置是这样的
location ~* \.(jpg|jpeg|png|gif|webp|ico|css|js|svg|woff2)$ {
proxy_pass http://127.0.0.1:81;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host;
# 30天缓存(仅对静态资源)
add_header Cache-Control "public, max-age=2592000, s-maxage=2592000";
# 跨域允许设置,允许所有跨域
add_header 'Access-Control-Allow-Origin' *;
# 自定义 Debug 头部(仅用于测试)
add_header HDKRESP "This-request-matched-jpg-location_test"; # 新增
# 跨域允许设置结束
# 防盗链设置,因为上述跨域是允许所有的,这里就要设置防盗链从而进行域名的白名单设置
valid_referers none blocked 940304.xyz *.940304.xyz hellodk.cn *.hellodk.cn hellodk.com *.hellodk.com 10.10.10.5;
#nginx不允许嵌套if语句,这个很关键,否则nginx -t 会测试失败,无法reload或者start nginx服务
set $block_access 0;
# 如果 referer 无效
if ($invalid_referer) {
set $block_access 1;
}
# 根据之前的判断结果决定是否拦截
if ($block_access) {
rewrite ^/ https://i.imgur.com/CB4Fseq.jpeg;
}
}
这样的确能增加Cache-Control 的返回头,但是edgeone 那边始终没有生效。我还去lsky pro 图床程序的源 apache2 服务端添加了 Cache-Control 头,因为根据 edgeone 的规则,会先读源站的缓存相关的返回头(Cache-Control:s-maxage, Cache-Control:max-age, Expires),如果有会优先遵循源站的配置
edgeone 的文档:https://cloud.tencent.com/document/product/1552/87651
edgeone默认缓存规则
默认缓存规则文字说明
3、发现修改vps nginx配置无果,我进入了 lsky pro 容器,做了以下操作
# Apache 需要启用 mod_headers 才能使用 Header set 指令,启用这个模块
a2enmod headers
# 修改生效配置文件 `/etc/apache2/sites-enabled/000-default.conf` 可以通过命令 `apache2ctl -S` 寻找生效的虚拟主机所在文件
# 并增加如下配置
<LocationMatch "^/i/.*\.(jpg|jpeg|png|gif|webp|ico|bmp)$">
Header set Cache-Control "public, max-age=2592000"
</LocationMatch>
# 重启apache2服务
service apache2 restart
现在图床源站点会给静态图片资源返回 Cache-Control 了,在图床容器中执行 curl -I http://localhost/i/2025/05/21/682dd7d3137c3.jpg
有如下返回
HTTP/1.1 200 OK
Date: Tue, 19 Aug 2025 03:11:18 GMT
Server: Apache/2.4.53 (Debian)
Last-Modified: Wed, 21 May 2025 13:40:35 GMT
ETag: "ef67-635a58279843c"
Accept-Ranges: bytes
Content-Length: 61287
Cache-Control: public, max-age=2592000
Content-Type: image/jpeg
在 edgeone 管理页面清除了这个URL https://image.940304.xyz/i/2025/05/21/682dd7d3137c3.jpg
的缓存,从 EO-Cache-Status
MISS 到 HIT(也就是第一次请求未击中缓存cdn节点回源了,到第二次击中了缓存),返回的 max-age 仍然是 3600
4、开始排查 edgeone 这边,终于找到了原因所在!
需要在这里点击站点加速,我以为默认的全局配置就是对的,因为设置的是遵循源站的 Cache-Control,所以一直没细看
这里全局配置是正确的,没毛病,但是右侧还有一个规则引擎默认是打开的(但是默认没有任何配置,尼玛坑死我),并且优先级更高。
规则引擎默认打开并且默认无配置坑我导致max-age一直是3600!!!(欲哭无泪
最后我因为不需要个性的规则引擎配置,我就将这边关掉了,直接使用全局配置,遵循源站的 Cache-Control 即可。
最终执行 curl -I https://image.940304.xyz/i/2025/05/21/682dd7d3137c3.jpg
返回了 Cache-Control: public, max-age=2592000
最终解决,这样可以减少 cdn 回源的频率,需求满足!
ok,如果你有任何疑问,欢迎留言与我讨论。
番外篇
edgeone国际版测速分享到X或者Facebook得FreePlan,网站 https://edgeone.ai 甚至分享到X+分享到Facebook可得两份FreePlan
我等当前买的国内版失效之前的几天就切换到国际版。但是需要注意的是,腾讯云的一份身份认证只能实名制一个腾讯云账号,edgeone国际版要想使用中国大陆节点需要实名认证的账号才行。我的身份已经实名了国内版的了,后面大概就选择国际节点
国内版edgeone产品,4.7元买的一个月
