1. 从一堆“重复造轮子”的痛说起:QuickBlue 到底想解决什么问题
做过几年企业级项目的人大概都有类似的经历:新项目立项,架构评审会上大家一致决定“上微服务”,然后团队花了两三个月搭框架——注册中心选型、网关鉴权、链路追踪、分布式事务、多租户隔离、代码生成器、权限模型、日志审计、灰度发布……等这套底座跑通,业务需求已经堆了一屏。更尴尬的是,下一个项目来了,这套东西又要重新搭一遍,改改包名、换换配置,本质上还是在做重复劳动。
QuickBlue 就是冲着这个场景来的。它本质上是一个“AI 应用底座”,你可以把它理解成一套已经搭好骨架、通好水电、装好门窗的微服务基座,开发者进来之后主要精力放在业务逻辑和 AI 能力集成上,而不是再去纠结 Spring Cloud 版本兼容、Sentinel 规则怎么持久化到 Redis 集群、JDK 21 的虚拟线程要不要开这些底层问题。它面向的是企业内部的平台团队、中台研发、以及那些想快速把 AI 能力落到业务系统里的技术负责人。
为什么现在特别强调“AI 应用底座”这个概念?因为过去一年我接触到的项目里,十个有八个都在做“AI 加业务”的尝试——智能客服、文档问答、流程自动化、代码辅助、数据分析助手。但真正卡住他们的往往不是模型本身,而是模型怎么和现有的用户体系、权限体系、数据权限、审计日志、限流熔断对接起来。一个 AI 接口调用要经过网关鉴权、租户隔离、Token 计费、敏感词过滤、结果缓存、异步任务队列,这些全是传统微服务里已经解决过的问题。QuickBlue 的思路就是:把这些通用能力沉淀到底座里,AI 应用只需要关注 Prompt 编排、模型路由和业务语义。
所以这篇文章我会从架构设计、核心模块、实操落地、踩坑排查几个角度,把 QuickBlue 这类 AI 应用底座拆开讲清楚。不管你是正在选型的技术负责人,还是准备基于它做二次开发的工程师,都能拿到可以直接参考的东西。
2. 架构设计拆解:为什么是微服务而不是单体
2.1 单体先行还是底座先行,这是个路线问题
很多团队一上来就问:“我就做个 AI 问答,有必要上微服务吗?”这个问题没有标准答案,但我的经验是:看你的 AI 应用会不会长成企业级系统。如果只是一个内部工具,几十个人用,单体加个模块化分包完全够。但一旦涉及到多部门、多租户、多模型供应商、多业务线复用,单体就会变成一坨——改一个限流规则要全量发版,加一个模型供应商要动核心代码,权限模型和业务逻辑耦合在一起,测试环境永远和线上不一致。
QuickBlue 选择微服务路线,核心考量有三点。第一是能力复用:AI 应用底座里的用户中心、权限中心、网关、文件服务、消息服务、任务调度,这些模块在不同业务线之间是高度复用的,拆成独立服务后可以独立演进、独立扩容。第二是故障隔离:AI 调用本身是不稳定的,模型响应慢、超时、限流是常态,如果和核心业务在同一个进程里,一个慢调用可能拖垮整个应用。第三是技术异构:AI 相关的组件迭代非常快,Python 生态、向量数据库、推理框架和 Java 业务系统的技术栈差异很大,微服务边界天然适合做技术栈隔离。
但我要泼一盆冷水:微服务不是免费的。服务拆分带来的分布式事务、链路追踪、配置管理、服务发现、网络延迟,这些都是实打实的成本。QuickBlue 的价值就在于它把这些成本提前消化掉了,你拿到的是一个已经处理好这些问题的底座,而不是一堆需要你自己组装的零件。
2.2 分层架构与模块边界怎么划
QuickBlue 的整体分层我习惯用四层来理解。最底层是基础设施层,包括注册中心、配置中心、网关、缓存、消息队列、数据库连接池这些。往上一层是通用能力层,也就是用户、权限、租户、字典、日志、文件、定时任务、代码生成这些每个系统都要用的东西。再往上是AI 能力层,包括模型路由、Prompt 管理、向量检索、会话管理、Token 计量、内容安全。最上面是业务应用层,也就是你真正要交付给用户的那部分。
这个分层的关键在于依赖方向单一:业务应用层依赖 AI 能力层和通用能力层,AI 能力层依赖通用能力层,通用能力层依赖基础设施层,反向依赖是严格禁止的。我见过太多项目因为业务代码直接调用了基础设施层的 Redis 客户端,导致后面想换缓存实现时牵一发动全身。QuickBlue 在模块边界上做了强约束,每个服务只暴露 Feign 接口和 DTO,内部实现对外不可见。
模块拆分上,我建议重点关注这几个边界:认证授权独立成服务,因为所有请求都要过它;网关独立部署,承担路由、限流、鉴权前置、日志采集;AI 编排独立成服务,因为它的扩缩容策略和普通业务服务完全不同;文件与向量存储独立,因为 AI 场景下文件处理和向量检索的 IO 特征很特殊。其他的像字典、日志、消息,可以按团队规模决定是合并还是拆分,小团队合并成“系统服务”也完全可行。
2.3 JDK 21 与 Spring Cloud 版本选型的现实考量
QuickBlue 基于 JDK 21,这个选择在当下是合理的。JDK 21 是 LTS 版本,虚拟线程(Virtual Threads)正式转正,对于 AI 应用这种大量 IO 等待的场景,虚拟线程能显著提升吞吐量。我实测过一个场景:同样的模型调用接口,用传统线程池在 200 并发时线程池打满开始排队,换成虚拟线程后 2000 并发下响应时间依然平稳。当然虚拟线程不是银弹,CPU 密集型任务用它反而可能因为调度开销略慢,但在 AI 应用底座这种 IO 密集为主的场景里,收益是明显的。
Spring Cloud 版本上,JDK 21 对应的比较稳的组合是 Spring Boot 3.2.x 加 Spring Cloud 2023.0.x。这里有个坑要提醒:Spring Cloud Alibaba 的版本跟进往往比 Spring Cloud 官方慢半拍,如果你要用 Nacos、Sentinel 这些组件,一定要去官方版本对应表里核对,不要凭感觉升级。我踩过一次坑,Spring Boot 升到 3.2 之后 Sentinel 的适配包没跟上,启动直接报类找不到,排查了半天。
提示:版本选型不要追新,要追“社区验证过的组合”。QuickBlue 这类底座项目,稳定性优先级高于尝鲜。
3. 核心模块实操:从网关到 AI 编排的落地细节
3.1 网关层:鉴权、限流、日志一个都不能少
网关是整个底座的入口,QuickBlue 的网关承担了路由转发、JWT 校验、租户识别、接口限流、访问日志采集这几件事。实操上我建议把网关的职责控制在“横切关注点”,不要往里塞业务逻辑。具体配置上,路由规则建议走配置中心动态下发,而不是写死在配置文件里,这样新增服务时不用重启网关。
限流这块,Sentinel 是常见选择,但规则持久化到 Redis 集群这一步很多人会漏。默认情况下 Sentinel 规则存在内存里,服务重启就丢了,生产环境必须做持久化。QuickBlue 的做法是规则写入 Redis,网关启动时拉取,同时监听配置变更事件实时刷新。这里有个细节:Redis 集群模式下,Sentinel 的规则 key 要设计好命名空间,避免多环境互相覆盖。我一般用sentinel:{env}:{app}:{resource}这种格式。
鉴权方面,JWT 校验放在网关做前置拦截,解析出用户 ID 和租户 ID 后通过请求头透传给下游服务。下游服务不再重复解析 Token,只信任网关注入的请求头。但这里有个安全前提:下游服务必须只允许网关访问,不能直接暴露公网,否则请求头可以被伪造。内网部署时用安全组或服务网格做隔离,这是底线。
3.2 认证授权与多租户隔离的实现要点
多租户是 AI 应用底座里绕不开的话题。QuickBlue 采用的是共享数据库、共享表、租户字段隔离的方案,也就是每张业务表都带一个tenant_id,所有查询自动拼接租户条件。这个方案的好处是成本低、运维简单,缺点是隔离性弱,一旦代码里漏了租户条件就会串数据。
实现上,我推荐用 MyBatis 的拦截器做统一处理,在 SQL 执行前自动注入tenant_id条件。但要注意几个例外场景:系统表、字典表、全局配置表不应该被租户隔离,需要在拦截器里做白名单排除。另外,跨租户的统计查询要显式声明忽略租户条件,不能靠拦截器猜。
权限模型上,QuickBlue 用的是 RBAC 加数据权限的组合。RBAC 管“能不能访问这个菜单/接口”,数据权限管“能看到哪些数据”。数据权限的实现我见过很多种,比较稳的是在 SQL 层面做行级过滤,比如按部门、按创建人、按自定义范围。这里有个经验:数据权限规则不要做得太灵活,越灵活越容易出 bug,覆盖 80% 的常见场景就够了,剩下的特殊需求用自定义 SQL 解决。
3.3 AI 编排服务:模型路由与 Prompt 管理
这是 QuickBlue 区别于传统微服务底座的核心模块。AI 编排服务要解决几个问题:多个模型供应商怎么统一调用、Prompt 怎么版本化管理、会话上下文怎么维护、Token 怎么计量、结果怎么缓存。
模型路由上,我建议抽象一层统一的ModelClient接口,不同供应商(各家大模型 API)实现各自的适配器。路由策略支持按模型名、按租户、按场景、按成本优先级来选。这里的关键是降级策略:主模型超时或限流时,自动切到备用模型,保证业务不中断。降级要记录日志,方便后续分析。
Prompt 管理我强烈建议做成配置化,而不是硬编码在代码里。每个 Prompt 有唯一标识、版本号、模板内容、变量定义、适用模型。业务代码只引用 Prompt 标识,具体内容从配置中心或数据库读取。这样做的好处是运营人员可以调 Prompt 而不用发版,A/B 测试也方便。我见过一个团队把 Prompt 写死在 Java 代码里,改一个标点都要走完整发布流程,效率极低。
会话管理上,短期上下文放 Redis,设置合理的过期时间;长期会话历史落库,支持按用户、按会话查询。Token 计量要在每次模型调用后累加,按租户和用户维度统计,这是后续计费和配额控制的基础。
3.4 数据通信与缓存:Redis 集群在底座里的角色
Redis 在 QuickBlue 里承担了缓存、会话、限流计数、分布式锁、规则存储等多重角色。集群模式下有几个实操要点。第一是key 设计要带业务前缀,避免不同模块互相干扰,比如auth:token:*、ai:session:*、sentinel:rule:*。第二是大 key 和热 key 要提前预防,会话数据如果单个 key 存了几百 KB,集群迁移时会很痛苦,建议拆分存储。第三是分布式锁要用 Redisson 这类成熟组件,不要自己用 SETNX 手搓,锁续期、可重入、锁释放这些细节自己实现很容易出问题。
缓存一致性上,我一般用“先更新数据库,再删除缓存”的策略,配合延迟双删处理并发场景。但说实话,强一致性在分布式缓存里很难做到完美,业务上要能接受短暂不一致。如果某个场景绝对不能容忍脏读,那就别用缓存,直接查库。
4. 从零搭建到跑通:一个可复现的落地流程
4.1 环境准备与依赖清单
假设你要基于 QuickBlue 的思路搭一套自己的底座,环境上我建议这样准备。JDK 21 装好,Maven 3.9 以上,MySQL 8.0,Redis 7.x(集群模式至少 3 主 3 从),Nacos 2.x 做注册和配置中心,Sentinel 做限流。如果要用消息队列,RocketMQ 或 Kafka 都行,看团队熟悉度。
依赖版本上,Spring Boot 3.2.x、Spring Cloud 2023.0.x、Spring Cloud Alibaba 2023.0.x.x,这几个要对齐。MyBatis-Plus 用 3.5.x,Redisson 用 3.2x.x。这些版本组合我实测过,兼容性没问题。
注意:Nacos 2.x 默认开启了 gRPC 通信,如果服务器有防火墙策略,要提前放行 9848 和 9849 端口,否则服务注册会失败,而且报错信息很不直观,容易误判为网络问题。
4.2 服务拆分与启动顺序
服务拆分我建议按这个顺序落地:先起注册中心和配置中心,再起网关,然后是认证授权服务,接着是通用能力服务(用户、权限、字典、日志),最后是 AI 编排服务和业务服务。启动顺序有依赖关系,认证服务依赖用户服务,网关依赖认证服务做 Token 校验,所以不能乱。
每个服务的配置文件建议分三份:application.yml放通用配置,application-{env}.yml放环境相关配置,敏感信息(数据库密码、模型 API Key)走配置中心的加密配置或环境变量,不要明文写在文件里。我见过把 API Key 提交到代码仓库的,这是大忌。
4.3 关键配置示例与参数说明
网关的 Sentinel 规则持久化配置,核心是配置数据源指向 Redis。大致思路是定义一个RedisDataSource,实现ReadableDataSource接口,启动时从 Redis 读取规则,同时注册监听器。规则内容用 JSON 存储,结构包含资源名、限流阈值、流控模式、流控效果。
虚拟线程的开启很简单,Spring Boot 3.2 里加一行配置spring.threads.virtual.enabled=true即可。但要注意,虚拟线程和某些依赖 ThreadLocal 的组件可能不兼容,比如老版本的分布式追踪 SDK。开启后要重点观察日志和链路追踪是否正常。
数据库连接池用 HikariCP,连接数不是越大越好。我一般按CPU 核数 * 2 + 磁盘数估算,再结合压测调整。AI 编排服务因为大量等待模型响应,连接数可以适当调大,但要注意数据库本身的连接上限。
4.4 跑通第一个 AI 接口的完整链路
从请求进来到模型返回,完整链路是这样的:客户端请求打到网关,网关校验 JWT、识别租户、限流检查,通过后转发到 AI 编排服务。编排服务根据请求参数选择 Prompt 模板,组装上下文,调用模型适配器。适配器根据路由策略选择模型供应商,发起调用,拿到结果后做内容安全过滤、Token 计量、结果缓存,最后返回给网关,网关记录访问日志后返回客户端。
这条链路上每个环节都可能出问题,所以全链路追踪是必须的。我建议用 TraceId 贯穿整个请求,网关生成,通过请求头透传,每个服务在日志里打印 TraceId。排查问题时,一个 TraceId 就能串起所有服务的日志,效率提升非常明显。
5. 常见问题与排查技巧实录
5.1 服务注册与配置拉取失败
这是新手最常遇到的问题。现象是服务启动后注册不上,或者配置拉取超时。排查顺序我一般这样走:先确认 Nacos 服务本身是否正常,浏览器访问控制台能不能打开;再确认网络连通性,telnet 端口通不通;然后看应用日志里的具体报错,是连接超时还是认证失败;最后检查命名空间和分组配置是否匹配。
有个隐蔽的坑:Nacos 2.x 的 gRPC 端口如果没放行,HTTP 端口能通但注册会失败,报错信息可能是“连接被拒绝”或“超时”,很容易误判。解决办法就是提前确认 9848、9849 端口开放。
5.2 限流规则不生效或重启丢失
Sentinel 规则不生效,先确认规则有没有成功推送到客户端。可以在 Sentinel 控制台看规则列表,也可以看应用日志里有没有规则加载记录。如果规则在控制台有但应用不生效,多半是数据源配置有问题,或者规则格式不对。
重启丢失就是持久化没做。默认内存存储,重启必丢。解决办法就是接 Redis 或 Nacos 做持久化数据源。这里要注意,持久化数据源的优先级要高于本地配置,否则会被覆盖。
5.3 多租户数据串读的排查思路
数据串读是最危险的问题,一旦发生就是数据泄露。排查时先看 SQL 日志,确认租户条件有没有拼上。如果没拼上,检查 MyBatis 拦截器是否生效,是不是被其他拦截器覆盖了,或者该表在排除名单里。如果拼上了还串读,检查租户 ID 的来源是否正确,是不是从请求头取的时候取错了。
预防上,我建议在测试环境专门造多租户数据做交叉验证,每个接口都要测。另外,代码评审时重点看手写 SQL 的地方,自动生成的 SQL 一般没问题,手写的最容易漏。
5.4 模型调用超时与降级处理
模型调用超时是 AI 应用的常态。处理上分三层:第一层是超时设置,不同模型响应时间差异很大,超时时间要按模型配置,不能一刀切;第二层是重试,但重试要谨慎,非幂等操作不能重试,而且重试次数不宜多,否则会放大下游压力;第三层是降级,主模型不可用时切备用模型,或者返回缓存结果,或者给用户友好提示。
我踩过的坑是重试没有做退避,失败后立刻重试,结果把下游打得更惨。正确做法是加指数退避,比如 1 秒、2 秒、4 秒这样递增。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决建议 |
|---|---|---|---|
| 服务注册不上 | 端口未放行、命名空间错误 | 检查 gRPC 端口、控制台配置 | 放行 9848/9849,核对命名空间 |
| 限流不生效 | 规则未推送、数据源未配置 | 看控制台规则、应用日志 | 配置持久化数据源 |
| 数据串读 | 租户条件未拼接 | 看 SQL 日志、拦截器配置 | 检查拦截器白名单和租户来源 |
| 模型超时 | 超时设置过短、下游限流 | 看调用日志、监控指标 | 按模型配置超时,加退避重试 |
| 虚拟线程异常 | 组件不兼容 ThreadLocal | 看启动日志、追踪链路 | 升级组件或关闭虚拟线程 |
6. 我在这类底座项目上的一些实操体会
做 AI 应用底座这几年,我最大的体会是:底座的复杂度要匹配团队的成熟度。QuickBlue 这类项目功能很全,但如果团队只有三五个人,硬上全套微服务反而是负担。我的建议是分阶段来,第一阶段先把网关、认证、AI 编排这三个核心跑通,其他模块按需引入;第二阶段再补全监控、链路追踪、灰度发布;第三阶段才考虑多租户、数据权限这些高级特性。
另一个体会是配置管理比代码管理更重要。底座项目里配置项非常多,环境差异、租户差异、模型差异都体现在配置上。我见过因为配置写错导致生产事故的案例,比代码 bug 还多。所以配置要有版本管理、要有变更审计、要有回滚机制,重要配置变更要走审批。
最后分享一个小技巧:底座项目一定要有健康检查接口和就绪探针,K8s 部署时这两个配置不对,会导致流量打到还没准备好的实例上。健康检查返回应用状态,就绪探针确认依赖(数据库、Redis、注册中心)都连通了再返回成功。这个细节看起来小,但能避免很多启动期的诡异问题。
后续如果要把这套底座往 AI 原生方向再推一步,可以考虑把向量检索、RAG 编排、Agent 调度这些能力也沉淀进去,让业务方接入 AI 的门槛进一步降低。不过那是另一个话题了,先把当前这套跑稳再说。