摘要:微服务一多,把客户端直接连到几十个服务是一场噩梦——要各配各的地址、各管各的权限。API 网关站在所有外部请求的最前面,把路由、认证、限流、聚合这些"横切杂活"统一收口。本文讲清它干嘛、怎么挡,以及网关是单点时怎么防它自己变成最大故障源。
你拆出了几十个服务,第一个涌上来的实际麻烦是:客户端凭什么叫它们? 如果手机上每个请求都要去拼十几个不同地址、处理十几份鉴权、容忍十几套失败样式,那你的客户端工程师会崩溃,接口也对全对外裸奔了。API 网关就是来解决这个问题的——它是所有外部流量进系统的第一道闸。
网关本质上是在入口处拦截,把那些"每个服务都要做一遍、做在一起又重复"的横切逻辑集中起来。用得最多的是四样:
/orders/* 去订单服务,/users/* 去用户服务。
带来的好处很直观:
拿走的东西更值得一提——网关是新的单点。如果网关挂掉,所有外部流量全堵死。所以网关的可用性要求和它收的功能成正比:它越能干,越必须高可用(多实例、健康检查、自动摘除、必要时降级返回缓存)。这是"收口"的天然代价:把分散的复杂性集中到一处,就必须对这一处的稳定负责。
把网关当成"聚合器"堆一切业务逻辑,是个很常见的跑偏。正确的分工是:网关只做横切和转发,业务逻辑继续留在服务里。如果网关里塞了太多"这个接口怎么拼装计算的规则",它很快就会变成一个脆弱的、谁都改不动又不得不改的神话级单体——那和你拆之前的老单体没什么两样。网关上能瘦则瘦,路由 + 安全 + 限流就够它忙的了。
顺着"响应聚合"这条,演化出一个务实的分支叫 BFF——每个端(iOS/安卓/Web)各自有一个偏后端的中间层,专门负责为这种端的界面打包成最合适的数据。它不改变网关收口的原则,只是把"聚合"从人人共用的一层,拆成按端隔离的多个门。BFF 的取舍是:换来了"每端接口最舒服",代价是多了几套要维护的层。中小团队先从"一个网关收口"起步,别一上来就铺 BFF。
网关一讲,很多人误以为"有个网关就万事大吉"。其实网关在系统里可以出现在不止一层,而且职责完全不同,先分清谁是谁,才不会在选型时张冠李戴:
一句话分界:入口网关管的是"外面进不进来",服务网格管的是"进来了之后服务间怎么走"。中小团队通常不会两个都上——先有入口网关把外部收口,再谈要不要为内部通讯绝社。别一上来就被"网关 + 网格"的组合拳整晕。
高可用不是指"网关绝不能挂"。事实上再高可用的网关也挡不住运气:上游网络事故、云厂商抖动、后端集体超时,都可能让网关在极端时刻透不过气。所以真正成熟的做法是给网关预置**"肚子满了怎么吐"的策略**——当请求量超过设定阈值,是返回 503、是丢掉最不重要的接口、还是先放行核心下单而拒绝次要的报表刷量。这是把网关当"闸门"而不是"玻璃墙"来看:闸门能调节,玻璃墙裂了就全塌。把"拒绝谁、保留谁"这个策略在平时就写清楚,比出事时手忙脚乱救灾靠谱得多。
网关顺手能做"响应聚合",但"该把多少个服务的响应拼成一个"是有讲究的,拼得太狠反而拖累。经验法则是:网关只拼"一小撮、低延迟、结果稳定"的服务,比如把"查用户昵称 + 查商品名"这种两三个轻查询并成一个接口,给客户端省一次往返。如果要拼的服务多、又慢又可能各自出问题,就别硬塞进网关——那种去调用第 4 章讲的只读副本/读服务,或 BFF 更合适。为什么?因为"拼得越多,网关的脆弱性和复杂度越高",把太重、太慢的聚合放进门禁,等于把明星服务又请回那个"神话级单体"的坑。判断标准:这个聚合值得在网关做,前提是它快、稳、小。 一旦它开始变慢、变脆,就该把它挪出网关,而不是给网关加更多并行调用。
网关收口后,它是所有流量的必经之路,也是最容易成为"大误解"的地方。别只顾着给后端配监控,网关自己要有:成功率、请求量、各后端分位的延迟分布、哪个路由在大量报错。否则两边噪音一大,你根本不知道是网关限流限错了,还是后端真的慢了。这个"入口先观测"的习惯,到第 5 章讲可观测性时会再放大。