架构图画得很优雅:服务拆得干净、边界划得清楚、每个框都配了独立的负载均衡。上线三个月后看账单,最大的一项是流量——不是计算,不是存储,是数据在两个框之间来回走。而架构图上一个字节都不会体现这件事。
网络成本的特殊性在于按行为计费:请求次数、字节数、跨区次数,每个架构选择都在改计费模式。这篇按"账"的口径摆开四个来源、定价不对称的扭曲与减少流量的手段。
1. 四个成本来源与各自的计价方式
| 来源 | 计价单位 | 典型形态 | 可控性 |
|---|---|---|---|
| 出网流量(egress) | 每 GB,按目的地分档 | 用户下载、API 响应、备份外送 | 中:可压缩、可缓存 |
| 跨区 / 跨可用区流量 | 每 GB,按方向与区域对 | 多副本同步、跨区调用 | 高:架构决定 |
| 专线与互联 | 固定月费 + 端口带宽 | 机房互联、云间直连 | 高:合同决定 |
| 请求次数 / 连接数 | 每百万请求或连接 | 网关、CDN、LB、对象存储 | 中:可批量化 |
前两项随流量线性增长,第三项是阶梯式固定成本,第四项对"小请求"极其敏感。只盯出网流量会漏掉请求次数:2 KB 的响应流量近零,请求数照收。
2. 入网免费、出网收费:这个不对称如何扭曲架构
| 架构选择 | 被扭曲的方向 | 账单表现 |
|---|---|---|
| 数据下沉到计算侧 | 数据只进不出 | 一次搬运,长期免费读 |
| 计算上浮到数据侧 | 计算无状态,可随时换 | 出网只在结果返回时发生 |
| 多区域各存一份 | 写放大换读本地化 | 跨区写流量增加,出网减少 |
| 把所有东西放一个区 | 简单,但单点 | 出网集中、可用性下降 |
| 反向代理回源拉数据 | 回源流量算在源站出网 | 回源比例直接决定成本 |
不对称的后果是:"把数据搬到计算旁边"通常比"把计算搬到数据旁边"贵,前者一次性、后者持续。设计里凡是"每次请求都跨区取元数据",账注定难看。
3. 跨可用区高可用的隐性成本
多可用区部署常被当成"高可用标配",但它同时把每个内部请求变成跨区请求。
跨区成本 ≈ 请求频率 × 平均响应字节 × 跨区单价 × 2(请求与响应各一次)
有效倍数 = 跨区请求占比 → 1.0 时内部流量账单近似翻倍
| 部署形态 | 跨区流量 | 可用性 | 适合 |
|---|---|---|---|
| 单区多机 | 无 | 中 | 内部系统、可容忍短停机 |
| 双区主备 | 同步写跨区 | 高 | 有状态、需快速切换 |
| 双区双活 | 请求级跨区 | 最高 | 强一致读、低延迟要求 |
| 双区读写分离 | 读本地、写跨区 | 高 | 读多写少 |
"每个请求都跨区"是最常见的成因:服务、库、缓存分布在两个区,一次渲染跨区三次。单次不贵,乘上 QPS 就是主成本项。
4. 就近访问与"数据放哪"的联动
| 决策 | 数据位置 | 流量后果 |
|---|---|---|
| 用户就近接入 | CDN 边缘 | 出网最少,回源才是成本 |
| 计算就近数据 | 同区同可用区 | 内部流量近乎免费 |
| 读就近、写集中 | 本地副本 + 跨区写 | 写放大,读便宜 |
| 全局单库 | 一个区 | 所有读跨区,账单随 QPS 增长 |
"就近访问"不能独立于数据放置。只做接入层就近、数据仍在一个区,等于把跨区成本从用户侧搬到服务侧,总额不变,只换了科目。
5. CDN 的账:回源率决定成本
CDN 总成本 ≈ 边缘出流量 × 边缘单价 + 回源流量 × 源站出网单价
回源率 = 回源请求数 / 边缘请求数
有效单价 = 边缘单价 + 回源率 × 源站出网单价
| 缓存策略 | 回源率的量级 | 成本走向 |
|---|---|---|
| 全量不缓存 | 接近 100% | CDN 只增加成本,不减少 |
| 短 TTL(分钟级) | 较高 | 适合频繁变更的内容 |
| 长 TTL + 文件名指纹 | 很低 | 静态资源的最优形态 |
| 按路径分级 | 中等 | 静态长缓存、接口不缓存 |
判断 CDN 是否划算只有一个量:回源率 × 源站单价是否显著低于直连出网单价。命中率低时它只是个更贵的反向代理。
6. 对象存储与计算同区
| 位置关系 | 计费 | 延迟 | 建议 |
|---|---|---|---|
| 同区 | 内网流量通常不计费或极低 | 低 | 默认选择 |
| 跨可用区 | 按跨区计费 | 略高 | 仅在有可用性要求时 |
| 跨区域 | 按出网计费 | 高 | 只在灾备或分发时 |
| 跨云 | 出网 + 互联费 | 最高 | 尽量避免频繁读写 |
把训练数据、日志归档、静态资源放在计算所在区,是收益最高、改动最小的一条。
# 确认桶位置与实例可用区一致(子命令与输出字段按自己的云核对)
BUCKET_LOC=$(aws s3api get-bucket-location --bucket BUCKET --output text)
AZ=$(aws ec2 describe-instances --instance-ids INSTANCE \
--query "Reservations[0].Instances[0].Placement.AvailabilityZone" --output text)
echo "$BUCKET_LOC vs $AZ"
"桶在 A、任务在 B"的拓扑,先搬桶再谈优化。
7. 专线、公网加密隧道与私有互联
| 方式 | 成本形态 | 带宽与稳定性 | 适用 |
|---|---|---|---|
| 公网 + TLS 隧道 | 按流量,弹性 | 抖动大,受公网影响 | 小流量、临时互联 |
| 专线 | 固定月费 + 端口费 | 稳定,SLA 明确 | 持续大流量、跨机房 |
| 云厂商私有互联 | 固定端口费 + 出网费 | 稳定,配置简单 | 多云同厂商生态 |
| SD-WAN / 叠加网络 | 订阅费 + 公网流量 | 中等 | 多点互联、快速开通 |
判据是月流量是否稳定超过专线的盈亏平衡点:流量小且波动,固定费摊不平;流量大且稳定,按量计费很快越过月费。平衡点按自家合同价算。
8. 可观测:按服务、按目的地拆解出流量
-- 出流量按 服务 × 目的地类型 拆解(示意字段)
SELECT service,
dest_type, -- internet / cross_az / cross_region / cross_cloud
SUM(bytes_out) / 1e9 AS gb_out,
SUM(requests) AS requests,
SUM(bytes_out) / NULLIF(SUM(requests), 0) AS bytes_per_request
FROM network_flow_hourly
WHERE hour >= now() - interval '7 days'
GROUP BY service, dest_type
ORDER BY gb_out DESC;
bytes_per_request 一变大多半是响应体膨胀:未分页的列表、未压缩的 JSON、重复图片。
PromQL 侧的最小观测集(指标名按自家 exporter 核对)
sum by (service) (rate(net_egress_bytes_total[5m]))
sum by (service) (rate(net_requests_total[5m]))
9. 减少流量的四种手段
| 手段 | 作用点 | 适用条件 | 代价 |
|---|---|---|---|
| 压缩 | 传输字节 | 文本类响应、可接受 CPU 交换 | 客户端需支持,压缩比随内容变 |
| 缓存 | 重复请求 | 内容可缓存且有热点 | 一致性窗口变长 |
| 批量化 | 请求次数 | 高频小请求、可合并语义 | 首字节延迟上升 |
| 下沉计算 | 跨区传输 | 数据与计算分离的拓扑 | 需要改部署位置 |
下沉计算收益最大且最容易被忽略,它不改代码只改位置;压缩与缓存受内容类型限制;批量化能同时降低请求数与连接成本,代价是延迟。建议顺序:改位置 → 改缓存 → 改压缩 → 改批量。
10. 成本与延迟的交换
| 策略 | 延迟 | 流量成本 | 适用 |
|---|---|---|---|
| 跨区强一致读 | 高 | 高 | 强一致业务 |
| 本地读副本 | 低 | 低(读) | 可容忍秒级不一致 |
| 写集中、读本地 | 写高读低 | 中 | 读多写少 |
| 全本地(含写) | 最低 | 最低 | 需要冲突解决机制 |
交换的本质是把一致性换成"少跨一次区"。每次跨区读多出一次网络往返(同区域内部通常个位到两位数毫秒,按实际链路核对),乘上页面的串行请求数就是用户感知到的差距。
11. 多云互联的额外成本
| 成本项 | 形态 | 常被漏算的原因 |
|---|---|---|
| 跨云出网 | 两边都收出网费 | 只算了入口一侧 |
| 专线/互联月费 | 固定 | 立项时只估了流量 |
| NAT 与网关处理费 | 按流量或按小时 | 藏在网关账单里 |
| 跨云 DNS 与健康检查 | 按请求 | 量小但持续 |
多云互联的成本结构是"固定费 + 双份出网",合理场景是容灾与监管,不是摊薄单价。
12. 度量
| 指标 | 定义 | 用途 |
|---|---|---|
| 每千请求出流量 | 出网 GB / 千请求 | 响应体膨胀的早期信号 |
| 出流量占比 | 网络成本 / 总成本 | 判断网络是否已成主成本项 |
| 回源率 | 回源请求 / 边缘请求 | CDN 是否划算的唯一判据 |
| 跨区请求占比 | 跨区请求 / 总请求 | 高可用拓扑的真实价格 |
| 专线利用率 | 实际带宽 / 端口带宽 | 判断专线是否买大了 |
13. 排错
| 现象 | 常见原因 | 检查 |
|---|---|---|
| 网络费远超预算但流量曲线平稳 | 请求次数多、响应体小 | 看每千请求流量与请求计数 |
| CDN 上线后总成本没降 | 回源率接近 100% | 查缓存头与 TTL、是否带随机参数 |
| 跨区费用突增 | 新服务部署在错误可用区 | 对比服务与依赖的区分布 |
| 某接口流量占比异常 | 未分页、未压缩、返回大对象 | 看 bytes_per_request 排序 |
| 专线月费高但利用率低 | 端口买大、或流量走了公网 | 看端口利用率与路由 |
| 多云账单对不上 | 两侧口径不同、双向计费 | 归一化字段后重新归集 |
14. 边界
| 场景 | 结论 | 理由 |
|---|---|---|
| 纯内部系统、无外网访问 | 不做网络成本优化 | 内网流量通常不计费,收益为零 |
| 流量极小的服务(月 GB 级) | 优化收益低于投入 | 绝对值小,改动风险反而更大 |
| 同区部署且无外部访问 | 只保留观测 | 无跨区、无出网,无从优化 |
| 合规要求数据不出境 | 成本让位于合规 | 不可协商项优先 |
| 延迟是硬指标的业务 | 接受跨区成本 | 用钱换毫秒是合理交易 |
15. 自测
- 一次 2 KB 的响应几乎不产生流量费,为什么账单还是涨了?
- 为什么"把计算搬到数据旁边"通常比"把数据搬到计算旁边"便宜?
- 双活部署下内部流量为什么会接近翻倍?只看 QPS 能不能算出这个倍数?
- CDN 是否划算,应该看哪一个比值?命中率高时它省的是什么钱?
- 减少流量的四种手段,哪一种不改代码就能拿到最大收益?代价是什么?
- 专线的盈亏平衡点应该用公开报价算还是用合同价算,为什么?