1. 先理清这条链路的角色:每一环到底在干什么
标题里这条链路“xxop网关 → APISIX集群(ApisixRoute) → 业务gateway模块”看起来很绕,很多刚接触的人第一反应是:一个请求有必要过三层网关吗?这不是自己给自己加延迟吗?等你看完整篇文章就会明白,这三层网关做的事情完全不一样,每一层都在干不同的活。
先说xxop网关。我把它理解为公司内部的统一流量入口网关,也就是整个对外API体系的第一道大门。它承接域名解析、SSL证书卸载、基础的身份认证、风控拦截、黑白名单、流量染色这些偏“接入层”的职责。为什么需要这么一层?因为如果你的后端服务直接暴露在外网,任何一次恶意扫描、异常流量都会直接打到业务服务上,成本和风险都不可控。xxop作为一个接入型网关,把“谁能进”这个问题在入口处解决掉。
接着是APISIX集群。APISIX是开源的高性能云原生API网关,它是基于Nginx和OpenResty做的,但跟传统Nginx配置最大的区别在于——APISIX支持动态配置,而且它能以声明式的方式运行在Kubernetes环境里。这里提到的ApisixRoute,就是APISIX在Kubernetes环境下的一种自定义资源(CRD,Custom Resource Definition)。简单理解就是,你不必去改APISIX服务器的配置文件,而是通过Kubernetes的API资源对象来描述路由规则,比如:当请求的域名是xxx.com、路径是以/order/开头,就转发到某个Kubernetes Service。这种声明式管理方式,让路由配置可以走代码评审、版本控制、自动发布,而不是登录服务器去手工改Nginx配置。
再往下是业务gateway模块。这里的“gateway”不是指基础设施网关,而是业务侧自己实现的一个网关模块,比如基于Spring Cloud Gateway、Netty或自研框架写出来的服务。它离业务最近,负责的是参数校验、协议转换、业务鉴权、聚合调用、数据裁剪这类跟业务强相关的事。它跟xxop、APISIX的最大区别是:前两层可以外包给基础设施团队统一运维,这一层是业务团队自己的领地,要经常迭代、频繁发版。
理解到这里,你已经能回答“这个链路为什么这么长”了:因为每一层都在解决不同维度的问题。接入层解决安全和入口的问题,路由层解决动态调度和流量的精细治理,业务gateway模块解决业务通用逻辑的收口。它们不是重复建设,是分层治理。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 一次请求的完整旅行:传统网关链路 vs Serverless的路径差异
理解了每一环的定义之后,我们用一个具体请求来演示两条链路,才能真正体会“区别”在哪里。假设有一个移动端请求要查询订单详情,请求体里带着用户的token和订单ID。
2.1 传统链路:三次跳转,每一跳都做了什么
客户端发起HTTPS请求,到达xxop网关。xxop先做TLS终止,把加密报文解出来,然后校验token是否存在且有效,再检查这个用户的IP或设备指纹是否命中风控策略。如果都通过了,它会往请求头里写入一些透传信息(比如userId、设备ID、来源渠道),然后把请求转发给APISIX集群。
请求到了APISIX之后,APISIX根据请求的域名和路径,在内存中查找到匹配的ApisixRoute路由规则,应用路由上挂载的插件链,比如限流限速、CORS跨域处理、日志采集。之后它会通过服务发现能力把请求转发到对应的Kubernetes Service上,也就是业务gateway模块的Pod。
业务gateway模块收到请求后,先做反序列化,然后做参数校验,校验失败直接返回参数异常,校验通过之后再去调用订单中心、商品中心等下游服务。如果一个查询要聚合订单信息、商品信息、物流信息,业务gateway模块里可能还要做并行调用和结果拼装。全部拿回来后,它把拼好的数据结构按协议要求裁剪字段,以统一格式返回给上游。直到这一步,用户请求才算真正完成。
这条链路的总耗时,在正常网络环境下降落下来大概是几十毫秒到一百多毫秒的级别。这里头的每一步都有明确的价值:xxop挡住了无效流量,APISIX做了路由和限流,业务gateway模块做了参数和聚合。但也要承认,链路越长,单点越多,故障排查越复杂。
2.2 Serverless链路:API GW直通函数,中途少了什么
再看Serverless架构。整个请求链路变成:客户端 → API网关(通常用云厂商自带的或者APISIX等自建网关) → 函数计算(Function as a Service)。
API网关这一层跟APISIX的角色很像,负责路由匹配、鉴权、限流、参数映射。但跟传统链路的一个关键差异是,网关匹配到路由之后,直接触发的不是长驻网关服务,而是一个函数。比如云厂商的函数计算平台,会根据调用请求把某个函数的代码实例启动起来,执行完就返回结果。
在这个架构里,中间那层“业务gateway模块”消失了。原来写在gateway模块里的参数校验、聚合逻辑怎么办?答案是内聚到函数里,或者拆分成多个函数,由API网关或事件服务完成编排。比如订单查询这个场景,可以写一个getOrder函数,函数内部直接调用订单服务;也可以拆成getOrder、getProduct、getLogistics三个函数,用工作流或函数编排服务串起来。
从路径上看,Serverless的请求链路更短:client → API Gateway → Function。少了一层业务网关,带来的直接好处是部署和扩缩容的单元变小了。函数按调用次数和资源使用计费,没有调用就没有成本;流量突发时,函数平台毫秒级拉起新实例,不需要预先准备机器。
2.3 两条路径的成本与延迟真相
这里要澄清一个很多人想当然的结论:Serverless必然比传统链路慢。这个认知在“函数被频繁调用、实例常热”的情况下是错的。如果函数实例处于热状态,API网关直通函数的处理路径,实际上比“网关→网关→网关”短得多,延迟反而更低。
真正的延迟风险出现在冷启动阶段。函数平台接到一个请求,发现当前没有可用实例,就需要拉取代码、创建容器、初始化运行时,这个过程一般在几百毫秒到几秒不等。传统链路虽然跳数多,但每个节点都是常驻服务,没有冷启动问题,所以延迟曲线更平稳。
从成本角度算笔账:传统链路下,不管有没有流量,业务gateway模块的Pod都占着CPU和内存资源,账单是按“容量”算的;Serverless是按“用量”算的,高峰期和低峰期的成本差异非常大。如果你的业务有明显的波峰波谷,Serverless在经济性上优势很明显;如果是全天候高并发的稳定流量,长期跑在常驻服务上可能更可控。
3. 路由配置范式对比:ApisixRoute与Serverless API GW的设置方式
虽然两种架构都叫“网关”,但配置路由的方式,思维模型是很不一样的。这一节把ApisixRoute和Serverless API Gateway的配置方式放在一起对比,你会发现两者的“治理粒度”和“配置心智”有着本质差异。
3.1 ApisixRoute CRD:基础设施即代码
ApisixRoute是APISIX在Kubernetes环境下的核心配置入口。它的工作方式是这样的:你在Kubernetes集群里创建一个ApisixRoute对象,APISIX的Ingress Controller监听到这个对象的变化,自动把路由配置同步到APISIX集群的节点内存中,即刻生效。
一个典型的ApisixRoute配置长这样:
yaml复制apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: order-api-route
namespace: business
spec:
http:
- name: order-query
match:
hosts:
- api.example.com
paths:
- /order/*
upstreams:
- name: order-gateway-svc
serviceName: order-gateway-svc
servicePort: 8080
plugins:
- name: limit-count
enable: true
config:
count: 10000
time_window: 60
rejected_code: 429
这里有几个信息值得注意。第一,路由匹配规则是“域名+路径”的组合,这在微服务架构中是最常用的方式。第二,upstream直接指向Kubernetes Service,意味着您不用在代码里硬编码后端地址,服务发现交给Kubernetes解决。第三,插件是挂在路由上的,一个路由可以独立配置限流、CORS、鉴权等能力。
用这种方式做配置,最大的好处是可以把基础设施变更纳入到GitOps流程里。你改一个路由,就是提交一个Pull Request,代码评审过了,merge到主干,CICD自动apply到集群。出了配置问题,也能通过版本回滚快速恢复。这是传统SSH登录Nginx改conf文件的方式完全没法比的。
3.2 Serverless API GW:配置跟着函数走
Serverless平台提供的API网关,配置逻辑一般是这样的:你先创建函数,然后创建一个触发器(Trigger)或者API分组,配置请求路径跟函数的映射关系。在控制台操作时,你需要填的通常是:请求路径(比如 /order/query)、请求方法(GET/POST)、要触发的函数名和版本(比如 $LATEST 或别名)。
有些平台还支持在网关层面做参数映射和Mock调试。比如前端传的参数名跟函数入参不一致,可以在API GW层做个映射;函数返回的数据结构要包裹一层,也可以在网关层做响应处理。
但这个配置有个特点:路由和函数是“绑定”关系,它不像ApisixRoute那样把“路由规则”当作一个独立可治理的对象。换句话说,Serverless API GW更倾向于处理“这个路径属于哪个函数”的单一映射,而APISIX这条链路天然支持更复杂的规则组合,比如按权重灰度、按Header分流、按用户维度路由。
3.3 共同本质与配置心智差异
底层逻辑其实是一致的:都是把“请求匹配条件”和“后端目标”建立对应关系,中间可挂载一些通用策略。但在心智模型上差异很明显:
- ApisixRoute是一种“基础设施层”的路由,它是独立于业务代码的,配置在YAML里,随着基础设施版本走。
- Serverless API GW是一种“平台绑定型”的路由,它跟函数生命周期绑定,通常要在云厂商控制台或者函数配置文件里管理。
如果你是从传统链路往Serverless迁移,最大的门槛不是写代码,而是适应这种“路由不归我做主、基础设施不归我管”的感觉。原来你可以随便往APISIX上挂插件、改路由、做灰度,到了Serverless平台里,很多能力变成“平台提供什么你就只能用什么”。这是很多业务团队在迁移时非常难受的地方。
4. 状态设计与治理能力:传统网关的看家本领,Serverless的取舍
网关层的职责不只是转发请求,更关键的是承载各种治理策略。这一节要深入讨论两类架构在状态设计和治理能力上的核心差异,这是一份经验之谈,也是很多架构评审会上真正会被反复追问的地方。
4.1 长驻进程的“隐形红利”:连接池、缓存、内存态
传统网关链路里的业务gateway模块,通常是一个长驻运行的进程。长驻意味着它可以在内存中维护很多东西,而且这些能力使用起来非常自然。
首先是连接池。业务gateway模块要调用下游服务,如果每次请求都新建TCP连接,延迟和资源消耗都会很可观。长驻进程可以维护一个到下游服务的连接池,连接复用率可以做到很高。APISIX基于OpenResty,Nginx的事件模型和Upstream连接池本身就能承载高并发的连接复用。
其次是内存缓存。在网关层做一个短周期的缓存,比如把用户权限信息、灰度标签、业务白名单缓存在本地内存中,可以大幅减少对下游的调用压力。网关层做缓存跟业务服务做缓存有个区别:网关的调用链更长,缓存带来的延迟收益更明显。举个例子,用户权限校验如果在xxop网关或业务gateway模块有一层本地缓存,就不必每次都打到权限中心。
再次是内存态的灰度规则。在传统链路里,你可以设计这样的逻辑:网关模块启动时从配置中心拉取一份灰度规则(比如10%的流量走新版服务),规则缓存在内存里,每次请求进来后根据用户ID的哈希值判断走新还是走旧。这种能力在长驻进程上实现成本很低,因为状态天然保存在内存中。
4.2 Serverless的“无状态”并不等于无能力
函数计算对运行时的假设是“无状态”,即每个函数实例可以在任意时刻被销毁、拉起。这就意味着,连接池、内存缓存、内存态灰度规则这些能力,在Serverless架构里不能直接照搬。
但这不是说Serverless就没法做治理。它的治理思路是“外置”:连接池的管理下沉到云基础设施或Serverless框架层;缓存放到Redis或分布式缓存;灰度规则放到配置中心或环境变量。函数本身不保存任何状态,所有需要持久和共享的东西都外置化。
这个转变对架构设计有很深远的影响。比如在传统gateway模块里写个内存缓存只花十分钟,在Serverless里你就要考虑:是用Redis存?缓存key怎么设计?过期策略怎么设置?如果函数实例多地多可用区部署,缓存一致性怎么保证?每一项都从“本地操作”变成了“分布式系统设计”。
我见过不少团队在迁移Serverless时,最大的性能事故恰恰出在这里:因为他们习惯了在长驻进程里用内存缓存,到了函数里也试图这么干,结果发现缓存命中率极低,因为函数实例频繁冷启动、频繁释放,缓存根本热不起来。最后只能老老实实接Redis,才把性能拉回来。
4.3 限流、鉴权、熔断在两个体系里的落点差异
- 限流:传统链路的限流可以在三层任意一层做,xxop做全局配额限流、APISIX做路由级别限流、业务gateway模块做用户维度限流,它们可以叠加成多层防护。Serverless架构里,API网关层可以做基础QPS限流,函数代码里可以做精细化的用户维度限流,但函数实例级别的并发控制通常交给平台,你可以在函数配置里设置“单实例并发度”。
- 鉴权:传统链路可以把鉴权拆成多级实现,入口层做粗粒度校验,业务层做细粒度授权。Serverless里,API GW可以挂一个统一的鉴权函数(或JWT验证插件),函数内部再做业务权限判断。需要注意的是,Serverless函数被直接调用时,你要防止绕过API网关的流量,所以签名校验和来源校验要做扎实。
- 熔断:传统链路在APISIX或业务gateway模块可以方便地实现熔断逻辑,比如连续失败达到阈值,后续请求快速失败。Serverless里,函数间的调用通常是同步阻塞调用,如果下游不可用,函数实例会被大量占用,所以更依赖平台层面的限流和函数超时配置来兜底。建议在代码里给所有外部调用设置超时和最大重试次数,同时配合消息队列做异步化。
5. 实务中两者的“联系”:不是替代关系,而是可以叠层
讲了这么多区别,最后回到标题里的“联系”两个字。我在实际项目中观察到一个很普遍的现象:团队在讨论架构方案时,容易陷入“传统网关 vs Serverless”的二选一思维。但真实世界里,两者往往是共存的,而且是可以配合得很好的。
5.1 用APISIX做Serverless的入口
你可以把xxop和APISIX保留在链路最前端,后端目标从“业务gateway模块”切换到“Serverless函数”。在这种架构下,原来的调用链变成:
客户端 → xxop网关 → APISIX集群(ApisixRoute) → Serverless函数(或函数所在的Service)
这个方案的好处很明显。第一,所有流量仍然经过统一入口,安全和治理能力不丢失。第二,APISIX的路由规则可以动态调整,灰度发布和蓝绿发布变得很灵活。比如你可以在ApisixRoute里配置两个upstream,一个指向传统的gateway服务,一个指向Serverless函数的HTTP触发器,然后按权重把流量慢慢从旧架构切到新架构。第三,如果某个函数存在问题,你可以在APISIX层快速摘除路由,或者降级回传统网关链路,而不是直接面对云平台后端的冷冰冰的报错。
这个混布方案我强烈建议做架构迁移的团队优先考虑。你在APISIX层做一个“分流开关”,比在客户端或DNS层做切流靠谱得多。
5.2 什么样的业务适合留在传统链路,什么适合Serverless
结合自己的经验,我给出一个比较朴素的判断思路,供读者参考:
- 适合留在传统链路的:核心交易链路(支付、下单、锁库存)、对延迟极度敏感的服务(毫秒级超时要求)、有强状态依赖的业务(比如依赖本地会话、分布式锁、长连接)。这些业务放在常驻服务里,状态管理和问题排查都更可控。
- 适合Serverless的:突发性强的业务(如秒杀、活动页瞬时流量)、低频但不是零频的边缘业务(比如管理后台的某些查询接口)、事件驱动型任务(消息处理、文件转换、定时任务)、按量付费场景下成本模型更清晰的新业务。
- 适合中间态(APISIX + Serverless混布)的:老业务要逐步改造、暂时无法全量迁移的;团队对函数平台的运维能力还不足、需要保留一层网关做兜底的。
一个实际案例:我之前参与过一个电商后台的改造,团队把“订单列表导出”这个低频但耗时的接口迁到了Serverless函数。这个接口平时没几个人用,但是大促结束后会有大量运营同时点导出,传统常驻服务的资源利用率非常低。迁到函数后,导出的执行逻辑跑到函数里,文件生成后放到对象存储,再把下载链接返回前端。API路径保持不变,但底层实现已经跟原来的gateway模块解耦。这个改造在APISIX上只改了一个upstream指向,整个过程没有影响线上其他任何接口。
5.3 迁移和混布时的高频踩坑点
这里把这些年见过的、亲身踩过的坑集中列一下,每个都是从实际生产环境中总结出来的:
- 超时配置不一致。传统网关的HTTP Client超时往往设置得比较保守(比如2秒、3秒),但Serverless函数(尤其是经历了冷启动)可能1秒内根本没有响应。迁移后你会发现大量请求在业务gateway或APISIX层就超时了,但函数其实执行成功了。这个问题的正确姿势是:把函数从网关到下游的整条链路超时做一次梳理,设置合理的超时梯度,上游比下游多留出至少1秒的余量(比如函数下游超时2秒,网关超时4秒)。
- 502 Bad Gateway的误判。标题相关的热搜词里出现了“unexpected status 502 bad gateway”,这个错误在日常运维里很常见。APISIX报502,常见原因有三种:upstream服务没有启动、upstream服务端口探测失败、upstream返回了非法的HTTP响应。如果upstream换成了函数,就多了一个场景——函数平台返回了5xx错误,APISIX在上游响应状态异常时也会抛出502。排查时不要只盯着APISIX日志,还要去看函数的调用日志和平台的健康检查状态。
- 日志链路断裂。传统链路里,日志框架一般会在入口生成一个traceId,往下游传递。但函数计算的日志输出体系跟传统服务不同,如果你没有在函数里显式接收和透传traceId、spanId,排查问题时就会发现整条链路串不起来。建议在函数入口做一层公共的日志上下文处理,无论从API GW进来还是从消息队列触发,都在入口处生成或透传traceId。
- 函数冷启动对网关层的冲击。对于延迟敏感的业务,函数冷启动产生的影响是实际的,你可以在网关层做预热(比如定时调用一个内部接口,让函数实例保持热状态),也可以在平台上配置最小实例数。但最小实例数意味着预算费用增加,需要在成本和延迟间做权衡。
6. 选型决策:什么时候该坚持传统链路,什么时候该拥抱Serverless
结合前面的分析,我画一条比较清晰的决策线(此段作为一个经验清单,可直接用于内部技术评审):
- 是否已有成熟的网关基础设施?如果团队已经搭好了xxop + APISIX这套体系,并且运行稳定,完全没有必要因为“Serverless很火”而强行替换。把Serverless作为“新链路的一部分”接进来,比“替换整个链路”要稳妥得多。
- 业务是否具备无状态改造的条件?如果业务强依赖本地文件系统、本地缓存、长连接,那Serverless会是一个非常痛苦的改造过程。反过来,如果业务本质上是请求-响应型、纯计算型、事件触发型,Serverless天然契合。
- 团队的排障成本承受能力如何?Serverless平台的排查手段相对传统手段更受限,尤其是在跨VPC、跨账号、复杂网络环境下,日志和链路追踪要靠平台提供的工具。如果团队没有较强的云平台运维能力,传统链路至少让你多一块可控的空间。
- 预算和计费模型。传统网关链路的主要成本是“常驻资源”,按峰值采购也按峰值付费;Serverless的主要成本是“调用次数 + 资源使用时长”,低峰期省钱,高峰期可能要控制并发容量,否则费用会很惊人。
具体到项目里,我处理这类问题的方法是:把所有候选业务按“状态依赖程度”和“流量稳定性”两个维度画一个四象限图,低状态依赖、流量波动大的业务优先尝试Serverless;高状态依赖、流量稳定的业务保留在传统链路;状态依赖居中、流量有波峰波谷的业务,用APISIX做分流,采取灰度迁移的策略。
7. 结尾:经验总结和一些实在的建议
回过头看标题里那条链路“xxop网关 → APISIX集群(ApisixRoute) → 业务gateway模块”,再对比Serverless架构,最核心的表达可以用一句话说透:传统网关链路是一套“分层治理”的架构,每一层都有它的权限和职责,长驻进程带来的状态能力是它的根基;Serverless架构是一套“全托管 + 按量使用”的架构,牺牲了对中间层的控制和状态的本地化,换来的是更小的运维粒度和更弹性的资源模型。两者各自的适用场景完全不同,但它们的联系在于:APISIX这类网关工具,恰恰是连接这两套架构的关键桥梁。你可以基于APISIX构建一个“双模网关集群”,传统服务走传统upstream,Serverless函数走新的upstream,在网关层完成统一调度、统一治理、统一灰度。
从个人实践的角度,我给正在考虑这个问题的团队三个建议。
第一个建议:不要为了简化架构而强行砍掉中间层。网关链路里的每一层,都有它在可观测性、故障隔离、安全管控上的价值,盲目的“化简”往往会带走这些价值。Serverless减少了运维组件,但同时把很多能力收归平台,你要确保平台的能力确实覆盖了你的需求,再做决定。
第二个建议:无论选哪条路,都要先做好可观测性。一次性把日志、指标、链路追踪的标准定好。拿APISIX来说,它提供了丰富的日志插件,可以把请求日志输出到Kafka或ClickHouse;函数平台也有日志服务。关键是确保两套体系里的traceId能串联起来。这一步看起来基础,但迁移过程中80%的排查痛苦都源于链路追踪的缺失。
第三个建议是用“出入口不动,中间层可替换”的策略推进改造。也就是说,对外暴露的API域名和路径尽可能保持稳定,在xxop网关或APISIX层完成切流。这样即使底层已经从传统gateway模块换成了Serverless函数,对调用方来说是无感知的。出问题的时候,也能快速把流量切回旧链路。这种渐进式的改造风格,比“推倒重来”式的大迁移要可靠得多。
最后,关于运维,我再补一句教训:502之类的错误不一定都是网关配置的锅。链路越长,越要建立“自底向上”的排障习惯——先看最终返回的源头服务(尤其是换成了函数之后),再一层层往上看网关和路由配置。盲目重启网关或刷新路由,很可能只是暂时止血,真正的根因还在下游。看清楚这一点,你在网关链路上能少踩很多坑。
