CDN:CDN监控与分析
发布时间:2026-04-21 15:01
CDN监控与分析实战
一、前言
搞过的人都清楚,CDN那玩意儿配完了不等于完了,客户投诉慢你得能说清楚慢在哪。命中率多少、回源多少、各节点带宽啥情况、哪些请求在回源——这些看不懂,你就是瞎运维。这篇说清楚怎么把CDN的监控和分析玩明白。
二、操作步骤
步骤1:搞定CDN日志开关
# 阿里云CDN - 控制台开启日志下载
# 路径:CDN控制台 → 日志管理 → 访问日志 → 开启
# 腾讯云CDN - 日志配置
# 控制台 → 域名管理 → 日志下载 → 开启日志
# AWS CloudFront - 配置日志
aws cloudfront update-distribution
--id EDFDVBD6EXAMPLE
--default-root-object index.html
预期输出:日志开关后,一般15分钟内开始生成gz压缩包,每小时一个文件。
步骤2:SSH登录日志服务器拉取样本
# 假设日志在 /data/cdn-logs/ 目录
ssh -i ~/.ssh/your_key.pem root@日志服务器IP
cd /data/cdn-logs
ls -lh | head -20
# 最近1小时的日志
ls -lth *.gz | head -5
预期输出:
-rw-r----- 1 root root 15M Jan 15 14:00 cdn_access_log_20240115_1400.gz
-rw-r----- 1 root root 14M Jan 15 13:00 cdn_access_log_20240115_1300.gz
-rw-r----- 1 root root 16M Jan 15 12:00 cdn_access_log_20240115_1200.gz
步骤3:解压并分析基础访问量
# 解压日志
gunzip -c cdn_access_log_20240115_1400.gz | head -100 | cat -A
# CentOS/RHEL 安装 awstats(如果需要)
sudo yum install -y awstats
# Ubuntu 安装 awstats
sudo apt-get install -y awstats
预期输出:
101.132.45.67 - - [15/Jan/2024:14:00:15 +0800] "GET /static/css/main.css HTTP/1.1" 200 4523 "https://www.example.com/index.html" "Mozilla/5.0" HIT
106.14.23.89 - - [15/Jan/2024:14:00:18 +0800] "GET /api/user/info HTTP/1.1" 200 1234 "-" "Apache-HttpClient/4.5" MISS
注意最后那列:HIT是命中CDN缓存,MISS是回源请求,HIT越多越好。
步骤4:统计命中率
# 统计HIT/MISS比例
gunzip -c cdn_access_log_20240115_1400.gz | awk '{print $NF}' | sort | uniq -c
# 精确计算命中率百分比
gunzip -c cdn_access_log_20240115_1400.gz | awk '{print $NF}' | sort | uniq -c | awk '
{
total+=$1
if($2=="HIT") hit=$1
}
END {
printf "总请求: %d\nHIT: %d\nMISS: %d\n命中率: %.2f%%\n", total, hit, total-hit, (hit/total)*100
}'
预期输出:
45231 HIT
3210 MISS
总请求: 48441
HIT: 45231
MISS: 3210
命中率: 93.37%
低于80%命中率就得查查原因了,大概率是动态内容或者缓存策略没配好。
步骤5:分析回源请求都是什么
# 找出所有MISS的请求URL
gunzip -c cdn_access_log_20240115_1400.gz | grep "MISS$" | awk -F'"' '{print $2}' | awk '{print $2}' | sort | uniq -c | sort -rn | head -20
# 分析回源请求的响应状态码
gunzip -c cdn_access_log_20240115_1400.gz | grep "MISS$" | awk '{print $9}' | sort | uniq -c | sort -rn
预期输出:
521 /api/v1/product/list
312 /api/v1/user/cart
156 /api/v1/search/suggest
89 /static/images/banner_2024.png
状态码分布:
200: 2102
304: 856
404: 123
502: 129
404和502得重点关注,502说明源站有问题了,别到时候用户投诉你才发现。
步骤6:带宽和流量分析
# 计算总流量(字节)
gunzip -c cdn_access_log_20240115_1400.gz | awk '{sum+=$10} END {print "总流量: " sum/1024/1024 " MB"}'
# 按URL统计流量TOP20
gunzip -c cdn_access_log_20240115_1400.gz | awk -F'"' '{url=$2; size=$10; count[url]++; bytes[url]+=size} END {for(u in count) print count[u], int(bytes[u]/1024/1024) "MB", u}' | sort -rn | head -20
# 统计每个节点的带宽消耗(如果有X-Cache-IP头)
gunzip -c cdn_access_log_20240115_1400.gz | grep -o "X-Cache-IP: [0-9.]*" | awk '{print $2}' | sort | uniq -c | sort -rn
预期输出:
总流量: 1.27 GB
45231 856MB /static/js/vendor.bundle.js
32100 423MB /static/images/logo.png
12340 156MB /static/css/main.min.css
那个vendor.bundle.js占了850MB流量,想想怎么优化——压缩、合并、CDN预热,能省不少带宽钱。
步骤7:慢请求分析
# 找出响应时间超过2秒的请求(假设第12列是响应时间)
gunzip -c cdn_access_log_20240115_1400.gz | awk '$10 > 2000' | head -50
# CentOS/RHEL - 安装 jq 处理JSON格式日志
sudo yum install -y jq
# Ubuntu - 安装 jq
sudo apt-get install -y jq
# 如果是JSON格式日志,解析查看延迟分布
gunzip -c cdn_access_log_20240115_1400.gz | jq '.response_time' | awk 'BEGIN{arr[0]=0;arr[1]=0;arr[2]=0;arr[3]=0;arr[4]=0} {if($1<100) arr[0]++; else if($1<500) arr[1]++; else if($1<1000) arr[2]++; else if($1<2000) arr[3]++; else arr[4]++} END {print "<100ms:",arr[0]; print "100-500ms:",arr[1]; print "500-1000ms:",arr[2]; print "1-2s:",arr[3]; print ">2s:",arr[4]}'
预期输出:
<100ms: 38234
100-500ms: 8567
500-1000ms: 1456
1-2s: 143
>2s: 41
慢请求详情:
103.45.67.89 - [15/Jan/2024:14:23:11 +0800] "GET /api/pay/callback HTTP/1.1" 200 3245 5342ms
超过2秒的41个请求全得查,API回调这类接口延迟高影响的不止是体验,还有可能拖垮整个下单流程。
步骤8:实时监控脚本
#!/bin/bash
# 放在 crontab 每5分钟执行一次
LOG_DIR="/data/cdn-logs"
ALERT_EMAIL="ops@example.com"
HIT_RATE_THRESHOLD=80
# 获取最近1小时的日志
LOG_FILE=$(ls -t ${LOG_DIR}/*.gz | head -1)
# 计算命中率
HIT_RATE=$(gunzip -c $LOG_FILE | awk '{print $NF}' | sort | uniq -c | awk '$2=="HIT"{hit=$1} $2=="MISS"{miss=$1} END {printf "%.1f", hit/(hit+miss)*100}')
echo "当前命中率: ${HIT_RATE}%"
if (( $(echo "$HIT_RATE < $HIT_RATE_THRESHOLD" | bc -l) )); then
echo "警告: CDN命中率低于${HIT_RATE_THRESHOLD}%" | mail -s "CDN告警" $ALERT_EMAIL
# 记录异常日志
echo "$(date): HIT_RATE=${HIT_RATE}%" >> /var/log/cdn_alert.log
fi
# 检查502错误
ERROR_502=$(gunzip -c $LOG_FILE | awk '$9==502' | wc -l)
if [ $ERROR_502 -gt 50 ]; then
echo "警告: 1小时内502错误超过50次,当前: ${ERROR_502}次" | mail -s "CDN 502告警" $ALERT_EMAIL
fi
echo "监控完成: $(date)"
预期输出:
当前命中率: 91.2%
监控完成: Wed Jan 15 14:05:02 CST 2024
三、常见问题FAQ
Q:CDN命中率挺高的,但用户还是反馈慢,怎么查?
别死盯着命中率,命中率99%也有可能是1%的miss请求拖了后腿。用步骤7的慢请求分析方法,专门看那些响应时间超过1秒的请求。常见原因就几个:源站响应慢(查后端服务RT)、DNS解析慢(CDN节点选的不好)、跨运营商跨区域(看看用户是什么网络)、证书握手耗时(检查TLS版本和cipher suite)。还有个最容易被忽略的——TCP连接复用率低导致的建连开销。
Q:日志格式看不懂,CloudFront和阿里云的格式完全不一样怎么办?
这俩差别大了。CloudFront是自定义格式带JSON字段,阿里云是标准NCSA格式。你得先head -5看看日志长啥样,然后写awk的时候按实际字段位置来。记住一个原则:日志格式再乱,timestamp、status、size、cache-status这几列肯定有,找到对应位置就行。阿里云的日志里HIT/MISS在最后一列,CloudFront的得看x-edge-result-type这个字段。
Q:源站带宽没省多少,钱反而多花了,怎么跟老板解释?
这事儿说清楚很简单:CDN不省源站带宽,省的是你服务器要承载的并发连接数。原来的带宽峰值10Gbps,上了CDN后源站降到2Gbps,但CDN产生的流量账单可能是原来带宽费用的两倍。跟老板算这笔账:2Gbps源站带宽+CDN流量费 vs 原来10Gbps带宽费,哪个便宜用哪个。用户访问的稳定性、延迟改善这些没法直接量化,但投诉少了、业务高峰不挂了这都是CDN的价值。
Q:回源率突然飙高,啥原因?
先别慌,按这个顺序查:1)检查最近是不是上了新功能导致新文件没预热,2)看缓存规则是不是被谁改过,3)查源站是不是在回源时间段有503/504错误导致CDN缓存失效,4)确认下日志里的miss是集中在某些URL还是均匀分布——集中说明是特定资源问题,均匀说明是整体策略问题。还有个容易忽略的:源站设置了no-cache或者CDN的缓存头被覆盖了,用curl -I http://cdn地址 看看cache-control是不是符合预期。
四、总结
核心要点:
- 日志是CDN监控的根基,开通日志下载是第一步,别省这步
- 命中率低于80%就得查,90%以上才算健康
- MISS请求要分类:404/502说明源站问题,API/动态内容说明缓存策略问题
- 带宽分析能帮你优化大文件,流量TOP10URL得门清
- 慢请求分析别只看CDN节点延迟,源站RT才是重点
- 告警脚本要跑起来,别等问题爆发了才登录控制台
延伸阅读:
- Cloudflare博客:《Understanding CDN Cache Hit Ratios》
- 阿里云CDN文档:《缓存过期配置最佳实践》
- AWS re:Invent 视频:《Optimizing CloudFront Performance at Scale》
- NGINX博客:《CDN Logging and Analysis with ELK Stack》
记住,CDN不是配完就完事的,持续监控才是保证用户体验的关键。那些半夜投诉网站慢的,大概率是监控没做到位。