上个月我们团队开始收口 QuickBlue 这个 AI 微服务应用底座的第一阶段开发我以为最麻烦的会是模型选型或者接口设计结果真正把人按在地上磨的是环境准备。QuickBlue 的定位很明确一个面向 AI 应用的微服务底座把用户、权限、网关、基础业务和 AI 能力编排统一管起来。但正因为它是“微服务 AI”的组合体本地环境比传统业务系统多出了模型服务、配置同步、跨服务调用链这几层复杂性。这篇文章我就完整记录一下从裸机到微服务骨架跑通的全过程包括硬件怎么选、JDK 和 Spring 版本怎么配、Nacos 怎么起、Ollama 怎么接、以及第一次联调时踩过的五个坑。内容适合准备做 AI 微服务开发的工程师、正在搭底座的架构师也适合那些已经写完代码但环境一直起不来的朋友对照排查。1. 为什么 QuickBlue 要把环境准备当成一个独立交付物很多团队对微服务有个误判以为代码拆成多个模块配上几个中间件环境自然就能跑起来。实际上微服务底座的环境准备本身就是第一个交付物而且是最容易返工的交付物。1.1 微服务底座的环境准备和单体时代到底差在哪单体应用的环境准备很简单装一个 JDK装一个 MySQL装一个 RedisIDE 一开项目一跑完事。最多再处理一下 Tomcat 端口冲突。到了微服务阶段环境里至少要有注册中心、配置中心、网关、链路追踪、消息队列到了 QuickBlue 这种 AI 应用底座还要再加模型服务、向量存储、AI 网关有时候还需要模型 API 的代理层。这些东西并不是装完就能协同工作。Nacos 起来了你的服务不一定注册得上去配置中心有配置你的服务不一定拉得到网关起来了路由不一定找得到背后的实例。微服务环境准备本质是在本地模拟一套分布式运行时的最小集任何一环配置不对后面的功能开发全部卡住。在单体时代环境问题顶多让你多花十分钟在 QuickBlue 这种系统里环境问题会直接决定你一周的联调效率。1.2 QuickBlue 技术栈补全从注册中心到 AI 模型网关QuickBlue 选型时我们没有追求新潮而是以“本地好跑、上手资料多、排查成本低”为标准。最终落地的核心组件如下表组件作用本地环境中的角色JDK 17Java 服务运行基础所有 Java 微服务的底座Spring Boot 3.2.x应用框架各业务服务的基础容器Spring Cloud 2023.x微服务治理框架提供注册发现、配置管理、网关等能力Nacos 2.3.x注册中心 配置中心服务注册与配置下发本地以单机模式运行Spring Cloud GatewayAPI 网关统一切入流量也将 AI 模型调用路由到对应服务Spring AIAI 应用接入层统一封装对话模型、向量模型、结构化输出Ollama / 云端 API模型运行时本地推理或云端调用的承载方MySQL Redis业务数据与缓存基础业务模块的存储依赖为什么用 Nacos 而不是 Eureka 或者 Consul两个原因第一QuickBlue 同时需要注册中心和配置中心Nacos 一个组件就能兼任减少本地环境的进程数第二Spring Cloud Alibaba 生态对 Nacos 的适配非常完整配合spring.config.import之后配置文件从 Nacos 拉取几乎零成本。Eureka 虽然更轻但配置中心还得单独搭一套本地环境多一个进程就多一个故障点。1.3 一个可复现的环境才是团队协作的前提我在 QuickBlue 里最坚持的一件事所有环境准备必须脚本化、可复现。团队里十来个开发如果每个人凭记忆装环境你根本说不清某次联调失败是因为代码还是因为某个人的本地环境差异。最简单的做法是把中间件的启动统一收口到docker compose把 JDK、Maven、IDEA 的版本写进 README并提供一个check-env.sh脚本做环境自检。这样后来者可以照着文档从一个空白环境完整拉起底座而不是靠“你帮我看看我的环境怎么跑不起来”这种低效方式。这个思路直接影响了后面所有章节的内容我不会只告诉你“要装什么”而是把版本、命令、验证方式都写清楚。2. 开发机硬件配置与工具链版本先把底线算清楚进入实操之前先把开发机这件事说透。QuickBlue 这类系统对开发机的真实需求往往被低估你以为只是多开几个服务实际上你是同时跑着 Nacos、Redis、MySQL、网关、三四个业务服务以及一个可能占掉好几个 GB 内存的本地模型。2.1 本地跑模型的硬件底线计算如果你打算在本机跑 7B 参数级别的开源模型量级大概是这样以 Qwen2.5 7B 的 Q4 量化版为例模型权重约 4.7GB推理时还需要额外的 KV Cache 和上下文窗口空间再叠加 Spring Boot 服务自身的 JVM 内存一台 16GB 内存的开发机基本会顶满。我的建议分两种情况纯 API 开发模型部署在云端或远端 GPU 机器开发机 16GB 起步、32GB 舒适。本地模型开发用 Ollama 或 vLLM 跑模型内存至少 32GB强烈建议 64GBGPU 最好有 8GB 以上显存。磁盘也有底线。本地模型动辄几个 GB加上多个中间件容器镜像1TB NVMe SSD 是合理的起步配置否则后续同时拉几个模型时磁盘很快就爆了。2.2 双路线选择本地模型 Runtime 与云端 APIQuickBlue 的 AI 接入层我们设计成双路线既支持本地 Ollama 推理也支持云端 API。环境准备阶段必须同时验证两条路线的连通性因为实际开发中经常出现“本地模型跑不动切云端 API 继续联调”的情况。如果你的开发机没有独立显卡建议直接走云端 API 路线日常开发和联调都够了本地模型留给专门的测试机。如果你的开发机有 8GB 以上显存强烈建议把 Ollama 装上因为调试时完全离线、响应快、也没有调用消耗对模型输出的迭代非常有帮助。两条路线的详细对接方式我在第 5 节展开这里先给你一个版本层面的判断。2.3 工具链版本匹配明细表版本匹配是环境准备里最容易出问题的环节尤其是 Spring Boot、Spring Cloud、Spring AI 三个框架的版本必须互相兼容。我直接给出 QuickBlue 当前用的版本组合工具/框架推荐版本选型原因JDK17 LTSSpring Boot 3.x 的最低兼容版本也避免升级到 21 带来的本地工具链兼容问题Maven3.9.x稳定IDEA 内置兼容好Spring Boot3.2.5Spring AI 1.0.0 正式版对其支持完善Spring Cloud2023.0.3与 Spring Boot 3.2.x 版本对应Spring AI1.0.0 及以上模块化清晰支持 Ollama、OpenAI 兼容接口Nacos2.3.22.x 之后的 gRPC 端口机制稳定Docker / PodmanDocker Desktop 4.30 / Podman 4.6本地中间件容器化运行Ollama0.3跨平台拉取模型方便这里有一个非常实际的建议不要盲目升版本。Spring AI 的迭代速度很快但每次大版本升级都可能改配置项的命名空间比如spring.ai.ollama.chat在不同版本间就调整过。如果团队目标是先把业务跑通锁版本比追求新版本更明智。3. 用 IDEA 拉起 QuickBlue 微服务骨架父工程、模块拆分与依赖管理环境底子打好了接下来是把 QuickBlue 的代码骨架立起来。我们团队日常用 IDEA所以下面以 IDEA 的操作为例但底层的 Maven 结构你用命令行或 VS Code 也能复现。3.1 父工程与模块清单QuickBlue 的模块划分遵循一个原则基于业务和能力边界拆分而不是按代码复用拆分。所有模块都挂在同一个父 Maven 工程下公共代码统一收敛到quickblue-common。模块清单quickblue-common公共工具、统一返回体、异常处理、常量定义。quickblue-base基础业务服务包含用户、角色、权限、字典等基础数据能力。quickblue-business-aiAI 能力编排服务负责对接模型、管理会话、处理 Prompt。quickblue-gateway网关服务负责路由转发、鉴权、以及 AI 相关请求的聚合路由。quickblue-auth认证服务负责登录态、Token 签发与校验。在 IDEA 里创建时我不会用 Initializr 一次性把问题扔给它而是先建一个空的 Maven 父工程然后在父工程上右键新建 Module依次选择对应的 Spring Boot 依赖。这样模块边界最清晰。父工程 POM 的骨架大致如下groupIdcom.quickblue/groupId artifactIdquickblue-application/artifactId version1.0.0-SNAPSHOT/version packagingpom/packaging modules modulequickblue-common/module modulequickblue-gateway/module modulequickblue-auth/module modulequickblue-base/module modulequickblue-business-ai/module /modules properties spring.boot.version3.2.5/spring.boot.version spring.cloud.version2023.0.3/spring.cloud.version spring.ai.version1.0.0/spring.ai.version /properties3.2 依赖版本集中管理的两种方式微服务工程最大的隐患是依赖各自为政。A 服务用这个版本B 服务用那个版本联调时不报错还好一旦报错你分不清是代码兼容问题还是依赖版本问题。我推荐两种方式叠加使用第一种是父 POM 里的dependencyManagement。父工程统一声明所有关键依赖的版本子模块只声明 groupId 和 artifactId不写版本号。这是 Java 工程的老传统也是最直观的方式。第二种是外部化 BOM 导入。对于 Spring Boot、Spring Cloud 这类官方已经提供 BOM 的框架用import作用域直接引入即可。Spring Cloud Alibaba 和 Spring AI 也都有对应的 BOM简化版本管理dependencyManagement dependencies dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-alibaba-dependencies/artifactId version2023.0.3.0/version typepom/type scopeimport/scope /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring.ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement这里有个容易被坑的地方Spring Cloud Alibaba 的版本号与 Spring Cloud 的版本号不是一一对应的。比如 Spring Cloud 2023.0.3对应的 Spring Cloud Alibaba 可能是 2023.0.3.0。如果你只盯着 Spring Cloud 版本很容易配错。建议直接到 Spring Cloud Alibaba 官方文档的版本说明页面确认对应关系。3.3 微服务拆分的最小集原则很多人在拆分微服务时会过度设计QuickBlue 的经验是本地环境能跑通的最小集才是微服务拆分的第一版参考标准。如果你拆出十几个服务本地联调一次要启动十几个进程单机内存直接见底这种项目连日常开发效率都保障不了更不用谈交付。QuickBlue 第一阶段只拆了五个模块加上网关正好六个这套组合在 32GB 的开发机上能流畅跑起来。等业务复杂度真正上来之后再按领域边界拆分新的服务比一开始就拆得稀碎要科学得多。环境准备本质上也会反推你的架构是否合理如果一套本地环境起一个服务就卡半天那架构大概率有问题。4. 中间件与注册中心本地化Nacos、MySQL、Redis 的容器化启动骨架工程有了接下来是整个环境准备的重头戏中间件。QuickBlue 本地联调依赖 Nacos、MySQL、Redis如果做 AI 相关业务还需要一个可用的模型服务或 API key。4.1 Nacos 2.x 的单机启动与端口玄机Nacos 在 QuickBlue 里承担两个角色注册中心和配置中心。本地开发用单机模式就行不需要搞集群。很多团队被 Nacos 坑过一次基本都是同一个原因只映射了 8848 端口。Nacos 2.x 和 1.x 最大的区别是引入了 gRPC 通信。服务注册、配置监听、服务发现的长连接都走 gRPC主端口是 8848但 gRPC 端口默认是主端口加 1000也就是 9848。如果本地只映射了 8848服务端会显示正常但客户端服务注册会反复失败日志里出现Client not connected, current status: STARTING。正确的启动命令是这样docker run -d --name nacos-quickblue \ -e MODEstandalone \ -e JVM_XMS256m \ -e JVM_XMX512m \ -p 8848:8848 \ -p 9848:9848 \ nacos/nacos-server:v2.3.2启动后先不要急着接服务先确认 Nacos 控制台能打开再确认 9848 端口处于监听状态。可以用docker logs看启动日志看到startup相关的成功日志再继续。4.2 用 docker compose 一键拉起底座中间件如果每次手动敲docker run那你迟早会漏掉某个环境变量。QuickBlue 把中间件统一收口到一个docker-compose.yml一条命令拉起所有基础依赖services: mysql: image: mysql:8.0 container_name: quickblue-mysql environment: MYSQL_ROOT_PASSWORD: root TZ: Asia/Shanghai ports: - 3306:3306 volumes: - mysql-data:/var/lib/mysql redis: image: redis:7.2 container_name: quickblue-redis ports: - 6379:6379 nacos: image: nacos/nacos-server:v2.3.2 container_name: quickblue-nacos environment: - MODEstandalone - JVM_XMS256m - JVM_XMX512m ports: - 8848:8848 - 9848:9848 volumes: mysql-data:MySQL 有两个细节值得单独提醒。第一是字符集如果数据库默认字符集不是 utf8mb4AI 会话内容里的 emoji 或特殊字符入库时会报错。第二是时区容器默认时区是 UTC和本机时间对不上会影响日志排查所以上面的配置里加了TZAsia/Shanghai。4.3 配置中心的首份配置如何写入中间件启动后下一步是把共享配置写入 Nacos。QuickBlue 的做法是把公共配置数据源、Redis、公共开关放到 Data ID 为quickblue-common.yaml的配置里各服务自己的配置文件保留在本地只把关键内容通过spring.config.import拉取。在 Spring Boot 3.2 和 Spring Cloud 2023 的组合里从 Nacos 拉配置的标准写法是spring: config: import: - nacos:quickblue-common.yaml?groupDEFAULT_GROUP这条配置拉取机制经常被忽略尤其是从旧版本升级上来的团队。以前用bootstrap.yml现在默认需要用spring.config.import否则你在 Nacos 里改了配置服务端完全感知不到。5. AI 引擎接入底座的两种路径Ollama 本地推理与云端 APIQuickBlue 既然叫 AI 微服务应用底座AI 引擎的环境准备自然避不开。这里我把两条路线的配置都完整贴出来你按自己的硬件条件二选一。5.1 Ollama 本地模型的部署与验证安装 Ollama 这一步没什么悬念去官网下载对应系统的安装包就好。关键是选模型。QuickBlue 默认使用 Qwen2.5 7B 做日常验证因为它在中文场景表现稳定、资源占用又相对友好。拉取并启动模型ollama pull qwen2.5:7b ollama run qwen2.5:7b看到输入框并能正常对话说明本地模型服务已经通了。Ollama 默认监听 11434 端口可以用下面的命令验证 API 是否可访问curl http://127.0.0.1:11434/api/tags返回模型列表就说明模型运行时正常。这一步验证非常关键因为后面如果 Spring AI 连不上模型问题大概率出在 Ollama 没启动或者模型没拉全而不是代码本身的问题。5.2 Spring AI 对接模型服务的基础配置QuickBlue 的quickblue-business-ai模块中接入本地 Ollama 的配置是这样的spring: ai: ollama: base-url: http://127.0.0.1:11434 chat: options: model: qwen2.5:7b temperature: 0.7如果是走云端 API配置改成 OpenAPI 兼容的方式即可。现在很多云端模型服务都提供 OpenAI 兼容的接口Spring AI 对这类接口的支持也最成熟spring: ai: openai: base-url: https://api.example.com/v1 api-key: ${AI_API_KEY} chat: options: model: gpt-4o-mini注意api-key不要硬编码在配置文件里用环境变量注入。这个约定不是矫情而是环境准备阶段就养成的好习惯不然配置一不小心提交到代码仓库密钥就泄露了。5.3 两条路线的取舍建议对比维度本地 Ollama云端 API硬件要求32GB 内存 8GB 显存起步几乎无要求响应速度取决本地显卡一般较快受网络影响离线能力完全离线不可离线成本一次性硬件成本按量计费隐私数据不出本机数据上传云端调试便利性可随时换模型、改参数需要联网API 波动影响排查我的建议很直接开发阶段优先本地 Ollama因为你可以随便调参数、随便重启不产生任何 API 费用只有当你需要验证云端模型特有能力和真实生产环境表现时再切到云端 API。把两套配置都放到环境变量开关后面切换成本几乎为零。6. 首次联调复盘服务启动顺序与五个常见环境坑最后这部分是 QuickBlue 联调时的真实复盘。代码层面其实大家写起来都差不多真正拉低效率的是环境层面的问题。6.1 启动顺序背后的依赖逻辑微服务启动不是随手点的QuickBlue 本地联调建议按这个顺序启动基础设施MySQL、Redis、Nacos。注册中心就绪打开 Nacos 控制台确认命名空间和分组正确。基础能力服务quickblue-common是被依赖的 jar 包不用单独启动先启动quickblue-base。网关服务quickblue-gateway。AI 业务服务quickblue-business-ai。若走本地模型路线提前把 Ollama 拉起来。为什么网关不能先启动因为网关启动后会注册到 Nacos路由配置依赖服务发现。如果后面服务还没注册上网关会因为找不到实例而报 503。虽然后续服务注册后网关会自动恢复但日志里多一堆无意义的告警干扰排查。6.2 五个常见坑的完整排查链路坑一服务注册不上 Nacos但控制台能打开。这个症状主要会翻译成“服务一直显示不健康”。排查链路是先确认容器是否映射了 9848 端口用netstat或lsof检查本机端口监听状态。再确认服务配置里的spring.cloud.nacos.discovery.server-addr是否写成了127.0.0.1:8848这个写法本身没问题但少了 gRPC 端口依赖。最后看服务日志里有没有 gRPC 连接失败的异常有的话基本就是端口问题。坑二配置中心的配置改了服务不生效。这种时候先看服务启动日志里有没有加载 Nacos 配置的记录。Spring Cloud 2023 之后不推荐直接用bootstrap.yml如果你没配spring.config.import服务根本不会去拉远程配置。这个问题很隐蔽因为本地配置文件都在服务能正常启动但远程配置永远不生效。坑三网关路由 503但目标服务在 Nacos 里明明是健康的。这个坑的典型场景是网关没有使用负载均衡地址。网关配置路由时如果直接写了http://127.0.0.1:8081服务实例一变地址就失效。正确做法是使用 lb 前缀让网关从 Nacos 动态发现实例spring: cloud: gateway: routes: - id: route-business-ai uri: lb://quickblue-business-ai predicates: - Path/ai/**坑四Spring AI 调用模型一直超时。先别急着调代码。用 curl 直接打 Ollama 或云端 API确认模型服务的连通性。如果是本地 Ollama确认模型是否已下载完成第一次调用时可能还在加载模型如果是云端 API确认网络是否通、API key 是否有效、是否限流。把模型层的问题和代码层的问题分开排查效率会高很多。坑五Lombok 编译失败注解生成的方法找不到。这类问题通常表现为新 clone 的代码一编译就报符号找不到。多数原因是 JDK 版本和 Lombok 版本不匹配或者工程里同时存在多个 Lombok 版本。QuickBlue 的处理是在父 POM 统一声明 Lombok 版本并启用annotationProcessorPaths显式指明注解处理器路径避免 IDE 默认行为差异。6.3 一分钟快速验证清单联调开始前按这个清单快速检查一轮Nacos 控制台可达服务列表为空或仅包含预期服务。Redisping返回PONG。MySQL 能用配置的用户名密码登录字符集为 utf8mb4。本地模型用curl能请求通。网关/actuator/health返回UP。任意调用一个经过网关的业务接口确认路由和鉴权链路正常。这些检查全部通过环境准备才算合格只要有一项不通过后面的联调大概率会被同样的问题卡住。在环境准备这块我最大的体会是不要以为环境准备是“辅助工作”它在微服务底座项目里是最该先被工程化的内容。把环境脚本化、版本化、验证化之后团队新成员从拉代码到跑通底座只需要半天而不是一周。这个投入相当值得。
