网站加载慢是很多站长的心头痛,尤其是服务器只部署在单一机房时,异地用户的访问延迟会明显偏高。CDN(内容分发网络)的核心思路就是把源站的内容缓存到离用户更近的节点上,用户请求先命中就近节点,命中则直接返回,未命中才回源拉取。商业CDN服务虽然省事,但对于流量不大、想省钱或者纯粹想研究技术的个人用户来说,用几台廉价VPS自建一个小型CDN完全是可行的。本文就以Nginx为例,完整讲解从零搭建到日常运营的全过程。

一、搭建前的准备:原理认知与资源规划
动手之前先要搞清楚CDN节点的工作方式。一个最简化的CDN架构由三部分组成:源站(存放真实内容的服务器)、缓存节点(分布在不同地域的Nginx反代服务器)、DNS调度(把用户解析到最近的节点)。当用户请求一张图片时,DNS根据用户来源返回离他最近的节点IP,节点检查本地缓存有没有这份文件,有就直接返回,没有则向源站发起回源请求,拿到内容后缓存一份再返回给用户。
资源规划方面,至少需要两台服务器:一台作为源站,一台或多台作为边缘节点。节点服务器的选择讲究地理分布,比如源站在国内某机房,那么可以在华东、华南、华北各放一个节点,或者如果你的用户遍布全国但预算有限,优先选择BGP多线机房,减少跨网访问的延迟。带宽方面,缓存型CDN的流量主要消耗在节点上,建议选择按流量计费且价格透明的VPS商。
域名规划也不能忽视。推荐准备两个域名:一个作为源站域名(比如 origin.ipipp.com,只允许节点访问),一个作为对外服务域名(比如 www.ipipp.com,解析到各节点)。这样源站可以被完全隐藏起来,避免被恶意直接攻击。
二、动手搭建:用Nginx的proxy_cache构建缓存节点
假设节点服务器已经装好Linux系统,第一步是安装Nginx。建议直接编译安装或使用官方源的稳定版本,确保带有ngx_http_proxy_cache模块,这个模块在默认编译参数中就已包含,一般不需要额外处理。安装完成后就可以开始写配置。
核心配置分为两块:一块定义缓存空间,一块定义反代和缓存规则。先看缓存定义部分:
http {
# 定义缓存路径,levels是目录层级,keys_zone是共享内存名和大小
proxy_cache_path /data/cdn_cache levels=1:2 keys_zone=cdn_cache:100m
max_size=20g inactive=7d use_temp_path=off;
# 只缓存GET和HEAD请求
proxy_cache_methods GET HEAD;
}这里的levels=1:2表示缓存文件按两级目录存放,避免单目录文件过多影响性能;inactive=7d表示文件7天没被访问就清理;max_size=20g限制缓存总大小,超过后Nginx会自动删除最久未访问的内容。接着是server块中的反代配置:
server {
listen 80;
server_name www.ipipp.com;
location / {
proxy_pass http://origin.ipipp.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache cdn_cache;
proxy_cache_valid 200 301 302 12h;
proxy_cache_valid 404 1m;
proxy_cache_key $scheme$host$request_uri;
# 命中时在响应头显示状态,方便调试
add_header X-Cache-Status $upstream_cache_status;
}
}配置完成后用nginx -t检查语法,再nginx -s reload重载。验证缓存是否生效,可以连续请求两次同一个URL,观察X-Cache-Status响应头:第一次显示MISS,第二次显示HIT就说明缓存已经正常工作了。
三、多节点部署与DNS调度
单节点只是反代,谈不上CDN。真正的分发能力来自多个节点加上智能解析。把上面的Nginx配置复制到各地的节点服务器后,需要在DNS层面做调度。最简单的方案是给同一个域名配置多条A记录,DNS服务器会轮询返回不同节点的IP,实现最基础的负载均衡。这种方式的缺点是不感知用户的地理位置,可能把南方用户解析到北方节点。
进阶一点可以用支持分线路解析的DNS服务商,比如设置默认线路指向节点A、联通线路指向节点B、电信线路指向节点C,这样能在一定程度上实现就近接入。如果节点分布在海外,还可以考虑用智能DNS软件自建,根据用户IP的地库判断来源区域再返回对应节点。
另外别忘了健康检查机制。某个节点宕机时,如果DNS还继续返回它的IP,那部分用户就会直接访问失败。商业智能DNS通常自带宕机切换功能,把故障节点的IP自动摘除,解析流量自动切到健康节点,这对个人CDN的稳定性至关重要。
四、常见错误与解决方法
1. 缓存始终不命中(一直是MISS)。最常见的原因是源站响应带了Set-Cookie头或者Cache-Control: no-cache,Nginx默认不会缓存这类响应。解决办法是在节点上加proxy_ignore_headers Set-Cookie Cache-Control;强制忽略这些头,或者从源站入手,对静态资源正确设置缓存策略。
2. HTTPS站点证书报错。节点做HTTPS反代时,需要在每个节点都部署证书。推荐用acme.sh自动申请Let's Encrypt免费证书并配置自动续期,避免证书过期导致全站报错。同时回源如果是HTTPS,确保节点的proxy_ssl_name与源站证书域名匹配。
3. 动态内容被错误缓存。有些接口返回了用户相关数据,如果被缓存,所有用户看到的都是同一份内容,这是严重的事故。务必在配置里对动态路径明确禁用缓存,比如location /api/ { proxy_no_cache 1; proxy_cache off; },只对静态目录和图片、CSS、JS类资源开启缓存。
4. 回源量异常大。如果发现源站流量没有因为上了CDN而下降,大概率是缓存时间设置太短,或者缓存key设计不合理导致命中率低。可以通过$upstream_cache_status做日志统计,算出命中率后再针对性调整proxy_cache_valid的时间。静态化的图片、样式文件可以大胆设置几天的缓存时长。
五、日常运营要点
搭建完成只是开始,长期运营需要关注几件事。首先是监控:给每个节点部署简单的心跳监控,节点离线第一时间收到通知;同时观察缓存命中率的变化,命中率突然下跌往往意味着源站改了响应头或者流量结构变了。其次是缓存清理:源站内容更新后需要刷新节点缓存,可以用Nginx的proxy_cache_purge模块实现按URL清除,也可以写个简单脚本删除对应的缓存文件。
最后是成本控制。个人CDN的优势是便宜可控,但节点流量超额会产生额外费用,建议设置流量告警阈值,并且定期评估各节点的实际负载,长期空闲的节点可以退掉,把钱花在刀刃上。只要把缓存规则、健康检查和监控告警这三件事做好,一套自建CDN的稳定性完全不输入门级的商业服务。