API Gateway 请求链:路由、过滤与转发怎样守住入口边界
沿请求匹配、过滤器排序、身份上下文、改写、负载选择、代理连接和响应回程拆解 Gateway 的数据面。
Spring Cloud Gateway 官方文档把 route predicate、GatewayFilter 与实际 routing filter 组成请求链,并明确 pre 逻辑顺序执行、post 逻辑反向返回。参见 Spring Cloud Gateway。
路由匹配先决定这次请求属于哪条策略链
Route 由 id、目标 URI、predicates、filters 和 metadata 组成。Path、Host、Method、Header 等 predicate 共同决定是否匹配;多条规则重叠时,顺序和条件必须可预测。自动根据 DiscoveryClient 暴露所有服务虽然方便,却可能把内部管理端点意外发布到公网。生产入口应使用显式路由目录和默认拒绝。
Path 重写、StripPrefix、SetPath 和 Host 修改会改变下游看到的资源标识。鉴权签名如果在改写前计算、下游却按改写后路径验证,就会出现一致性漏洞。原始 URI、规范化 URI、routeId 和目标 serviceId 要分别记录,防止日志只剩最终地址而无法解释路由选择。
Filter 顺序同时控制请求和响应
全局与路由 filter 合并后按 order 进入 pre 阶段,代理返回时以相反嵌套顺序执行 post 阶段。一个 filter 若在调用 chain 前写请求头、在调用后写响应头,就必须理解其外层/内层位置。认证失败、限流或缓存命中会短路链,未执行的下游 filter 不能被计入成功指标。
读取或修改请求体需要缓存与重新发布 DataBuffer,大文件和流式上传不能无界聚合到堆。WebSocket、SSE 和下载流拥有长连接生命周期,普通请求级超时、重试和响应改写不一定适用。网关应限制 header、URI、body 和连接时长,但把媒体转码、报表生成等重业务留在后端。
身份传递不能退化成信任任意 Header
网关可以校验外部凭证并生成内部身份上下文,但必须先删除客户端伪造的同名头,再由受信通道签名或 mTLS 传递。目标服务仍需验证该上下文来源,并执行资源级业务授权;只在网关检查“已登录”无法阻止服务间越权。
限流维度、跨域、安全响应头和审计适合入口统一,但 key 不能直接使用可伪造的 IP 或高基数原始 token。故障时的降级响应要有明确业务语义和缓存年龄。网关不是把所有治理逻辑塞进一个进程的理由,否则入口发布和故障会成为全系统瓶颈。
把同步调用画成预算递减的状态机
设计时为每条边记录 owner、协议、连接模型、超时阶段、重试责任、幂等键、流量上限、降级语义和回滚方式。同步扇出越大,成功率乘积越低,尾延迟取最大值;能异步解耦的非关键副作用不要停留在主请求链。
失败控制必须按依赖隔离
注册中心不可用、无实例、连接池满、连接失败、读取超时、业务拒绝和服务端错误要分型。只有动作未开始或有幂等保障的暂态失败允许重试;结果未知先查询或使用稳定幂等键。限流、隔离和熔断的拒绝应成为可观测结果,不能统一包装成空数据。
代理连接池决定入口是否真的非阻塞
Reactive Gateway 不等于任何下游调用都不会阻塞。自定义 filter 中执行 JDBC、同步 SDK、磁盘访问或阻塞式 token introspection,会占住 event loop 并让所有 route 尾延迟同时上升。阻塞工作必须迁移到有界调度器并设置并发与队列上限,更好的做法是把高频鉴权材料本地验证或缓存。
下游连接池按目标实例管理活动与空闲连接。实例摘除后旧连接可能仍可用或已失效,长连接需要排空策略;连接数上限要与实例数、HTTP/2 stream 上限和下游并发共同计算。网关只扩 Pod 而不限制每 Pod 连接,会把扩容转成下游连接风暴。
用两个 Java 状态模型固定决策边界
这两个 Java 17 模型不启动真实注册中心、Gateway 或 RPC Server,而是把本篇的状态、预算和不变量转成确定输出。真实集成测试继续验证客户端协议、自动配置、连接复用、推送延迟与故障时序。
javac --release 17 -Xlint:all -Werror examples/backend-development/microservice/gateway-routing/RouteMatchDemo.java examples/backend-development/microservice/gateway-routing/FilterOrderDemo.java
java -cp examples/backend-development/microservice/gateway-routing RouteMatchDemo
java -cp examples/backend-development/microservice/gateway-routing FilterOrderDemopath=/api/orders/42 route=orders predicatesMatched=true rewritten=/orders/42
pre=[trace,auth,rewrite] post=[rewrite,auth,trace] shortCircuited=false状态模型输出变化时,要解释对应的服务边界、Deadline、版本或治理不变量为什么改变。集成测试必须主动制造连接已写出后超时、实例列表陈旧、配置刷新一半、半开探测和灰度标签断链。
契约、安全与配置共同决定可运营性
动态配置和发现元数据都可能陈旧。变更必须带版本、owner、范围、过期时间和回滚值,先灰度到少量实例并比较版本分布。会影响线程池、连接池、路由、限流和鉴权的配置要通过不变量校验,失败时保留上一完整快照。
容量与可观测证据要覆盖控制面和数据面
上线证据包括新旧契约互调、实例排空、Deadline 传播、幂等重试、治理状态机、灰度指标和回滚后的残留任务。完成标准不是“组件控制台显示健康”,而是业务不变量保持、未知结果可查询、故障被限制在预算内并最终收敛。
从开发环境到生产流量要跨过四层验证
依赖拓扑必须有复杂度上限
变更和回滚要覆盖控制面残留
回滚不能只替换镜像。注册元数据可能仍指向 v2,配置推送可能已经删除旧键,Gateway route 仍命中新路径,连接池仍保持到异常实例的长连接,消息与任务仍携带新版本标签。回滚清单要逐项验证代码、配置、路由、实例、连接、异步积压和数据版本,并以业务结果恢复为完成条件。
架构评审要把“自动”翻译成具体责任
每项机制都要指定单一 owner 和紧急关闭开关。Gateway、Feign、HTTP client 与业务代码不能同时拥有同一重试策略;注册中心健康、应用 readiness 和 LoadBalancer 被动健康不能互相覆盖却无人解释;平台默认配置不能在所有依赖上统一复制。治理目录保存默认值、例外理由、变更审计和自动过期,防止事故时临时放开的旁路永久存在。
