一、下载站的流量画像,和访问网页完全是两种生意

选下载站VPS 的时候,很多人是按建站的思路看配置的:核数、内存、磁盘容量,挑一台内存大一点的就行。这套判断在下载站上会直接失效,因为下载站的成本结构里,CPU 和内存只占很小一部分,真正的开销是出口带宽和月度流量。
延伸对照:interserver 的公开机型与线路说明,可结合本节的判断标准自行核对。
根本原因是传输量。访问一个网页,浏览器会拉取几十到几百 KB 的 HTML 加静态资源,一个访客一次会话的总下载量通常在几百 KB 到几 MB。而下载一个安装包动辄几百 MB,下载一部视频是几个 GB。单个用户产生的流量差距是三个数量级,更关键的是这种流量是不可缓存的——网页可以被 CDN 缓存到边缘节点反复命中,下载文件每次都是实打实的源站出网。
第二个差别是并发形态。网页是大量短连接、每个连接传一点点数据;下载是少量长连接、每个连接长时间占满带宽。网页场景下瓶颈通常是请求处理能力,下载场景下瓶颈几乎总是出口带宽和网卡队列。一台 8 核 64G 的服务器配 100 Mbps 带宽,能同时服务上百个网页请求,但换成 1 Gbps 带宽,它能服务的下载并发也只有二十个上下。
第三个差别是流量集中度。下载站的访问往往不是全天均匀的,而是集中在版本发布后的几小时。软件更新、热门资源、限时活动都会制造尖峰。尖峰期如果出口打满,所有用户一起变慢,而不是一个变慢。
| 场景 | 单次下载量 | 典型并发 | 瓶颈所在 | 成本主导 |
|---|---|---|---|---|
| 软件安装包分发 | 100 MB 至 2 GB | 数十到数百 | 出口带宽 | 流量费 |
| 影视资源下载 | 1 GB 至 20 GB | 数十 | 出口带宽 | 流量费 |
| 开源镜像仓库 | 50 MB 至 500 MB | 数百 | 带宽与并发 | 两者 |
| 素材与附件下载 | 1 MB 至 50 MB | 上千 | 请求处理 | 带宽费 |
| 示例数据与文档附件 | 几百 KB 至 5 MB | 数千 | 连接数 | 带宽费 |
这张表给出的第一个结论是:下载站的机器配置几乎不用为峰值操心,核心矛盾永远是出口。第二个结论藏在第五行,小文件下载的瓶颈是请求处理和连接数,这时 CPU 和内存反而会先成为限制,得靠 Nginx 调优和连接数控制来解。
还有一个常被算漏的成本项是存储本身。下载站要长期保存大量文件,文件占用的是磁盘容量,容量不够就要买更大的盘或者做清理策略。廉价的机械硬盘容量单价低但小文件场景慢,SSD 容量单价高但快。这个取舍在文件以大包为主时无所谓,在以小文件为主时就会直接反映在响应时间上。
另外,下载站有一个普通网站没有的收入或者流量特征:下载请求可能来自非浏览器客户端,比如更新脚本、CI 流水线、第三方应用。这些请求的用户代理和来源分布与真人访问完全不同,做流量分析和限流时如果只按浏览器行为建模,会把正常的大客户误判成爬虫。
二、带宽和流量两种计费方式,决定了完全不同的成本模型

下载站VPS 的账单有两种完全不同的生成方式,选错模式会让同一个业务在一家商家花小钱、在另一家花大钱。
延伸对照:itldc 的公开机型与线路说明,可结合本节的判断标准自行核对。
第一种是按带宽计费,按固定带宽月租,同时限制峰值速率。你买 100 Mbps 就是每月付 100 Mbps 的钱,无论实际用了多少。这种模式成本可预测,流量涨到把带宽打满也不会产生额外账单,代价是超过带宽上限之后所有用户一起变慢,而且闲置的时候付的是纯浪费。对下载站来说这是最常见的模式。
第二种是按流量计费,按实际出网流量乘以单价结算,常见单价在每 GB 零点零几美元到零点几美元之间,具体以各商家官网当日报价为准。这种模式下带宽峰值可能给得很高,只是不保证,实际用多少付多少。它的风险在于账单不可预测——一个被批量抓取的链接可以在几小时内吃掉几个月预算。
第三种是混合模式,包含一定流量的流量包,超出后按单价计费,或者超出后降速不断线。还有第四种,突发带宽计费,允许在短时间内跑满更高的峰值,按突发量单独计价。
# 查看当前网卡实时出网速率,确认单位是 bit 还是 Byte
iftop -i eth0 -f
# 或者用 sar 看历史流量峰值
sar -n DEV 1 60 | grep -E "eth0|ens"
# 抓一分钟的接口流量,看有没有被限速的迹象
nload -f /tmp/traffic.log -t 60 eth0
判断模式对不对有个简单办法:把上个月的账单除以当月实际出网流量,得到你的实际单价,再和商家的标称单价比较。如果实际单价明显高于标称,说明流量包没用满、超出部分被按更高单价计了;如果实际单价远低于标称,说明包月带宽有大量闲置,把流量包换成带宽计费可能更划算。
按带宽计费还有一个隐含风险叫降速而非停机。有些商家在跑满带宽额度后只是把速率降到一个很低的值,服务器还在服务,但每个用户的下载速度可能只有几百 KB 每秒。这时候如果用户看到的是慢而不是错误,就会反复重试,流量凭空翻几倍,你的账单和用户体验同时崩掉。所以要问清楚商家:超限之后是断线、限速到多少、还是计费继续。
三、月流量怎么估:三个口径和四个误差来源

下载站最怕的就是账单来了才发现估错了。估流量的正确做法是分三个口径算,而不是拍一个总数。
延伸对照:iwebfusion 的公开机型与线路说明,可结合本节的判断标准自行核对。
第一个口径是日志统计,这是最准的。直接分析 Nginx 或者对象存储的访问日志,把响应字节数按月汇总,再乘以请求数,得到真实的出网总量。日志里如果没有字节数字段,要在 Nginx 里加上。
# 汇总 Nginx 访问日志里的出网字节数(GB)
awk '{sum+=$10} END {printf "总计 %.2f GB\n", sum/1024/1024/1024}' access.log
# 按天拆分,看流量集中在哪几天
awk '{d=substr($4,2,11); sum[d]+=$10} END {for (k in sum) printf "%s %.2f GB\n", k, sum[k]/1024/1024/1024}' access.log \
| sort
# 找出下载量最大的十个文件,评估优化优先级
awk '{sum[$7]+=$10} END {for (k in sum) printf "%.2f %s\n", sum[k]/1024/1024, k}' access.log \
| sort -rn | head -10
第二个口径是业务推算。用注册用户数乘以人均下载次数乘以平均文件大小,再乘以一个冗余系数。这个口径适合上线前估算,误差主要来自人均下载次数的假设。
第三个口径是行业参考值。经验上,软件分发类站点的下载流量与日活的比例大致在每活跃用户每天几十 MB 到几百 MB 的量级,影视和素材类会高出一个数量级。这个口径只能用来做最初的可行性判断,不能用来做采购决策。
四个主要误差来源要特别注意。第一是爬虫和批量下载,正常用户的下载和脚本批量抓取的流量可能差几倍,而且爬虫流量完全无价值却要付全价。第二是重试和断点续传,客户端网络断开后从头重下的流量在日志里是两次完整下载。第三是预取和 Range 请求异常,部分客户端会请求整个文件范围做校验。第四是统计口径本身,有些面板统计的是入口流量而账单算的是出口流量,两者通常接近但不完全相同。
# 找出疑似爬虫的来源 IP 排行
awk '{print $1, $10}' access.log | awk '{s[$1]+=$10} END {for (k in s) print s[k]/1024/1024, k}' \
| sort -rn | head -20
# 对比入口与出口字节数,确认统计口径
ip -s link show dev eth0
四、CDN 和对象存储,什么时候上,怎么算这笔账

下载站上 CDN 或者对象存储不是为了提速,而是为了省钱和把风险转移出去。这个判断要算清楚,因为 CDN 的成本模型和源站完全不同。
延伸对照:racknerd 的公开机型与线路说明,可结合本节的判断标准自行核对。
源站计费是按你的服务器出网流量收钱,不管文件被下多少次。CDN 的计费是按流量收钱加上请求数收钱,同样是流量,但价格结构不一样:CDN 的单位流量单价通常高于普通 VPS 带宽折算出来的单价,但 CDN 的边缘缓存会让热点文件的流量在边缘命中,不再回源。下载站的下载是典型的长尾加热点结构,一个安装包可能被下载几十万次,如果这个文件进了 CDN 边缘缓存,回源流量几乎归零。
# 检查文件的缓存命中率:命中行里 "HIT" 的比例
awk '{print $6}' access.log | sort | uniq -c
# 找出回源次数最多的文件,这些是 CDN 缓存没生效的重点
grep "MISS" access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
对象存储是另一种思路。文件放对象存储加 CDN,源站只做鉴权签发下载链接,文件本体不经过 VPS 源站。这样源站的带宽成本几乎归零,成本转移到对象存储的存储费加流量费。存储费通常很便宜,流量费是主要部分,而且对象存储的流量单价一般比 CDN 便宜,配合 CDN 边缘缓存,整体成本常常低于源站直出。
还有一个折中方案是源站只做跳转而不做转发。源站收到请求后返回一个 302 指向对象存储或 CDN 的地址,文件传输完全在存储侧完成。这个方案改造量很小,通常只需要改下载接口的返回方式,但要注意浏览器和客户端对重定向的处理,以及能否正确传递签名参数。
| 方案 | 成本构成 | 适合的下载量 | 优点 | 代价 |
|---|---|---|---|---|
| 源站直出 | 带宽月租加流量费 | 每月几百 GB 以内 | 简单、无额外组件 | 峰值易被打满、无冗余 |
| 源站加 CDN 回源 | 源站流量加 CDN 流量 | 每月几 TB 以内 | 热点文件成本大降 | 回源仍有流量成本 |
| 对象存储加 CDN | 存储费加 CDN 流量 | 每月几十 TB 以上 | 成本最省、可无限扩容 | 需要改造下载链接逻辑 |
| 多源加分流 | 上述组合 | 大流量且有商业化 | 可分流可灰度 | 架构复杂度最高 |
判断分界线很简单:算一下你的月度总流量和其中热点文件占比。如果热点文件占了总量的一半以上且下载次数超过几千次,上 CDN 或对象存储基本立刻回本。如果流量全是长尾冷门文件,源站直出更划算,因为 CDN 对每个请求还要收请求数费用,长尾文件的请求费占比会很高。
五、限速策略:限单连接还是限总出口

下载站的限速有两个层次,搞混了就会伤害用户体验。第一个层次是限单连接速率,也就是每个用户最多能跑多少 Mbps。这个做法能让带宽在多个用户之间公平分配,用户不会因为一个人狂下把所有人都挤成龟速,是下载站的标准做法。
延伸对照:zenlayer 的公开机型与线路说明,可结合本节的判断标准自行核对。
第二个层次是限总出口,也就是限制整个网卡的总速率。这是商家的套餐上限,你无法突破。理解这一点很重要:如果你买了 1 Gbps 带宽、开了 100 个并发用户、单连接限 10 Mbps,那么理论上总速率上限就是 1 Gbps,100 个用户每个 10 Mbps 正好填满。所以单连接限速值乘以预期并发数,就是你需要的总带宽。
# 限制单连接的下载速率:限速 5 MB/s,超时的连接被断开
limit_rate 5m;
limit_rate_after 1m; # 前 1 秒不限速,给连接建立留出时间
server {
location /download/ {
limit_rate 5m;
limit_conn addr 4; # 同一 IP 最多 4 个并发下载连接
limit_req zone=dl_zone burst=10 nodelay;
proxy_pass http://127.0.0.1:8080;
}
}
限速值怎么定有个实际考量。用户在浏览器里感知速度时,低于每秒几百 KB 就会觉得卡,低于每秒几十 KB 会直接以为坏了。如果你的带宽总量有限,宁可让每个用户跑得更快但可用人数少一点,也不要让所有人共享一个很低的速率。具体数值要结合你的总带宽和预期并发算,同时留出余量给网页和接口。
限速还应该按文件类型分档。大文件适合给高速率,因为它本身传输时间长,慢速下载会让用户等很久;小文件适合给较低速率甚至可以不限,因为传输时间本来就短,限速反而显得莫名其妙。Nginx 可以按 location 分别设置不同的 limit_rate,实现起来只是多写几段配置。
另外要处理限速带来的技术副作用。启用限速之后,每个慢速连接会长时间占住一个服务端连接和文件描述符,连接数会暴涨,所以 limit_conn 和文件描述符上限必须一起调,否则限速反而把服务器打挂。
六、防盗链与访问控制:签名 URL 才是真防线

下载站的防盗链是必须做的一件事,但要清楚每种方案的实际效果,别把 Referer 检查当安全措施。
延伸对照:cloudcone 的公开机型与线路说明,可结合本节的判断标准自行核对。
Referer 检查是最容易做也最容易被绕过的。伪造 Referer 只需要改一个请求头,脚本几行代码就能做到。Referer 检查唯一的价值是挡住普通的直接链接分享,比如把链接贴到论坛里被人直接贴到下载页上。它挡不住任何有心的批量下载。
真正有效的方案是签名 URL 加短有效期。服务端按约定算法把文件路径、过期时间、用户标识算成一个签名,URL 里带上签名和过期时间,Nginx 用 secure_link 模块或者一段校验脚本验证。签名算错或者已过期就返回 403。这样链接被转发出去也只能在有效期内用,过期就废。
# 生成带签名的下载链接:签名 = md5(路径 + 密钥 + 过期时间戳)
FILE="/downloads/app-2.1.0.zip"
EXPIRE=$(($(date +%s) + 3600))
SECRET="your-secret-key"
SIG=$(echo -n "${FILE}${EXPIRE}${SECRET}" | md5sum | cut -d' ' -f1)
echo "https://dl.example.com${FILE}?expire=${EXPIRE}&sig=${SIG}"
# Nginx 侧用 secure_link_md5 校验,签名不一致直接 403
# secure_link_md5 "$secure_link_expires$uri$remote_addr$secret";
再加一层是账号绑定,把签名和用户 ID 关联,只允许登录用户下载,这样文件链接既不能公开传播也不能被多账号共用。要注意下载本身可能是游客行为,那就退一步做 IP 维度的速率限制和每日配额。
还有一个常被忽略的问题是文件的直链泄露。一旦源站 IP 暴露,别人可以绕过你的应用直接访问文件路径,前面的签名和鉴权全部失效。解决方式有两条:源站只允许 CDN 回源 IP 访问,其余一律拒绝;或者把文件本体放在对象存储,源站只签发带时效的下载链接。
盗链防护还有一个容易忽略的层面是分享渠道本身。下载链接被贴到社交平台、论坛或者群里之后,传播速度和流量会远超预期,尤其是有奖励机制的分享活动。给不同渠道生成不同的签名密钥,一旦某个渠道的密钥出现异常流量,立刻作废该密钥而不影响其他渠道,这样能把损失控制在单渠道。
七、机房选择:下载站对线路的敏感点在哪

下载站选机房时最容易犯的错,是按自己所在的位置选。用户在国内就买国内机房,用户在海外就买美国,这是直觉,但直觉在下载站上经常导致成本浪费。
延伸对照:digitalocean 的公开机型与线路说明,可结合本节的判断标准自行核对。
原因是下载站的传输是持续大流量的长连接,单次传输量大。跨洲链路的物理往返时间依然是那个下限,但下载场景下这个下限只占总时间的一小部分——一个 1 GB 的文件即使跑在 100 Mbps 的链路上也要跑八十多秒,多出来的 200 毫秒往返时间几乎可以忽略。所以下载站的体验主要由带宽速率和丢包决定,而不是由延迟决定。
# 从用户侧测实际下载速度,多试几个大文件
curl -o /dev/null -w "speed=%{speed_download} B/s time=%{time_total}s\n" \
https://dl.example.com/test/1GB.bin
# 看路由和丢包,确认没有绕路
mtr -r -c 100 -n dl.example.com
# 测大流量下的稳定性,看有没有周期性掉速
iperf3 -c speed.example.com -t 30 -P 8
由此推出三条选型结论。第一,如果用户主要在国内,选择回程质量好的机房比选择物理距离近更关键,带宽速率和丢包率是下载体验的决定因素。第二,如果用户分布在全球,考虑就近的多个源站加分发,但是否值得做多源取决于月流量规模,流量不大时多源的复杂度不划算。第三,机房选择还要看存储介质,下载站的源站要读大量文件,机械硬盘的顺序读可以给到上百 MB 每秒,但随机 IO 和大量小文件场景会明显拖后腿,这时优先选 SSD 或者 NVMe 存储的套餐。
带宽数字也要问清楚口径。有些套餐写的是端口速率,就是网卡能跑到的上限,不代表任何时候都能跑到;有些套餐写的是保证带宽,超出部分不保证,这两种在下载站的实际体验差别很大。理想状态是写明保证带宽并给出超限后的处理规则。
# 连续测速多次,取最低值而不是最高值,下载体验取决于最差情况
for i in $(seq 1 5); do
curl -o /dev/null -w "speed=%{speed_download}\n" https://dl.example.com/test/1GB.bin
done
八、大文件还是小文件:IO 特征和并发模型完全不同

下载站的磁盘压力取决于文件形态,这个差异会直接决定机器规格和 Web 服务器的配置。
延伸对照:hostwinds 的公开机型与线路说明,可结合本节的判断标准自行核对。
大文件分发是顺序读。系统可以顺序预读,几百 MB 的文件在 SSD 上几乎不产生等待,在机械硬盘上也能跑出上百 MB 每秒。这类场景的瓶颈在网卡,不在磁盘,很多下载站的机器配置完全用不上。
小文件分发是随机 IO。几 KB 的文件散布在目录树里,每次请求都是一次随机定位,而且这些文件通常要放进页缓存供下次复用。机械硬盘在这一场景下的表现会比 SSD 差一个数量级,表现出来就是并发一高磁盘 await 值飙升,Nginx 响应变慢。
# 测磁盘随机读性能:小文件场景的关键指标
fio --name=randread --filename=/tmp/testfile --size=2G \
--rw=randread --bs=4k --iodepth=32 --direct=1 --numjobs=4
# 测顺序读:大文件分发的关键指标
fio --name=seqread --filename=/tmp/testfile --size=2G \
--rw=read --bs=1M --direct=1 --iodepth=16
# 线上实时观察磁盘等待
iostat -x 2
除了存储介质,还有几个可以立刻见效的优化。第一是开启 sendfile,让内核直接把文件内容发到网卡,避开用户态的一次拷贝,在大文件场景下能提升百分之十到三十的吞吐。第二是调整文件描述符上限,下载站的并发连接多,默认的一千远远不够。第三是把下载文件和站点文件分开放到不同的目录甚至不同的磁盘,避免大文件下载的顺序读把网页的随机读挤掉。
# 确认 sendfile 是否开启
nginx -V 2>&1 | grep -o "sendfile_on"
# 提高文件描述符上限
ulimit -n 65535
echo "fs.file-max = 2097152" >> /etc/sysctl.conf
sysctl -p
九、成本模型与选型决策

把前面的数字串起来,下载站VPS 的成本可以拆成三块:带宽月租、超额流量费、机器与存储的固定成本。前两块是主要变量,第三块相对稳定。
延伸对照:justg 的公开机型与线路说明,可结合本节的判断标准自行核对。
带宽月租按总带宽乘月单价算,这是刚性的,跟你实际用没用满无关。超额流量费按超出流量包的部分乘以超额单价。机器成本则按核数、内存、存储规格的组合定价。
举一个估算例子。假设一个月出网流量八百 GB,其中热点文件占六成,热点文件被重复下载的次数平均在三千次。这个结构适合上 CDN:源站只回源一次,CDN 边缘承担剩下的流量,源站带宽可以从 1 Gbps 降到 200 Mbps,机器也能相应降配。反过来,如果流量全是一万次冷门文件的一次性下载,上 CDN 就没有意义,因为边缘缓存永远命中不了,只会在原成本上再加一层请求费。
| 你的情况 | 建议方案 | 关键判断依据 | 不要做的事 |
|---|---|---|---|
| 月流量几百 GB 以内 | 源站直出,按带宽计费 | 成本低于架构复杂度 | 不要为了将来可能涨量而提前上 CDN |
| 月流量几 TB 且有热点 | 源站加 CDN 回源 | 热点重复下载次数过千 | 不要把所有文件都推上 CDN |
| 月流量几十 TB 以上 | 对象存储加 CDN | 存储和流量成本随规模摊薄 | 不要用单台源站扛全部出网 |
| 小文件下载为主 | 高并发调优加 SSD | 瓶颈在请求处理和随机 IO | 不要用机械硬盘 |
机房的分布式程度也要跟着流量规模走。月流量在几百 GB 的时候,单机房加一台大带宽机器就够;到几 TB 级别,可以考虑两三个地区各放一台源站做分流;到几十 TB 级别,架构里必须引入对象存储,因为单台机器的网卡上限会成为硬约束。
选具体商家时,把这几家公开定位放进候选池对比:DigitalOcean 面向开发者与中小企业,可按小时计费自选配置并附带快照和防火墙;RackNerd 提供 KVM VPS 与 AI VPS,覆盖二十个数据中心并常有特价促销机型;CloudCone 同时经营云实例和独立服务器,可直接按 CPU 内存磁盘下单;Interserver 做云与裸机,也有托管与 GPU 业务;ITLDC 在多个全球机房提供 NVMe 与 HDD 虚拟服务器;Hostwinds 覆盖虚拟主机、VPS、云服务器与独立服务器;iWebFusion 提供共享主机、VPS、主机商与独立服务器并有全年支持;SpinServers 主做美国市场的即时与独立服务器;Zenlayer 侧重分布式云和全球网络加速;JUSTG 在东京、首尔、莫斯科等地提供云服务器和原生 IPv4。所有具体价格、带宽额度与流量包规则,一律以官网当日报价为准。
比价格更重要的是三件事:带宽上限是多少、流量包怎么算、跑满之后是降速还是断线。下载站最怕的是跑到上限直接断线,因为用户下到一半失败会立刻重试,流量翻倍而收入为零。
十、常见问题

下载站VPS 需要多大带宽才够用? 用并发数乘以单连接限速来估,再留两到三倍余量。假设你打算给每个用户 5 MB 的速度、同时容纳五十个用户,那么需要 250 Mbps,按三倍余量准备 1 Gbps 带宽比较稳妥。同时要确认商家的套餐允许的峰值带宽是多少,有的套餐名义带宽高但有突发限制。
按带宽计费和按流量计费哪个划算? 月流量稳定且在带宽额度以内,按带宽计费更便宜且账单可预测;流量波动大或者多数时间用不满带宽,按流量计费更省。判断方法是用上个月的账单除以实际出网流量得到真实单价,再和标称单价比。
月流量怎么估算才准? 上线前用业务推算法,上线后必须用日志统计法。Nginx 日志里的响应字节数汇总最准,重点看四个误差来源:爬虫批量抓取、客户端断线重下的重复流量、Range 请求异常,以及入口流量与出口流量的统计口径差。
下载文件应该放源站还是对象存储? 月流量在几百 GB 以内放源站最简单;超过几 TB 且有热点文件时,对象存储加 CDN 的成本优势明显,因为存储费便宜、边缘缓存能挡掉大部分重复下载、源站带宽可以大幅降低。具体单价以各家官网当日报价为准。
怎么防止下载链接被别人批量抓走? 有效的是签名 URL 加短有效期,再叠加账号绑定和每 IP 速率限制。Referer 检查只能挡普通分享挡不住脚本。源站 IP 也要藏好,只允许 CDN 回源 IP 访问,避免直链泄露后前面所有防护失效。
限速应该限单连接还是限总带宽? 两个都要。商家套餐限的是总出口,这个你改不了;自己在 Nginx 里限单连接速率,保证带宽在多个用户之间公平分配。开了限速之后要同步调大文件描述符上限和连接数上限,否则慢连接堆积会把服务器资源占满。
小文件下载站该选什么存储? SSD 或 NVMe,因为小文件是随机读,机械硬盘的寻道延迟会让并发一高就崩。用 fio 的 randread 加 4K 块大小测一次,这比看商家写的规格更可靠。
下载站和普通网站用同一台服务器行不行? 流量小的时候行,但要隔开存储目录和连接池。下载的大文件顺序读会把网页的随机读挤掉,下载占用的文件描述符也会让网页请求失败。下载量超过几百 GB 每月之后,源站就只做签名和跳转,把文件交给对象存储。

喜欢
高兴
鬼脸
呵呵
无聊
伤心