本文约 5,451 字,预计阅读 14 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:带宽买少了网站卡,买多了每月白烧钱
服务器配置里最贵的一项往往不是 CPU 而是带宽。国内云厂商 1 Mbps 带宽月费约 20–25 元,10 Mbps 就是 200 多元一年上千元。很多站长要么凭感觉买(”先来 5 Mbps 吧”),要么被”不限流量”的宣传迷惑,结果要么高峰期打不开,要么每月账单一堆闲置带宽。
带宽和流量是两个容易混淆的概念:带宽是管道粗细(Mbps,决定同时能过多少数据),流量是流过的总量(GB,决定这个月用了多少)。国内服务器通常按带宽峰值计费(买 5 Mbps 就是峰值 5 Mbps),海外与 CDN 通常按流量计费(用多少 GB 算多少钱)。要把这两件事算清楚,只需要四个输入:日均 PV、单页平均体积、峰值系数、静态资源是否走 CDN。
原理分析:三个公式与一个换算
换算基础。 网络带宽单位 Mbps = Megabit per second(兆比特/秒),而文件大小常用 MB(兆字节)。1 Byte = 8 bit,所以:
理论下载速度(MB/s) = 带宽(Mbps) ÷ 8
1 Mbps ≈ 128 KB/s
5 Mbps ≈ 640 KB/s
10 Mbps ≈ 1.25 MB/s
实际可用约为理论值的 85%–90%(TCP/IP 头部开销、重传等),估算时按 0.85 系数打折。
公式一:单页传输量。
单页体积 = HTML(gzip 后) + CSS + JS + 图片 + 字体
典型 WordPress 站点单页体积参考:极简博客 300–600 KB;带配图的文章页 1–2 MB;电商首页 2–4 MB;未优化的图片站 5 MB+。按 F12 开发者工具 Network 面板底部的 “transferred” 值最准确。
公式二:月流量。
月流量(GB) = 日均 PV × 单页体积(MB) × 30 ÷ 1024
举例:日均 5000 PV,单页 1.2 MB → 5000 × 1.2 × 30 ÷ 1024 ≈ 176 GB/月。如果用了 CDN,这 176 GB 里约 85%–95% 由 CDN 承担,源站只剩 10–25 GB。
公式三:峰值带宽。
峰值带宽(Mbps) = 峰值并发 × 单页体积(MB) × 8 ÷ 目标加载时间(秒) ÷ 0.85
其中峰值并发 = 日均 PV × 峰值集中比例 ÷ 集中时段秒数 × 单用户平均请求数。
三个公式的实际应用里有几个容易被忽略的修正项:爬虫流量(未优化的站点爬虫可能吃掉 30% 以上的带宽,可以用 robots.txt 的 Crawl-delay 或 CDN 的爬虫限速控制)、盗链(图片被别的站直接引用,流量算你的,用 Nginx 的 valid_referers 防盗链)、API 与后台(APP 接口、定时任务、备份上传也走带宽)。
保姆级实操:从日志里算出你的真实数字
步骤 1:从 Nginx 日志统计真实 PV 与流量。 不要拍脑袋估,先看已有数据:
# 统计昨天的总请求数(近似 PV 的上限)
grep "$(date -d yesterday +%d/%b/%Y)" /var/log/nginx/access.log | wc -l
# 只看 HTML 页面请求,排除静态资源(更接近真实 PV)
grep "$(date -d yesterday +%d/%b/%Y)" /var/log/nginx/access.log \
| grep -E 'GET /[^.]* HTTP|GET /(|\?.*) HTTP' | wc -l
# 统计当天发出的总字节数($body_bytes_sent 通常在日志最后一列)
awk '$(NF) ~ /^[0-9]+$/ {sum += $(NF)} END {printf "总流量: %.2f GB\n", sum/1024/1024/1024}' \
/var/log/nginx/access.log
# 找出流量消耗最大的前 20 个 URL(定位大文件或盗链)
awk '{print $7, $(NF)}' /var/log/nginx/access.log \
| awk '{arr[$1]+=$2} END {for (i in arr) printf "%.1f MB\t%s\n", arr[i]/1024/1024, i}' \
| sort -rn | head -20
步骤 2:用 GoAccess 看完整的带宽与访客曲线。 命令行统计适合快速查,看趋势建议装 GoAccess:
# 安装
sudo apt install -y goaccess
# 生成实时终端报告(按提示选择 NCSA Combined Log Format)
sudo goaccess /var/log/nginx/access.log --log-format=COMBINED
# 生成 HTML 报告,看每天的带宽峰值与访客分布
sudo goaccess /var/log/nginx/access.log \
--log-format=COMBINED \
-o /var/www/html/stats.html \
--real-time-html
步骤 3:实测单页体积。 用 curl 测首屏 HTML 与整页资源的实际传输量:
# 测首页 HTML 经 gzip 后的大小
curl -s -H 'Accept-Encoding: gzip, deflate, br' -o /dev/null \
-w 'HTML传输大小: %{size_download} bytes\n耗时: %{time_total}s\n' \
导航
# 分别看各阶段的耗时,定位是传输慢还是服务器慢
curl -s -o /dev/null -w \
'DNS: %{time_namelookup}s | 连接: %{time_connect}s | TLS: %{time_appconnect}s | 首字节: %{time_starttransfer}s | 总耗时: %{time_total}s | 下载: %{size_download}B\n' \
导航
步骤 4:把数字代入公式算出带宽与流量。 用一个可复用的计算脚本:
python3 -c "
pv = 5000 # 日均 PV
page_mb = 1.2 # 单页体积 MB
peak_rate = 0.10 # 峰值时段集中比例
peak_hour = 2 # 峰值持续小时数
target_s = 3 # 期望整页加载秒数
cdn_ratio = 0.90 # CDN 承担的静态资源比例
monthly_gb = pv * page_mb * 30 / 1024
origin_gb = monthly_gb * (1 - cdn_ratio)
concurrency = pv * peak_rate / (peak_hour * 3600) * 20 # 20 为单用户平均请求数
bw = concurrency * page_mb * 8 / target_s / 0.85
print(f'月总流量 : {monthly_gb:.1f} GB')
print(f'CDN 后源站流量: {origin_gb:.1f} GB')
print(f'峰值并发请求 : {concurrency:.2f}')
print(f'建议源站带宽 : {bw:.2f} Mbps')
"
步骤 5:按计算结果选择计费方式。 国内服务器的临界点很好算:如果算出的峰值带宽低于 5 Mbps,买固定带宽划算;如果峰值高于 10 Mbps,用”按流量计费 + CDN”更省钱。 因为固定带宽买的是峰值,而大多数站点一天里只有两三个小时会跑到峰值。
步骤 6:配置 Nginx 限速与压缩,降低带宽消耗。 这些配置直接把带宽账单打下来:
# /etc/nginx/nginx.conf 的 http 块
http {
# 开启 gzip 压缩,文本类资源可压缩 60%-80%
gzip on;
gzip_vary on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_proxied any;
gzip_types text/plain text/css application/javascript application/json
application/xml image/svg+xml;
# 静态资源长缓存,配合 CDN 大幅减少回源
server {
location ~* \.(jpg|jpeg|png|gif|webp|ico|css|js|woff2?)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
# 防盗链,避免图片被外站引用吃掉你的流量
valid_referers none blocked server_names *.mimangfei.com;
if ($invalid_referer) {
return 403;
}
}
}
}
改完记得 sudo nginx -t && sudo systemctl reload nginx。
步骤 7:设置带宽水位监控。 在云厂商控制台配置带宽告警(如持续 5 分钟超过带宽上限的 80%),或者用 vnStat 在机器上自统计:
sudo apt install -y vnstat
sudo systemctl enable --now vnstat
# 查看今日/本月流量
vnstat -d
vnstat -m
# 实时看网卡速率(单位 MB/s,乘以 8 就是 Mbps)
vnstat -l -i eth0
常见踩坑
- 把 Mbps 当成 MB/s。 5 Mbps 的实际下载速度约 0.6 MB/s,不是 5 MB/s,这是最常见的换算错误。
- 只算 HTML 不算图片。 一个”文字为主”的博客,一张未压缩的 3 MB 头图就能抵得上 50 次 HTML 请求。
- 忽略爬虫与恶意扫描。 新站上线后每天有大量扫描请求访问
/wp-login.php、/xmlrpc.php,虽然单次流量小,但高并发时会吃掉可观带宽。可以用 fail2ban 拦掉。 - CDN 回源流量也算钱。 静态资源缓存命中率低时,CDN 会频繁回源,源站带宽和 CDN 流量双重计费。提高命中率的关键是配置正确的
Cache-Control头。 - 备份和同步走公网带宽。 用 rsync 或 rclone 往另一台机器备份时会跑满带宽,导致网站打不开。备份任务要用
trickle限速或安排在凌晨。 - 案例:一次”流量暴增”排查。 客户某天收到云厂商告警,说流量是平时的 8 倍。登录服务器用上面第 1 条的 awk 脚本统计 Top URL,发现一个 2.4 MB 的 PDF 产品手册被某行业论坛直接链接,24 小时内被下载了 6000 多次,吃掉 14 GB 流量。处理方式是:先加了 Nginx 的
valid_referers防盗链拦住外站引用(允许空 referer 以免误伤正常用户),再把 PDF 迁到对象存储并设置 Referer 白名单,同时在 CDN 上配置单 IP 限速。教训:大文件一定要配防盗链和限速,且不要放在源站的 Web 目录下直连下载。
总结
带宽估算的落地顺序是:先用 Nginx 日志和 curl 测出真实的 PV、单页体积、峰值分布,再代入公式,最后用 CDN + gzip + 浏览器缓存把结果压下来。经验值:日均 5000 PV、单页 1.2 MB 的 WordPress 站,上 CDN 后源站流量约 18 GB/月,3–5 Mbps 带宽足够。上线后装个 vnStat 持续观察,跑满 80% 就扩容,别等崩了再处理。算清楚带宽之后,服务器选型指南 里的配置表可以直接对照执行;如果访客主要在海外,还要结合 国内与海外服务器对比 中不同地域的计费方式(按流量 vs 按带宽)重新算一遍。
