47.5 南北向与东西向流量
一句话
南北向是「用户 → 系统」的入口流量,东西向是「服务 → 服务」的内部流量;两者的差别不在方向,而在信任边界、调用方数量、故障放大方式——所以前者重身份收敛与入口防护,后者重身份加密、连接复用与重试预算。
两种流量
┌──────────── 南北向(North-South)────────────┐
用户/客户端 ──▶ CDN ──▶ WAF ──▶ 入口网关 ──▶ 服务 A
│
├──▶ 服务 B ┐
├──▶ 服务 C ├─ 东西向(East-West)
└──▶ 服务 D ┘
| 维度 | 南北向 | 东西向 |
|---|---|---|
| 调用方 | 互联网用户、第三方、客户端 App | 内部服务(可能是几百个) |
| 协议 | HTTP/1.1、HTTP/2、HTTP/3、WebSocket | gRPC、HTTP/2、Thrift、MQ、DB 协议 |
| 身份 | 终端用户(JWT/OAuth2/API key) | 工作负载(mTLS/SPIFFE、服务账号) |
| 加密 | 在入口终结 TLS(后面可能明文) | 全链路 mTLS(零信任) |
| 负载均衡 | 四层(L4)+ 七层(L7),DNS/GSLB 分流 | 客户端 LB、sidecar、服务注册表 |
| 流量特征 | 峰值明显、突发、可能被攻击 | 恒定、内部可预测、但扇出大 |
| 故障放大 | 入口挂 = 全站不可用 | 一个依赖挂 = 沿调用链放大成雪崩 |
| 典型组件 | CDN、WAF、Ingress/Gateway、GSLB | Service Mesh、注册中心、连接池、重试/熔断 |
东西向的四个特殊问题
① 连接数爆炸
100 个服务、每个服务 50 个实例:
| 连接方式 | 连接数量级 | 说明 |
|---|---|---|
| 实例全互联 | 5000 × 4999 / 2 ≈ 1250 万 | 不可能维护:端口、内存、健康检查全部爆炸 |
| 客户端 LB + 连接池(每实例:上游实例数 × 池大小) | 单个实例约 3 × 10 = 30,全集群约 15 万 | 收敛 80 倍,这是 mesh/sidecar 的核心价值 |
| 服务端 LB(VIP) | 客户端只连 VIP,连接数与后端实例数解耦 | 多一跳,但连接管理最简单 |
🔑 东西向连接的第一原则:连接数由"客户端实例数 × 池大小"决定,不由"服务数"决定。不做连接复用,1000 QPS × 每请求一次握手,握手就吃掉一半 CPU(见 8.3 连接复用与 TIME_WAIT)。
② 重试风暴
三层都配"失败重试 3 次",最坏情况一次用户请求变成 3 × 3 × 3 = 27 次下游调用:
| 层 | 配置 | 放大 |
|---|---|---|
| 网关 | 重试 3 次 | 3× |
| 服务 A | 调 B 重试 3 次 | 3× |
| 服务 B | 调 C 重试 3 次 | 3× |
| 合计 | 27× |
这就是"下游只是慢了 10%,却被重试打死"的机制。约束:只在一层做重试(通常是离用户最近、且知道幂等性的那一层),其余层用超时 + 快速失败;重试必须带预算(见 35.5 超时、重试与退避)。
③ mTLS:身份正确,但要付握手成本
| 成本项 | 量级 | 摊薄方式 |
|---|---|---|
| TLS 1.3 握手 | 1 RTT + 非对称运算(同机房约 0.1–0.3ms) | 连接复用后几乎为 0 |
| 证书轮换 | 每次轮换全集群重连 | 短连接 + 平滑重载;证书 TTL 别设太短 |
| CPU | 新建连接速率决定,不由 QPS 决定 | 会话复用、连接池预热 |
所以"零信任 = 每请求握手"是误解:每连接一次 mTLS,连接复用后身份就随连接走(见 38.8 零信任)。
④ 跨 AZ / 跨地域的流量成本
| 路径 | 延迟 | 成本 | 策略 |
|---|---|---|---|
| 同 AZ | < 1ms | 免费 | 优先本地调用 |
| 跨 AZ | 1–2ms | 按 GB 计费(量级:每 GB 几美分) | 就近路由、读本地副本 |
| 跨地域 | 10–100ms | 高(专线 + 出网) | 只同步异步数据,别做同步调用 |
算一笔账:每天 10 TB 跨 AZ 流量,按 0.01 元/GB 量级 ≈ 100 元/天 ≈ 3000 元/月;同样的量如果因为"服务没做就近路由"全部跨 AZ,成本线性放大。就近路由(zone-aware routing)是省钱的架构决策,不只是性能优化。
南北向的四个特殊问题
| 问题 | 机制 | 防线 |
|---|---|---|
| DDoS | 流量在到达源站前就被打满带宽 | CDN/清洗中心、Anycast、弹性带宽 |
| TLS 终结与证书 | 证书过期、链不全、SNI 配错 | 集中管理 + 到期告警(提前 30 天)+ 灰度换证 |
| WAF / Bot | SQL 注入、爬虫、撞库 | 规则 + 速率限制 + 行为挑战(见 38.6 常见攻击) |
| 多地域接入 | DNS 解析、就近接入、地域故障 | GSLB/GeoDNS + 健康检查 + 地域级切流(见 36.4 两地三中心与多活) |
南北向的第一原则是收敛:把"互联网的复杂性"挡在少数几个入口,让内部只有一种协议、一种身份、一种超时口径。
会合处:入口网关 vs Mesh 网关
互联网 ──▶ 边缘网关(南北向)──▶ 服务 A ──(mTLS)──▶ 服务 B
│ ▲
└────── 也作为 mesh 的入口 ───────┘
| 形态 | 做法 | 优点 | 代价 |
|---|---|---|---|
| 独立入口网关 + 内部 mesh | 边缘网关终结 TLS、做认证,再以 mesh 身份进入 | 边界清晰,入口防护与内部治理解耦 | 两套配置、两次策略(容易不一致) |
| 入口网关即 mesh 网关 | 用同一套数据面(如 Gateway API + sidecar) | 策略统一、身份贯通 | 入口特性(WAF/DDoS)仍需外部组件 |
| 全部靠 mesh 暴露 | 不推荐 | 省事 | 把内部治理面直接暴露到互联网,攻击面变大 |
⚠️ 无论哪种形态,入口到内部的"身份转换"必须显式:外部是用户 token,内部是工作负载身份 + 用户上下文(透传但要重签/校验)。把外部 token 原样透传到最内层,等于让每个服务都暴露在公网令牌的攻击面上。
两种流量的量级对照
| 指标 | 南北向 | 东西向 |
|---|---|---|
| 峰值 QPS | 高(10 万级,突发 10×) | 更高但平稳(内部扇出,每入口请求 → 3–10 次内部调用) |
| 包大小 | 大(响应体、静态资源) | 小(gRPC/JSON,KB 级) |
| 连接数 | 与在线用户数同阶(长连接应用可达百万) | 与实例数 × 池大小同阶(万级) |
| 延迟预算 | 用户可感知(100–300ms) | 每跳 1–10ms,累计决定端到端 |
| 失败影响 | 全站不可用 | 局部放大成雪崩 |
这一节不给可加载的配置,因为它回答的是「配置该落在哪一层」:入口的配置在 47.1 反向代理 与 47.2 API 网关,东西向在网格/注册中心(30.5 Service Mesh 与 Sidecar)。硬塞一份 YAML 只会重复别节的主场。
反模式
| 反模式 | 后果 |
|---|---|
| 东西向不做连接复用 | 握手与 TLS 吃掉大量 CPU;TIME_WAIT 堆积 |
| 每层都配重试 | 27 倍放大,慢依赖被打死 |
| 东西向明文("内网可信") | 横向移动即可嗅探/篡改 |
| 跨 AZ 不做就近路由 | 延迟与流量成本双升 |
| 入口网关直接暴露 mesh 内部服务 | 攻击面从 1 个入口变成 N 个服务 |
| 把外部 token 原样透传到所有内部服务 | 公网令牌成为内部通行证 |
| 南北向只在单 AZ 部署 | 单 AZ 故障 = 全站入口不可用 |
| 用 DNS TTL 做秒级切流 | TTL 缓存导致切流不彻底(见 8.4 DNS 解析链路与缓存) |
自检
Q1 同样一次调用,南北向与东西向在"身份"上的本质差别是什么?
▸ 答案:南北向的身份是终端用户(人/客户端),需要认证用户、携带业务权限(scope/租户);东西向的身份是工作负载(哪个服务、哪个版本的哪个实例),需要证明"我是被授权的调用方"。前者用 JWT/OAuth2,后者用 mTLS/SPIFFE。混用会出两类问题:内部服务拿用户 token 互相调用(无法表达服务权限),或把服务身份透传给用户(无法做用户级授权)。
Q2 100 个服务、每个 50 实例,为什么"全互联"不可行?实际连接数由什么决定?
▸ 答案:全互联是实例两两建连,5000×4999/2 ≈ 1250 万 对连接,端口、内存、健康检查、配置都撑不住。实际连接数由"客户端实例数 × 每个上游的连接池大小"决定:单实例若访问 3 个上游、每上游 10 条连接,就是 30 条;全集群约 15 万条——收敛近 80 倍。这也是 sidecar/客户端 LB 的核心价值。
Q3 三层各配"重试 3 次",最坏放大多少倍?正确做法是什么?
▸ 答案:3×3×3 = 27 倍。正确做法:① 只在一层重试(通常是入口或最了解幂等性的调用方);② 其余层只设超时与快速失败;③ 重试要有全局预算(如"重试流量不超过总请求的 10%");④ 只对幂等操作重试(见 25.4 幂等设计与去重)。
Q4 "零信任要求全链路加密"是否意味着每个请求都要重新做 TLS 握手?
▸ 答案:不是。mTLS 是连接级的:连接建立时握手一次,之后该连接上的所有请求都继承这个身份;连接复用(HTTP/2 多路复用、gRPC 长连接、连接池)把握手成本摊薄到接近零。真正需要关注的是"新建连接速率"(决定 CPU)与"证书轮换时的重连风暴",而不是 QPS。
Q5 为什么"入口网关直接暴露 mesh 内部服务"是反模式?
▸ 答案:mesh 的内部服务通常只做了服务级授权(信任集群内的工作负载身份),把它们的端口直接暴露到互联网,等于让每个服务独自面对 DDoS、扫描、漏洞利用,攻击面从 1 个入口变成 N 个服务;而且这些服务往往没有 WAF、速率限制、TLS 证书管理等入口能力。正确做法是保持一个收敛的边缘入口,由它完成认证与防护后,再以工作负载身份进入 mesh。