AI 网关实战(二):拆解网关内部模块

14 阅读12分钟

AI 网关实战(二):拆解网关内部模块

这是「AI 网关实战」系列第 2 篇。 上篇我们聊了为什么要搭 AI 网关,这篇深入每个模块,看看网关内部到底是什么样。


目录


先回忆一下 7 个模块

AI 网关架构设计参考 OpenAI 网关,结合银行场景的特殊要求,设计了 7 个核心模块:

模块重要性做什么
API 网关★★★★★统一入口,兼容 OpenAI 格式
认证授权★★★★★JWT 管理端 + API Key 应用端
渠道管理★★★★★多供应商接入 + 故障转移
合规过滤★★★★敏感词 + 脱敏 + 风险提示
审计日志★★★★★每一条请求可追溯
限流熔断★★★★多层限流 + 熔断降级
流式处理★★★★★SSE 流式返回

星级表示在银行场景下的重要性,你可以根据自己的业务需求调整优先级。

下面逐个模块详细讲解设计目标、核心功能和实现要点。


模块 1:API 网关层 ★★★★★

设计目标

客户端只认一套接口(OpenAI 兼容格式),无论底层调用的是 OpenAI、通义千问还是智谱,对客户端来说都是一样的。这样可以屏蔽下游供应商的差异,客户端只需要统一调用网关的接口即可。

核心功能

AI 网关作为统一入口,需要提供以下核心功能:

功能说明接口
聊天补全流式/非流式都支持POST /api/v1/chat/completions
文本补全简单文本生成POST /api/v1/completions
模型列表聚合所有渠道可用模型GET /api/v1/models
多渠道路由按优先级 + 权重选择内部逻辑
失败重试可重试状态码 + 熔断 + 备用渠道内部逻辑

关键设计:流式响应处理

这是新手最容易踩坑的地方。

流式请求有个矛盾:入参要全量过滤(好办),出参是分段返回的,怎么合规?

我的方案是:

场景策略
非流式请求请求和响应都做完整敏感词检测
流式请求(入参)全量过滤(入参不是流式,没问题)
流式请求(出参)逐 chunk 做快速检测,完整响应异步审计留存

为什么出参不全程拦截?

因为流式体验的核心是"即时性",如果你等 AI 把话说完再检测合规,用户会感觉像在看慢动作回放。

所以我的做法是:

  • 逐 chunk 做快速检测(只检测高频敏感词)
  • 一旦发现违规,立即中断流,返回错误
  • 完整响应异步审计,留存证据

模块 2:认证授权 ★★★★★

设计目标

银行场景必须有两套认证体系:

认证方式用途
管理端JWT Token管理员登录后台,配置渠道、管理 API Key
调用端API Key业务系统调用 AI 接口

核心功能

认证授权模块提供以下核心功能:

功能说明
JWT 认证管理端登录获取 Token,有效期 2h
API Key 认证前缀定位 + Hash 校验
API Key 管理创建/禁用/删除/轮换
配额校验Key 级别配额检查(请求数 + Token 数)
登录安全密码策略 + 失败锁定

关键设计:API Key 只存哈希

创建 API Key 时的流程:

1. 管理员登录 → 获取 JWT Token
2. 用 JWT 调用创建 API Key 接口
3. 生成随机 Key: sk-{8位随机前缀}-{32位随机后缀}
4. 存储: key_prefix = "sk-xxxxxxxx", key_hash = SHA256(完整key)
5. 返回: 完整 Key 明文(仅此一次,不存储明文)

客户端调用时:

1. Header: Authorization: Bearer sk-xxxxxxxx-yyyyyyyyyyyyyyyyyyyyyyyy
2. 系统用 key_prefix("sk-xxxxxxxx") 快速定位数据库记录
3. 对完整 key 做 SHA256,与 key_hash 比对
4. 通过 → 校验配额 → 放行

为什么要用前缀?

如果直接用 SHA256 做索引,每次都要哈希一遍,效率太低。用前缀定位,再哈希校验,速度更快。

密码安全策略

项目规范
哈希算法bcrypt,cost factor ≥ 12
密码长度≥ 8 位
复杂度必须包含大写 + 小写 + 数字 + 特殊字符
失败锁定连续 5 次失败,锁定 30 分钟

模块 3:渠道管理 ★★★★★

设计目标

支持多家 AI 供应商接入,实现故障转移和负载均衡,避免单点故障。

支持的渠道

AI 网关支持以下 6 家主流 AI 供应商:

类型配置项说明
OpenAIbase_url, api_key, models, organization官方/兼容 API
Claudebase_url, api_key, models, anthropic_versionAnthropic
文心api_key, secret_key, model_ids百度
通义api_key, model_ids阿里
智谱api_key, model_ids清华
Kimiapi_key, model_ids月之暗面

核心功能

渠道管理模块的核心功能:

功能说明
渠道配置支持上述 6 家供应商
渠道状态启用/禁用/熔断状态
模型映射统一名称 → 渠道模型映射(如 gpt-4 → 各家的不同模型名)
健康检查定时探测渠道可用性
渠道 API Key 加密AES-256-GCM 加密(下篇详细讲)

关键设计:模型映射

不同供应商对同一能力的模型命名不一样:

OpenAI: gpt-4
文心: ERNIE-Bot-4
通义: qwen-max

业务系统只认统一的 gpt-4,网关内部通过模型映射表转换:

CREATE TABLE model_mappings (
    unified_name    VARCHAR(64)     NOT NULL,  -- 统一名称:gpt-4
    channel_id      BIGINT          NOT NULL,
    provider_model  VARCHAR(64)     NOT NULL,  -- 渠道内模型名:ERNIE-Bot-4
    status          SMALLINT        NOT NULL DEFAULT 1
);

模块 4:合规过滤 ★★★★

设计目标

银行场景必须防止违规内容通过网关,确保输出内容符合合规要求。

核心功能

合规过滤模块提供以下功能:

功能说明
敏感词过滤入参/出参检测,支持白名单和组合规则
违规拦截命中 BLOCK 规则直接拒绝
风险提示自动追加免责声明
内容脱敏手机号/身份证/银行卡号掩码
过滤策略扩展点策略模式,预留 LLM 辅助判断扩展

关键设计:过滤器链(策略模式)

采用策略模式实现过滤器链,方便扩展:

public interface ContentFilter {
    String name();
    FilterResult filter(String content, FilterContext context);
    int order();  // 执行顺序
}

// MVP 实现
public class RegexFilter implements ContentFilter { ... }     // 正则脱敏
public class KeywordFilter implements ContentFilter { ... }   // 敏感词检测
public class DisclaimerFilter implements ContentFilter { ... } // 免责声明

过滤执行顺序:

1. RegexFilter (order=10)  — 正则脱敏(手机号/身份证/银行卡号掩码)
2. KeywordFilter (order=20) — 敏感词检测(含组合规则)
3. DisclaimerFilter (order=30) — 追加风险提示(仅出参)

敏感词分类

分类说明默认动作
FRAUD诈骗相关BLOCK
COMPLIANCE合规红线BLOCK
PRIVACY隐私信息MASK
RISK风险敏感WARN
POLITICAL政治敏感BLOCK

组合规则示例

规则: "转账" AND "验证码" → BLOCK
含义: 同时出现"转账""验证码"时拦截,防止社会工程学攻击

模块 5:审计日志 ★★★★★

设计目标

每一条管理操作、每一条 AI 调用都要可追溯,且不可篡改,满足合规审计要求。

审计范围

审计日志需要记录以下操作:

操作类型资源类型说明
CREATE / DELETEAPI_KEYKey 的创建和删除
CREATE / UPDATE / DELETECHANNEL渠道的增删改
UPDATECONFIG系统配置变更
UPDATEUSER用户状态变更
LOGIN / LOGIN_FAILSESSION登录成功/失败

核心功能

审计日志模块的核心功能:

功能说明
操作审计记录所有管理操作(增删改)
变更快照记录操作前后的数据变更
查询接口支持按操作人/时间/类型查询
不可篡改审计日志只增不改不删

模块 6:限流熔断 ★★★★

设计目标

控制成本,保护服务稳定性,防止恶意调用或意外超支。

核心功能

限流熔断模块的核心功能:

功能说明
API Key 级限流令牌桶,每 Key RPM + TPM 双维度
模型级限流滑动窗口,防止单模型耗尽渠道配额
全局限流保护网关自身
渠道熔断Resilience4j 熔断器
重试策略可重试状态码 + 指数退避

限流配置示例

rate-limit:
  global:
    max-rpm: 1000            # 全局每分钟最大请求数
  api-key:
    algorithm: token-bucket
    default-rpm: 60          # 默认每分钟60次
    default-tpm: 100000      # 默认每分钟10万token
  model:
    algorithm: sliding-window
    overrides:
      gpt-4: { rpm: 10, tpm: 10000 }
      gpt-4o: { rpm: 30, tpm: 60000 }
      gpt-3.5-turbo: { rpm: 120, tpm: 200000 }

熔断配置

circuit-breaker:
  failure-rate-threshold: 50         # 失败率阈值50%
  slow-call-rate-threshold: 80       # 慢调用率阈值80%
  slow-call-duration-threshold: 10s  # 慢调用判定阈值
  sliding-window-type: COUNT_BASED   # 基于计数的滑动窗口
  sliding-window-size: 10            # 窗口大小10次
  minimum-number-of-calls: 5         # 最少5次调用后开始计算
  wait-duration-in-open-state: 60s   # 熔断开启后等待时间
  permitted-number-of-calls-in-half-open-state: 3  # 半开状态允许的探测调用数

模块 7:流式处理 ★★★★★

设计目标

AI 对话必须流式,否则体验太差。

核心功能

流式处理模块的核心功能:

功能说明
SSE 流式响应Spring WebFlux Flux
流式合规处理入参全量过滤 + 出参滑动窗口快速检测
流式中断检测到违规内容时中断流式输出
超时控制流式请求整体超时 + 单 chunk 超时

一个请求的完整流转路径

上面讲了 7 个模块,现在把它们串起来,看看一个请求从进入到响应,到底经过了什么。

非流式请求(标准场景)

客户端请求
   │
   ▼
[AuthFilter] ── Token/API Key 校验
   │
   ▼
[RateLimitFilter] ── 限流检查(Redis 令牌桶)
   │
   ▼
[ComplianceFilter] ── 入参合规过滤(敏感词 + 脱敏)
   │
   ▼
[RouteService] ── 模型映射 + 渠道路由(优先级 + 权重)
   │
   ▼
[CircuitBreaker] ── 熔断检查(Resilience4j)
   │
   ▼
[ModelAdapter] ── 渠道适配器(OpenAI/Claude/文心/通义/...)
   │
   ▼
[ComplianceFilter] ── 出参合规过滤(敏感词 + 脱敏 + 风险提示)
   │
   ▼
[AuditLogger] ── 记录调用日志 + 审计日志
   │
   ▼
客户端响应

流式请求(SSE)

流式请求的流转路径略有不同,主要差异在于合规处理和审计日志的处理方式:

客户端请求(stream=true)
   │
   ▼
[AuthFilter] ── Token/API Key 校验
   │
   ▼
[RateLimitFilter] ── 限流检查
   │
   ▼
[ComplianceFilter] ── 入参合规过滤(全量)
   │
   ▼
[RouteService] ── 模型映射 + 渠道路由
   │
   ▼
[CircuitBreaker] ── 熔断检查
   │
   ▼
[ModelAdapter] ── 渠道适配器(返回 Flux<ServerSentEvent>)
   │
   ▼
[StreamComplianceFilter] ── 逐 chunk 快速检测
   │  ├─ 发现违规 → 立即中断流 → 返回错误
   │  └─ 无违规 → 继续
   │
   ▼
[DisclaimerFilter] ── 追加风险提示(最后一个 chunk)
   │
   ▼
[AuditLogger] ── 异步审计(完整响应留存)
   │
   ▼
客户端流式接收

故障转移流程

当某个渠道出现故障时,系统会自动切换到备用渠道:

请求 → 渠道A
   │
   ├─ 成功 → 返回
   │
   └─ 失败(可重试) → 重试渠道A(最多2次)
        │
        ├─ 成功 → 返回
        │
        └─ 仍失败 → 记录渠道A失败 → 选择渠道B(同优先级次选或低优先级)
             │
             ├─ 成功 → 返回
             │
             └─ 仍失败 → 返回错误(无可用渠道)

下一步

这篇讲了 7 个模块的设计细节,以及请求在网关内部的完整流转路径。

但还有个问题没说:我们用什么技术栈来实现这些?

下一篇(第 3 章)会详细讲技术选型:为什么是 Spring Boot 3 WebFlux + PostgreSQL + Redis,而不是其他组合。


关于源码和开发进度

这个项目的开发进度会在 GitHub 上持续更新,每一章对应的代码推进都会提交记录,你可以随时看到项目从零到一的成长过程。

GitHub 地址:github.com/ynzz-j/bank…

完整源码计划在完成最新 MVP 版本后,统一上传到 Gitee,届时会在公众号和系列文章里同步通知。


🔔 关注有价值

关注「亦暖筑序」,不错过系列更新:

已发布章节

  • 第 1 章:参考 OpenAI 架构,设计企业级 AI 网关

下篇预告

  • 第 3 章:技术选型——为什么是 Spring Boot 3 WebFlux + PostgreSQL + Redis

源码进度

🐙 开发进度在 GitHub 持续更新:github.com/ynzz-j/bank…

📦 完成最新 MVP 后,完整源码统一上传 Gitee