读者视角导读
为什么我们把网关塞进了进程里
WP01 导读:大多数平台买一台 API 网关或搭一个 Service Mesh,HotelByte 把网关逻辑编译进了每个服务进程。这个选择的代价是真实的。
为什么我们把网关塞进了进程里
大多数酒店分销平台在入口层的选择很简单:买一台 API 网关,或者搭一个 Service Mesh。HotelByte 没这么做。它把认证、授权、缓存、流式响应、字段裁剪和请求证据等网关逻辑,编译进了每个服务进程。
这不是性能炫技。在一个单次搜索可能触发几十次内部调用的系统里,每一跳网络延迟都会累积到 P99 尾延迟上。而酒店搜索的 P99 直接决定转化率。把网关压缩进进程边界,消除一跳网络,是能量化衡量的收益。
但代价是真实的。你失去了多语言微服务的自由——每个服务必须说同样的网关语言。策略更新需要重新编译部署,进程内的 CPU 和内存竞争需要更严格的容量规划。而替代外部网关的十层洋葱中间件链,也不是换个供应商就能升级的东西。
行业通常怎么做
默认方案大家都熟悉:边缘终止 TLS,网关做限流和路由,服务之间通过 Mesh 或直接 HTTP 通信。这在内部调用图简单时没问题。但到了 HotelByte 的规模——27+ 供应商集成、多租户凭证隔离、每请求字段过滤——网关本身成了瓶颈和单点故障。更糟的是,每个请求要过网关两次:入站一次,每次需要认证或缓存的内部调用再过一次。
进程内网关的取舍
HotelByte 的做法是反过来的:网关不是独立进程,而是链接进每个服务的库。十层中间件链——Short Token 认证、RBAC、请求标准化、缓存、流式、字段裁剪、证据日志等——和业务逻辑跑在同一个 OS 进程里。内部调用因此完全消除了网络跳数。
白皮书详细记录了三个让这个方案成立的具体机制:
- Short Token 模式:一种轻量级凭证格式,无需远程 token 自省即可在进程内完成验证。撤销可以在毫秒级完成,因为 token 自带足够上下文支持本地拒绝。
- 纯查询参数路由:用查询参数替代 REST 路径参数。这看起来只是 API 风格选择,但它让缓存键在不同服务实例之间保持确定性——当同一个请求可能被不同进程实例处理时,这一点至关重要。
- 进程内调度器:内部服务调用走和外部请求相同的中间件链,确保安全和可观测策略统一生效。不存在”内部绕过”悄悄跳过认证或日志的情况。
放弃了什么
白皮书没有假装这个选择没有代价。最大的约束是语言统一:网关库用 Go 写成,所有使用它的服务必须是 Go 二进制。团队不能随意塞一个 Python 或 Node.js 微服务进来,还指望它参与同样的安全模型。策略变更——新中间件、认证规则更新、字段裁剪逻辑调整——需要所有服务全量重建和重新部署。
调试成本也在上升。网关是独立进程时,你可以 tcpdump 抓边界。现在边界是进程内的一个函数调用。白皮书用结构化证据日志来应对:每一层中间件都输出结构化记录,支持事后回放和审查。
什么时候这个选择合理
进程内网关不是万能架构。它在三个条件同时满足时才划算:
- 内部调用密度高:网络跳数的成本显著高于进程内计算成本。
- 运行时同质:组织能统一语言和构建体系。
- 策略变更频率可接受:团队能容忍安全与路由更新的重新部署周期。
如果你的内部调用图很浅,或者服务是多语言的,外部网关或 Mesh 很可能是更好的选择。HotelByte 这份白皮书的价值,恰恰在于它记录了”反常选择”在什么边界条件下变得理性。
阅读原文时重点看什么
- 分层架构:十层中间件链各自负责什么、边界在哪。
- Short Token 模式:无远程调用的凭证验证机制,以及撤销是如何处理的。
- 查询参数路由:为什么缓存键确定性在这个场景下比 REST 美学更重要。
- 证据与可审计性:每层输出什么结构化日志,如何支持事后复盘。
评论