项目记录
RAG 环境搭建:六个容器与启动预热
说明 FastAPI、MySQL、Redis、Milvus、etcd 与 MinIO 的职责,以及服务启动时需要完成的预热校验。
本文目录 · 5 节
六个容器,各自在管什么
| 容器 | 角色 | 不启动会怎样 |
|---|---|---|
api | FastAPI 服务本体,跑意图、检索、生成 | 什么都没了 |
mysql | 控制面:知识库版本、会话历史、反馈 | 版本解析失败,启动直接中断 |
redis | L2 缓存:检索结果、embedding 向量 | 缓存失效,性能掉档但不报错 |
milvus | 向量库:FAQ 集合 + 文档集合 | 检索栈预热超时,服务不接流量 |
etcd | Milvus 的元数据与服务发现 | Milvus 起不来 |
minio | Milvus 的对象存储(日志、快照、段文件) | Milvus 起不来 |
很多人会疑惑:为什么一个 RAG 项目要拖六个容器?因为 Milvus 从来不是单机组件。 它需要 etcd 存元数据和做服务发现,需要 MinIO 存对象的段文件和日志快照。 把这两个当成「Milvus 的隐藏依赖」记下来,排障时能省半天。
依赖链是分层的:etcd + minio -> milvus -> api,mysql 和 redis 与 api 并行。
如果 api 起不来但 Milvus 是健康的,问题基本在配置或模型,不在检索基础设施。
为什么要做环境隔离
这套项目默认用「独立环境」的方式部署,而不是覆盖已有服务。手段有三个:
- 独立的 Compose 项目名(
COMPOSE_PROJECT_NAME) - 独立的容器名(
MYSQL_CONTAINER_NAME、API_CONTAINER_NAME等一整套) - 独立的宿主机端口:API
18000、MySQL13317、Redis16379、Milvus29530、MinIO19000/19001
结论很直接:新环境和旧部署可以同时存在,互不抢占端口、互不共享数据卷。 对「机器上已经有一套在跑的 RAG」这种真实情况,这比「先停旧的再起新的」安全得多。
启动时到底校验了什么
入口文件很短,warmup_runtime() 里的顺序就是全部的启动契约:
validate_runtime_environment() # Key、Milvus、MySQL、本地模型、场景配置
bootstrap_mysql_schema() # 建表 / 迁移控制面
validate_active_kb_versions() # 必须存在 active 知识库版本
warmup_intent_decision_gateway() # BERT 意图模型进场
(后台)refresh_llm_runtime_status() # LLM 供应商连通性,异步探测
start_retrieval_warmup_background() # BGE-M3、Reranker、Milvus collection
wait_for_retrieval_warmup() # 等它完成,再放行流量
两个设计点值得抄:
第一,LLM 连通性放到后台。 供应商接口响应慢是常态,如果放在主流程里同步探测, 启动时间就交给了外部服务。所以它异步跑,只写入运行状态。
第二,检索栈预热必须同步等待。 BGE-M3 和 Reranker 是本地模型,首次加载要几十秒; Milvus collection 首次连接也要握手。如果不等,第一个真实用户请求就要和预热竞争资源, 表现为「首问特别慢」甚至超时。宁可启动慢三十秒,也不要让用户踩这个坑。
怎么确认你真的起对了
# 只看本地运行时依赖是否齐全,不启动容器
python scripts/tools/check_local_runtime.py
# 启动独立单场景环境
.\scripts\deploy\deploy_docker_single.ps1
# 验证容器、端口、接口是否都对
.\scripts\deploy\verify_single_docker.ps1
启动日志里按顺序出现下面几行,就说明预热链路是完整的:
Runtime preflight passed: ...
Runtime MySQL schema bootstrap passed: ...
Runtime active KB version check passed: ...
Runtime BERT intent model warmup passed: ...
Runtime retrieval warmup passed: ...
拿到 http://127.0.0.1:18000 之后,接口文档在 /api/docs,管理端缓存状态在 /api/admin/cache/status。
取舍与边界
- 冷启动换稳定:预热让首次请求体验一致,代价是启动慢、滚动发布需要就绪探针配合。
- 单机 Compose 不是生产形态:这套编排适合本地、演示和单机交付; 真正多副本部署时,Milvus 和 MySQL 应该走独立集群,api 无状态横向扩。
- 模型要提前放好:BGE-M3 和 Reranker 体积不小,
download_models.py支持指定镜像源; 内网环境建议先把models/目录整体同步过去,而不是在容器里现下。 - 失败信息就是排障入口:preflight 报哪一项,就修哪一项,不要去猜。
下一篇进入数据侧:企业文档又脏又杂,它是怎么被解析、切分、加指纹, 最后变成可以增量更新的可检索知识的。