拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI网关实战:Apache APISIX统一管理大模型API的架构方案

AI网关实战:Apache APISIX统一管理大模型API的架构方案

大模型火了这两年,身边越来越多团队把业务逻辑接到各类大模型上,但聊到最后基本都会撞上同一堵墙:模型接口到底该怎么统一管理?这堵墙光靠写代码是砌不完的。我自己的答案是,在所有模型调用前面加一层 API 网关,具体用的就是 Apache APISIX。这不是简单地把大模型当成普通后端服务,而是把限流、缓存、密钥管理、审计、灰度这些基础设施级能力一次补齐。这篇文章想和你聊聊 APISIX AI 网关能做什么、怎么做,以及我几次落地实操里踩过的坑、事后总结的经验。

1. 把大模型当成一种特殊 API 来治理

1.1 裸调模型接口的四个典型问题

先说一个我亲眼见过的典型事故。某个项目把模型 API Key 直接写在前端代码里,上线第一天被刷掉几千块钱。这其实不是个例,很多人觉得大模型接入就是一个 HTTP 请求的事,但当你真把它当成业务核心服务来看,会发现它比普通 REST API 难伺候得多。

第一个问题是成本不可控。模型调用跟普通接口最大区别是,每次请求都按 token 计费,而且同一个问题问 100 遍就收 100 遍的钱。常见业务里,用户反复提交相似请求、Agent 内部循环调用、上游服务重试,都会让成本成倍放大。更坑的是,请求体和响应里都计费,你没法只按 QPS 去估算花销。

第二个问题是供应商配额和限流。云端模型服务几乎都有限流,有的按每分钟请求数限,有的按每分钟 token 数限。一旦业务量上来,直接面对供应商接口写业务代码,就会遇到高峰期请求被拒、核心链路抖动的问题,而你又很难在业务代码里把“谁消耗了多少配额”说清楚。

第三个问题是安全和审计。密钥散落在各个微服务里,有的在配置文件、有的在环境变量、有的干脆写进代码仓库,轮换的时候满世界找。谁在什么时间调用了哪个模型、消耗了多少 token,基本没有完整记录。出了问题只能人肉翻日志。

第四个问题是模型切换困难。今天觉得 A 模型效果好,明天想换成 B 模型,或者想同时接多家模型做对比、做容灾,如果每个服务都是自己直接调 SDK,改造成本极高。这还没算上那些已经私有化部署在机房里的大模型,它们虽然是 OpenAI 兼容协议,但在网络结构、负载能力上和云端服务又不太一样。

1.2 网关要补的能力清单

把这些痛点摆在一起,你会发现真正缺的是一个统一的模型访问层。用 API 网关来补这个位置,在逻辑上非常顺:它本来就在所有流量的必经之路上,天然能做认证、限流、灰度、日志。针对大模型场景,网关需要额外补的能力大概有四块。

认证与配额隔离是第一步。不同业务线、不同团队各自持有自己的凭证,网关统一做身份识别,再按消费方维度分配模型调用配额。这跟普通接口网关里的 consumer 概念一回事,只是把“每分钟请求数”扩展成了“每分钟、每天、每月的 token 预算”。

成本治理是第二步。网关能看到完整的 token 消耗,可以做重复内容缓存,也可以做模型降级。比如把高频低价值的请求路由到便宜模型,把复杂推理请求路由到强模型,这个策略在网关层做非常顺手。

安全审计是第三步。所有模型请求的入参、出参、耗时、token 用量都记录在案,配合访问日志和 OpenTelemetry 这类指标系统,能看清每条链路的真实成本和质量。

多模型路由是第四步。网关拿到请求后,按规则决定发给哪家模型、哪个版本、本地还是云端,失败后自动重试或降级到备用模型。业务方只知道自己访问的是一个 OpenAI 兼容的入口,底层模型随便换。

1.3 本地部署模型也需要网关吗

很多人觉得“我们用的是本地私有化大模型,不走公网,不需要网关”。这个想法我一开始也有,后来发现不完全对。本地部署的模型虽然省了按 token 付费的问题,但 GPU 资源依然是稀缺的。

vLLM、Ollama 这类推理服务起来之后,企业内部会有多个团队共用同一批 GPU。没有网关时,每个团队的调用都在挤占显存和并发,出了问题谁也说不清是谁把卡打满了。接入 APISIX 之后,可以给不同团队做并发上限、请求优先级、排队策略,还能把多张 GPU 卡、多个推理实例的流量做负载均衡。

另外,本地模型和云端模型混用非常常见。内部系统跑本地模型省钱,对外的客户服务用云端强模型保效果。这两种模型放在一条链路里统一管理,出了问题互相容灾,网关是性价比最高的方案。

2. Apache APISIX 做 AI 网关的底气

2.1 插件化架构带来的扩展自由

就算明白了“需要网关”,很多人还是会问:为什么偏偏是 APISIX,而不是自己写个中间层,或者用 Spring Cloud Gateway、Kong 这些?

我的理由首先是插件化架构。APISIX 基于 OpenResty 和 Nginx,核心数据面性能本身就够硬,但真正让它适合 AI 场景的是插件机制。它的插件可以热加载,配置通过 etcd 下发,做到管理面和数据面分离。也就是说,你修改限流规则、加一个缓存策略、换一个上游模型,不需要重启网关进程,这在模型频繁切换的时期非常值钱。

我自己用过一段时间自研的“模型代理服务”,刚开始只是转发请求、记个日志,后来要加限流、要加缓存、要对接告警,一版一版地往工程里堆代码。维护到后面,配置逻辑、业务逻辑、模型适配代码全混在一起,改一个参数都要重新发版。换到 APISIX 之后,绝大多数需求变成了一条 Admin API 请求,改的是配置,不是代码。

2.2 不只是代理,还有 AI 专用插件

如果只是把通用网关拿去代理模型请求,那其实任何网关都行。APISIX 让我比较舒服的地方是,官方在较新的版本里引入了一整套 AI 插件族,专门解决大模型场景下的细节问题,而不是逼着我去组合一堆通用插件硬凑。

以我实际用过的几类为例,代理类插件负责对接不同模型供应商,统一转换成 OpenAI 兼容协议;限流类插件不只是按 QPS 限,还能按 token 消耗去做预算控制;缓存类插件可以做语义缓存,意思差不多的问题直接命中缓存,不用真的再请求一次大模型;提示词模板类插件把 Prompt 放在网关节点的配置里,业务方只需要传参数变量。

这类插件解决的事,如果让你自己做,通常要写不少代码。比如语义缓存,你首先得把文本向量化,再算相似度,再管理缓存淘汰策略。网关把这些能力变成可声明的配置,省事太多。

我不建议你直接把别人博客里的插件参数抄过去,因为 APISIX 版本迭代很快,插件名和字段在不同版本里可能有调整。看官方文档里对应版本的 AI 网关章节,那才是准的。

2.3 多模型、多云、本地点的一体化路由

真正让我确定选择的是多模型路由能力。我们的环境里既有云端模型,又有公司内部机房部署的模型,还有专门微调过的行业模型。要是没有网关,业务代码里就得写一堆 if-else 去判断走哪条路。

有了 APISIX 在中间层做路由,上游变成了一个逻辑池子:同一类业务请求,默认走效果最好的强模型,但加了按比例分流、按条件灰度、按错误率自动切换这些规则。比如先让 5% 的流量走新微调模型,观察生成质量和耗时,再逐步放大比例,这个能力在普通网关里其实也能做,但 APISIX 把路由规则和 AI 插件放在同一个配置体系里,操作起来更顺手。

我也试过对比几种方案的取舍,核心差异大概是这样:

方案模型协议适配语义缓存细粒度 token 限流多模型灰度切换运维成本
自研代理服务需要自己写需要自己写需要自己写需要自己写高
通用 API 网关看插件生态多数不具备通常按 QPS可以做但配置复杂中
APISIX AI 网关内置插件内置插件支持原生支持低

3. 实操:从零配置一个能跑的 AI 网关

3.1 用 Docker 快速拉起 APISIX

实操部分必须有。先说最基础的部署,照着做一遍你就明白整个链路长什么样。APISIX 依赖 etcd 做配置存储,最简单的跑法是 docker compose 把 etcd 和 APISIX 一起启动。

services: etcd: image: bitnami/etcd:3.5 environment: - ETCD_UNSUPPORTED_ARCH=arm64 - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 - ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379 ports: - "2379:2379" apisix: image: apache/apisix:3.12.0 depends_on: - etcd ports: - "9080:9080" - "9180:9180" volumes: - ./config.yaml:/usr/local/apisix/conf/config.yaml:ro

这里 9080 是数据面端口,所有业务请求都走它;9180 是管理端口,Admin API 用它来配置路由和插件。config.yaml 里需要把 etcd 地址指到 etcd 容器,默认配置一般会监听本机 127.0.0.1,容器之间要换成服务名。

启动之后,先访问一下管理端口确认网关活了,再往里写配置。整个过程不会超过五分钟。有一件事我特别提醒:默认 admin key 一定在正式环境改掉,文档里给的那个默认值全网都知道。

3.2 接通第一个 OpenAI 兼容模型

APISIX 自身不强依赖某个模型品牌,它对接的是 OpenAI 兼容协议。现在绝大多数模型服务都提供这种兼容接口,云端模型有,本地部署的 vLLM、Ollama 也有,所以一套配置通吃。

先建一个 Upstream,指向真正的模型服务地址。比如企业内部某个模型服务的地址是http://model.internal:8000:

curl http://127.0.0.1:9180/apisix/admin/upstreams/1 \ -H "X-API-KEY: your-admin-key" \ -X PUT -d '{ "name": "openai-compatible-upstream", "type": "roundrobin", "nodes": { "model.internal:8000": 1 } }'

接着配置路由,在插件里启用 AI 代理能力。业务方访问你的网关时,路径依然是/v1/chat/completions,网关负责把请求转发到真实模型地址,同时把鉴权信息注入进去。

curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: your-admin-key" \ -X PUT -d '{ "uri": "/v1/chat/completions", "upstream_id": "1", "plugins": { "ai-proxy": { "provider": "openai", "auth": { "header": { "Authorization": "Bearer env:OPENAI_API_KEY" } }, "model": "gpt-4o-mini" } } }'

这里的关键点是密钥不要直接明文写进配置。我习惯把密钥放到环境变量里,配置引用环境变量名,这样配置入库也不怕泄露。路由建好之后,拿 curl 从 9080 端口发一个普通补全请求,能收到正常响应,就说明链路通了。

3.3 加限流、缓存和提示词模板

链路通了,接下来就是往上面叠治理能力。

先加 token 维度限流。普通限流按 QPS 算,但大模型场景更关心的其实是“这个团队这个月还能用多少 token”。在 APISIX 里加 AI 限流插件后,可以按模型维度、按消费者维度设置配额。比如规定某个内部应用每小时的 token 预算不能超过 100 万,超出之后返回提示信息而不是硬闯模型接口。

再加语义缓存。语义缓存跟普通缓存不一样,不是要求请求文本完全一样才命中,而是语义相近就命中。配置时通常会有一个相似度阈值,比如 0.9,意思是两个请求在向量空间里的相似度超过 90% 就直接复用上次的生成结果。这个对客服问答、政策查询这类重复度高的场景特别管用,明显降低成本和延迟。

还有提示词模板。把 Prompt 下沉到网关配置里,业务方不用在代码里拼接复杂指令,只需要传变量。这还能保证所有团队对外服务的提示词口径一致,模型版本升级时只改网关配置,不用业务方重新发版。

这些插件的配置风格跟前面路由一致,都是往 plugins 字段里追加一段 JSON。我建议第一次配置时把缓存 TTL 设短一点,比如 600 到 1800 秒,先观察命中率和内容质量,再逐步加长。缓存命中率高不是唯一目标,关键看返回内容是不是真的是用户想要的。

3.4 把本地 vLLM/Ollama 接进同一网关

本地部署的大模型接入方式,本质上跟接云端模型一模一样,因为 vLLM 和 Ollama 都原生提供 OpenAI 兼容接口。

以 vLLM 为例,本地起了服务之后默认监听 8000 端口,接口路径就是/v1/chat/completions。配置 APISIX 时,Upstream 指向127.0.0.1:8000,路由 URI 不变,AI 代理插件里的 provider 换成合适的本地类型,或者直接用兼容模式对接。Ollama 也类似,不过默认端口是 11434,而且它走 OpenAI 兼容接口的路径同样是/v1/chat/completions。

我实际操作中还会多做一步:把云端模型和本地模型放到同一个 Upstream 池子里,或者配成两条不同路由,用权重控制流量比例。比如新上的微调模型先在本地跑,对外表现为一个单独的模型名,方便跟线上模型做对比测试。等评估指标稳定了,再通过修改路由权重逐步切流量。整个过程业务方是无感的,他们一直访问的是同一个网关地址。

4. 实际落地中踩过的坑

4.1 SSE 流式响应被网关“吃了”

这是我在 AI 网关落地时遇到的最经典问题。大模型应用几乎都会用流式输出,前端打字机效果背后走的是 SSE。本来直连模型服务时一切正常,但流量一过网关,前端就开始转圈半天不出字。

问题根源通常是网关默认开启了响应缓冲。Nginx 为了性能,会把上游响应的内容攒到一定量再一次性发给客户端,但 SSE 是持续不断的小片段,缓冲区没满就一直压着。结果就是模型那边已经生成了一大段内容,客户端这边一个字都没显示,体验极其糟糕。

解决思路是让网关对流式接口关闭缓冲。具体字段在不同版本里略有差异,但思路是一样的:识别出stream: true的请求,在响应路径上关闭缓冲、关闭压缩,保持 chunked 传输。同时还要把读取超时时间调大,大模型生成长文本的时间很容易超过普通接口的 60 秒默认值,不然生成到一半网关就主动断连了。

4.2 语义缓存命中率低到怀疑人生

语义缓存刚上线时,我一度以为插件没生效,因为命中率只有个位数。后来排查发现,问题出在请求文本的“个性化元素”太多。

比如一个客服系统的问题模板是“我的订单 xxx 怎么样了”,每个用户都有不同的订单号。语义缓存要识别出这些请求的意图相似,不能因为它们表面字符串不同就认为不是同一个问题。另一类问题是请求里带了大量上下文、用户 ID、时间戳,这些变量把向量表示搅乱了,相似度自然算不高。

后来我调整了缓存设计:在入缓存之前先做归一化,把明显的变量、数字、ID 用占位符替换掉,再计算相似度。这样“我的订单 12345 怎么样了”和“我的订单 67890 出什么问题了”就能被识别为同一类问题,命中率一下就上来了。这个经验对做语义缓存的人都适用,缓存能不能打出效果,一半取决于前置的文本清洗。

4.3 限流配置太粗暴

第一次配 AI 限流时,我直接按全局维度限制了一个总配额,结果没到一天,某个内部工具的突发流量把整个模型的配额全吃完了,核心业务反而被限流挡住。这就是典型的治理粒度没设计好。

正确做法是把限流维度拆开:按消费方限流,每个业务线有自己的额度;按模型限流,便宜模型和贵模型分开控制;按优先级限流,核心链路配额预留充足,非核心任务甚至可以直接丢到排队队列。APISIX 的插件体系支持通过 consumer 身份做区分,这就是为什么我前面反复强调,网关层面的认证不是可有可无,它是后续所有配额管理的基础。

对了,限流参数也别拍脑袋。先观察一周线上真实 token 消耗曲线,再按 80% 水位设配额,留出一点弹性。限流太紧会误伤正常流量,太松又失去意义。

4.4 密钥和多团队权限怎么隔离

多团队共用同一个网关时,密钥管理容易乱成一锅粥。原本每个团队自己管自己的供应商密钥,但放进网关后,核心问题变成:怎么知道某个请求是哪个团队发的,以及怎么限制它只能用自己的密钥。

我的做法是启用消费方认证。每个团队注册一个 consumer,持有独立的 API Key,路由上绑定对应的限流策略和密钥映射。业务请求到达网关时先做身份识别,再按身份决定注入哪套鉴权信息、走哪个模型、受什么配额限制。这样出来的效果是:团队 A 即使拿到了团队 B 的 API Key,也调不动团队 B 的模型配额,因为身份对不上。

审计日志也一定要开。模型请求的入参、出参、真实耗时、token 用量、命中哪个上游模型,全部记录下来。出了问题这是唯一的回溯依据,改模型、调限额、做成本分摊,都靠它。

5. 几个长期值得坚持的经验

5.1 先有监控,再谈治理

我给刚上车的团队一个反常识的建议:别一上来就把限流、缓存、 Prompt 模板全都配置得满满当当。先做透明,再做控制。第一周只做一件事,把所有模型请求的指标接进监控系统,看清每个业务线的 token 消耗趋势、调用失败率、平均耗时、生成质量。

没有这些数据,你做的任何限流阈值都是拍脑袋,任何成本优化都是盲操作。等数据积累两三周之后你会发现,真正要治理的点和最初预想的经常不一样,有的业务看似调用量巨大但缓存命中率高得离谱,有的业务调用量小但全是昂贵的长上下文请求。

5.2 路由是从简单到复杂长出来的

不要第一次就设计一个复杂的多模型路由矩阵。先用一个默认模型,把所有流量都交给它,跑通链路。然后再根据业务场景拆路由:高价值场景走强模型,内部提效场景走便宜模型,测试流量走本地模型。

我在做过一轮模型评估之后,把原来“所有流量都打同一个模型”的模式,改成了按任务类型路由。复杂推理、代码生成、长文档总结走贵模型,简单分类、抽取、改写走便宜模型。成本直接降了大概四成,业务效果几乎没有变化。这个优化在网关层做,只需要加几条路由规则,试错成本很低。

5.3 把模型回归评估纳入日常

接入 AI 网关以后,模型供应商随时可能更新版本,你自己也可能微调出新的模型。每次模型变更,都不要直接全量切过去,而是先走灰度路由,让一部分流量用新模型,观察生成质量、延迟、错误率这些指标。我在实际操作中,会固定一批业务问题作为回归测试集,每次切模型前先把这些问题跑一遍,人工看输出质量,再决定放量比例。

最后分享一个我一直在用的组合:默认流式请求关闭响应缓冲,普通非流式请求保持原样;语义缓存只对幂等、重复度高的业务开启,绝不给实时创作、个性化对话类请求开缓存;限流优先按消费方维度配置,再叠加模型维度做第二层防线。这套配置帮我扛住了好几次流量高峰,也让我在复盘时能清楚地说出每笔模型开销花在了哪里。

返回列表