云计算百科
云计算领域专业知识百科平台

第2章 技术选型、环境搭建与项目结构

第2章 技术选型、环境搭建与项目结构

本章目标

上一章我们先从业务角度认识了大模型、企业知识库和 RAG。你已经知道,企业知识库不是简单调用大模型接口,而是一套包含用户认证、文档管理、异步索引、向量检索、问答生成、日志追踪和前端展示的完整系统。

从这一章开始,我们正式进入项目准备阶段。

很多初学者做项目时容易犯一个错误:一上来就看技术栈,看到 Spring Cloud、Nacos、RabbitMQ、MinIO、pgvector、Redis、Sentinel,一下子觉得很复杂。其实技术栈本身并不可怕,可怕的是不知道每个技术为什么存在。

本章的目标不是让你立刻精通所有中间件,而是先建立一张清晰的地图:

  • KnowHub 为什么需要这些技术。
  • 每个技术在项目里解决什么问题。
  • 本地或 Linux 虚拟机中应该准备哪些环境。
  • rag-demo-monolith 和 rag-platform 两个项目是什么关系。
  • Spring Cloud 多模块工程的目录应该怎么看。
  • 只要你能看懂本章,后面进入代码时就不会迷路。


    2.1 技术选型必须服务于业务链路

    我们先不要急着背技术名词。先看 KnowHub 的核心业务链路。

    用户上传一份文档,系统要把它变成可问答的知识。这个过程大致是:

    请添加图片描述

    这条链路里,每个技术都有自己的位置。

    如果要保存用户、知识库、文档、任务、日志,就需要 MySQL。

    如果要根据语义相似度检索文档片段,就需要 PostgreSQL + pgvector。

    如果要保存用户上传的原始文件,并让多个服务都能访问,就需要 MinIO。

    如果文档解析和向量化耗时较长,不能阻塞上传接口,就需要 RabbitMQ 做异步解耦。

    如果要避免重复消费同一个任务,就需要 Redis 做幂等锁和状态缓存。

    如果要把多个服务拆开,就需要 Spring Cloud、Gateway、Nacos、OpenFeign。

    如果要调用大模型和 Embedding 模型,就需要 Spring AI。

    所以,技术选型不是为了堆简历关键词,而是为了让系统能稳定完成业务链路。


    2.2 KnowHub 技术栈总览

    KnowHub 的技术栈可以分成六类。

    2.2.1 Java 后端基础栈

    后端主语言是 Java 17。

    Java 17 是当前 Spring Boot 3 体系中非常常见的版本。相比 Java 8,它对现代框架支持更好,也更适合 Spring Boot 3、Spring Cloud 2025 这类新版本生态。

    后端基础框架包括:

    Spring Boot 3.x
    Spring Cloud Alibaba
    Spring Cloud Gateway
    Nacos
    OpenFeign
    MyBatis-Plus
    Maven
    Knife4j

    它们分别解决不同问题。

    Spring Boot 负责快速搭建单个服务。Spring Cloud Alibaba 负责微服务治理。Gateway 负责统一入口。Nacos 负责服务注册。OpenFeign 负责服务间调用。MyBatis-Plus 负责简化数据库访问。Maven 负责项目构建。Knife4j 负责接口文档展示。

    2.2.2 AI 与 RAG 技术栈

    AI 相关能力主要使用 Spring AI。

    Spring AI 在项目里承担两个职责:

    • 调用 Embedding 模型,把文本变成向量。
    • 调用 Chat 模型,根据上下文生成答案。

    RAG 不是只有模型调用,还需要向量检索。因此 KnowHub 使用 PostgreSQL + pgvector 作为向量存储。

    pgvector 的优点是部署简单、SQL 可调试、适合教学和简历项目。读者可以直接看到向量表、索引、TopK 查询语句,而不是一开始就被大型向量数据库的复杂部署挡住。

    后续如果文档规模变大,可以扩展到 Milvus、Elasticsearch 混合检索或 Rerank,但本书主线先用 pgvector 把核心链路讲清楚。

    2.2.3 数据与中间件

    KnowHub 使用的中间件包括:

    MySQL
    PostgreSQL + pgvector
    Redis
    RabbitMQ
    MinIO
    Nacos

    MySQL 保存业务数据。比如用户表、知识库表、文档表、切片表、任务表、问答日志表。

    PostgreSQL + pgvector 保存向量数据。比如每个 chunk 对应的 embedding 向量。

    Redis 用于缓存和幂等。比如知识库 owner 缓存、文档索引状态缓存、RabbitMQ 消费任务锁。

    RabbitMQ 用于文档索引异步化。上传文档后,系统不在上传接口里同步完成解析和向量化,而是投递消息,由 task-service 在后台消费。

    MinIO 用于对象存储。文档上传后保存到 MinIO,task-service 根据对象路径下载文件并处理,避免多服务部署时本地路径不一致。

    Nacos 用于服务注册。Gateway 可以通过服务名找到 auth-service、knowledge-service、task-service。

    2.2.4 前端技术栈

    前端使用:

    Vue 3
    Vite
    TypeScript
    Element Plus
    Pinia
    Vue Router
    Axios

    KnowHub 有两个前端入口。

    rag-user-web 面向普通用户,主要完成登录、知识库、文档上传、索引状态、问答和引用来源展示。

    rag-admin-web 面向管理员,主要完成用户管理、知识库管理、文档管理、索引任务查看、失败任务重试和问答日志查看。

    这里的重点不是页面炫酷,而是通过前端把后端链路串起来,让系统能被演示、被体验、被验证。

    2.2.5 部署与交付

    KnowHub 使用 Docker Compose 统一编排本地和虚拟机环境中的依赖。

    Docker Compose 主要负责启动:

    MySQL
    PostgreSQL + pgvector
    Redis
    RabbitMQ
    MinIO
    Nacos

    对于电脑内存不够的情况,可以采用一种更现实的方式:

    Windows 本机写代码、跑 Java 服务
    Linux 虚拟机或云服务器跑中间件

    这样既能减少本机中间件压力,也能让部署环境更接近真实服务器。


    2.3 开发环境准备

    下面我们按从基础到中间件的顺序,介绍需要准备的环境。

    2.3.1 JDK 17

    KnowHub 后端使用 Java 17。

    你需要确认本机命令行能看到正确版本:

    java -version

    预期能看到类似:

    java version "17"

    如果你的电脑同时安装了 Java 8 和 Java 17,要注意 IDEA、Maven、命令行使用的是不是同一个 JDK。很多项目启动失败,不是代码错,而是 JDK 版本不一致。

    2.3.2 Maven

    Maven 用于管理依赖和构建多模块项目。

    检查命令:

    mvn -v

    如果依赖下载很慢,可以配置国内镜像。但要注意,不要随意混用多个镜像源,否则可能出现依赖版本不一致或下载失败。

    2.3.3 IDEA

    推荐使用 IntelliJ IDEA 打开后端项目。

    打开 rag-platform 时,要从父工程 pom.xml 打开,而不是只打开某一个服务目录。因为这是 Maven 多模块项目,父工程负责统一管理版本和模块关系。

    2.3.4 Node.js

    前端项目需要 Node.js。

    检查命令:

    node -v
    npm -v

    进入 rag-user-web 或 rag-admin-web 后,可以安装依赖并启动:

    npm install
    npm run dev

    2.3.5 MySQL

    MySQL 保存业务数据。

    KnowHub 中主要表包括:

    • user_account
    • knowledge_base
    • document_info
    • document_chunk
    • index_task
    • qa_log
    • qa_reference

    这些表支撑用户、知识库、文档、任务和问答日志。

    2.3.6 PostgreSQL + pgvector

    PostgreSQL 负责存储向量数据,pgvector 是它的向量扩展。

    初始化时必须启用扩展:

    CREATE EXTENSION IF NOT EXISTS vector;

    如果忘记启用 pgvector,后续创建 vector(1024) 字段或执行向量相似度查询时会报错。

    2.3.7 Redis

    Redis 在 KnowHub 中主要用于:

    • 缓存知识库 owner。
    • 缓存文档索引状态。
    • 作为 RabbitMQ 消费幂等锁。

    比如任务消费时可以使用类似 key:

    lock:index-task:{taskId}

    这样即使 RabbitMQ 重复投递消息,也能避免多个消费者同时处理同一个索引任务。

    2.3.8 Nacos

    Nacos 用于服务注册。

    当 auth-service、knowledge-service、task-service 启动后,它们会注册到 Nacos。Gateway 根据服务名路由请求,而不是写死每个服务的 IP。

    这就是微服务和单体项目的重要区别之一。

    2.3.9 RabbitMQ

    RabbitMQ 用于异步索引。

    在 KnowHub 中,文档上传后会发送一条索引消息:

    exchange: rag.index.exchange
    queue: rag.index.queue
    routingKey: rag.index.document

    消息中只需要放任务 ID、文档 ID、知识库 ID、用户 ID,不要把整个文档内容塞进消息。

    原因很简单:MQ 适合传递事件,不适合传递大文件。大文件应该放在 MinIO,消息里只传引用。

    2.3.10 MinIO

    MinIO 是对象存储服务。

    它在 KnowHub 中负责保存用户上传的原始文档。

    对象路径可以设计成:

    kb/{kbId}/{yyyyMMdd}/{uuid}.{ext}

    比如:

    kb/12/20260726/6f1a9a6e9b7c4d2f.md

    这样既方便按知识库和日期组织文件,也避免原始文件名重复。

    2.3.11 Docker Compose

    如果你手动安装 MySQL、Redis、PostgreSQL、Nacos、RabbitMQ、MinIO,会非常麻烦。

    所以本书推荐使用 Docker Compose 编排中间件。

    你可以把 Docker Compose 理解成一个“环境启动清单”。执行一条命令,就能把项目需要的依赖统一拉起来:

    docker compose up -d

    如果你的 Windows 电脑内存不足,可以把 Docker Compose 放到 Linux 虚拟机或云服务器上运行,Java 服务仍然在 Windows 本机启动,通过 Linux IP 访问中间件。


    2.4 单体版和微服务版的关系

    本书涉及两个项目目录:

    D:\\rag\\rag-demo-monolith
    D:\\rag\\rag-platform

    初学者看到两个项目时,很容易疑惑:为什么要有两个?是不是重复了?

    不是。

    它们是演进关系。

    2.4.1 rag-demo-monolith

    rag-demo-monolith 是单体阶段项目。

    它的作用是先把 RAG 核心链路跑通:

    • 知识库管理。
    • 文档上传。
    • 文档解析。
    • 文本切片。
    • pgvector 检索。
    • RAG 问答。
    • qa_log 记录。
    • 索引任务状态。

    单体项目的优点是简单。所有代码都在一个 Spring Boot 应用里,调试方便,适合学习核心业务。

    如果一开始就上 Spring Cloud、多服务、Gateway、Nacos、Feign、RabbitMQ,初学者很容易被环境配置打乱,反而忘记 RAG 本身要解决什么问题。

    所以单体版的意义是:先理解业务闭环。

    2.4.2 rag-platform

    rag-platform 是最终 Spring Cloud 多服务版。

    它在单体版基础上增加了:

    • Gateway 统一入口。
    • Auth 认证服务。
    • Knowledge 知识库服务。
    • Task 任务服务。
    • Common 公共模块。
    • 用户端前端。
    • 管理端前端。
    • Nacos 服务注册。
    • Redis 缓存。
    • Sentinel 限流降级。
    • RabbitMQ 异步索引。
    • MinIO 对象存储。

    微服务版的意义是:把一个能跑的 RAG Demo,演进为更接近企业项目的系统。


    2.5 rag-platform 工程结构

    下面看 rag-platform 的核心目录。

    rag-platform
    ├── rag-common
    ├── rag-gateway-service
    ├── rag-auth-service
    ├── rag-knowledge-service
    ├── rag-task-service
    ├── rag-user-web
    ├── rag-admin-web
    ├── sql
    ├── docs
    ├── uploads
    ├── docker-compose.yml
    └── pom.xml

    2.5.1 rag-common

    rag-common 存放公共代码。

    常见内容包括:

    • 统一返回结构。
    • 统一异常。
    • 错误码。
    • 基础实体。
    • JWT 工具。
    • 用户声明对象。
    • 通用枚举。

    公共模块的价值是减少重复。比如 Gateway、auth-service、knowledge-service 都需要理解 Token 和用户信息,就可以复用 common 中的安全相关类。

    2.5.2 rag-gateway-service

    Gateway 是系统入口。

    它负责:

    • 根据路径转发请求。
    • 放行登录、注册等白名单接口。
    • 校验 JWT。
    • 解析用户身份。
    • 透传请求头。
    • 拦截非管理员访问 /admin/**。

    以后读者访问后端接口,应该优先通过 Gateway,而不是直接访问某个服务端口。

    2.5.3 rag-auth-service

    Auth 服务负责用户相关能力。

    主要包括:

    • 注册。
    • 登录。
    • 密码加密。
    • JWT 签发。
    • 当前用户信息。
    • 用户角色。
    • 用户状态。

    用户登录成功后,前端拿到 Token。后续所有需要登录的请求,都携带这个 Token。

    2.5.4 rag-knowledge-service

    Knowledge 服务是 RAG 主业务服务。

    它负责:

    • 知识库管理。
    • 文档上传入口。
    • 文档元数据。
    • 文档切片查询。
    • 向量检索。
    • RAG 问答。
    • qa_log 和 qa_reference。
    • Redis 缓存。
    • Sentinel 限流。
    • AI 降级。

    它是本书后续最重要的服务之一。

    2.5.5 rag-task-service

    Task 服务负责异步任务。

    在完整架构中,它会消费 RabbitMQ 消息,并执行文档索引流程。

    它主要关注:

    • index_task 表。
    • 任务状态流转。
    • 失败重试。
    • 超时扫描。
    • Redis 幂等锁。
    • RabbitMQ 消息消费。
    • 索引执行日志。

    Task 服务的存在,是为了让耗时处理从用户请求链路中拆出去。

    2.5.6 rag-user-web 和 rag-admin-web

    rag-user-web 是用户端。

    rag-admin-web 是管理端。

    用户端解决“普通用户怎么使用知识库”,管理端解决“管理员怎么查看系统运行情况”。

    这两个前端让项目从接口 Demo 变成可操作系统。

    2.5.7 sql 和 docs

    sql 目录保存初始化脚本。

    docs 目录保存接口演示、架构图、检查清单等材料。

    对一个简历项目来说,这些材料非常重要。因为它们证明项目不是只写了代码,还能复现、能演示、能讲清楚。


    2.6 端口与配置约定

    为了避免后续混乱,先统一常用端口。

    组件默认端口说明
    Gateway 9000 后端统一入口
    auth-service 9101 用户认证服务
    knowledge-service 9102 知识库与 RAG 服务
    task-service 9103 索引任务服务
    MySQL 3306 业务数据库
    PostgreSQL 5432 pgvector 向量库
    Redis 6379 缓存和幂等锁
    Nacos 8848 服务注册中心
    RabbitMQ 5672 消息通信端口
    RabbitMQ Console 15672 管理控制台
    MinIO API 9000 对象存储 API
    MinIO Console 9001 对象存储控制台
    用户端前端 5173 Vite dev server
    管理端前端 5175 Vite dev server

    实际开发时,端口冲突是很常见的问题。如果服务启动失败,第一步先看是不是端口被占用。

    Windows 可以使用:

    netstat ano | findstr 9000

    Linux 可以使用:

    lsof -i:9000


    2.7 第一次启动前的检查清单

    在真正启动项目之前,建议按下面顺序检查。

    2.7.1 基础工具检查

    java -version
    mvn -v
    node -v
    npm -v

    确认 Java 是 17,Maven 能正常运行,Node 和 npm 能识别。

    2.7.2 中间件检查

    如果使用 Docker Compose,确认容器都在运行:

    docker ps

    至少应该看到:

    mysql
    postgres / pgvector
    redis
    nacos
    rabbitmq
    minio

    如果中间件部署在 Linux 虚拟机,要确认 Windows 本机能访问 Linux IP 的对应端口。

    2.7.3 数据库初始化检查

    MySQL 要执行业务表 SQL。

    PostgreSQL 要执行 pgvector 初始化 SQL。

    如果表没有创建,后端服务即使启动成功,请求接口时也会报数据库表不存在。

    2.7.4 Nacos 检查

    启动各个微服务后,登录 Nacos 控制台,确认服务已经注册。

    至少应该看到:

    rag-auth-service
    rag-knowledge-service
    rag-task-service
    rag-gateway-service

    如果 Gateway 找不到下游服务,通常要先检查 Nacos。

    2.7.5 模型配置检查

    RAG 项目离不开模型 API。

    需要检查:

    • Chat 模型配置。
    • Embedding 模型配置。
    • API Key。
    • Base URL。
    • 模型名称。
    • Embedding 维度是否与 pgvector 表一致。

    如果 Embedding 模型输出 1024 维,但表字段不是 vector(1024),写入时会失败。


    2.8 常见问题排查

    2.8.1 JDK 版本错误

    现象:项目编译失败,提示 class file version 不匹配。

    排查:检查 java -version、IDEA Project SDK、Maven Runner JRE 是否都是 Java 17。

    2.8.2 Maven 依赖下载失败

    现象:IDEA 一直刷新 Maven,依赖红色。

    排查:检查网络、Maven settings、镜像源,必要时删除本地仓库中下载失败的半截依赖后重新刷新。

    2.8.3 Nacos 未启动

    现象:Gateway 路由失败,Feign 调用失败,控制台提示找不到服务。

    排查:先访问 Nacos 控制台,再看各服务是否注册成功。

    2.8.4 pgvector 未启用

    现象:PostgreSQL 创建 vector 字段失败,或者向量查询报错。

    排查:确认执行过:

    CREATE EXTENSION IF NOT EXISTS vector;

    2.8.5 RabbitMQ 连接失败

    现象:服务启动时报 RabbitMQ refused connection 或 authentication failed。

    排查顺序:

  • RabbitMQ 容器是否启动。
  • 端口 5672 是否能访问。
  • 用户名密码是否正确。
  • Windows 服务是否能访问 Linux 虚拟机 IP。
  • exchange、queue、routing key 是否声明一致。
  • 2.8.6 MinIO 文件访问失败

    现象:上传成功但索引任务下载文件失败。

    排查顺序:

  • MinIO 是否启动。
  • bucket 是否存在。
  • accessKey、secretKey 是否正确。
  • 对象 key 是否和数据库 storage_path 一致。
  • task-service 是否能访问 MinIO API 端口。
  • 2.8.7 Windows 路径和 Linux 路径不一致

    这是多服务项目里很容易遇到的问题。

    如果 knowledge-service 在 Windows 上传到:

    D:\\rag\\rag-platform\\uploads

    而 task-service 在 Linux 上运行,它一定读不到这个路径。

    所以完整架构中要用 MinIO,而不是依赖本地路径。上传服务和任务服务都通过对象存储访问文件,路径才不会受机器影响。


    本章小结

    这一章我们完成了 KnowHub 的技术选型和环境准备说明。

    你需要记住一点:技术栈不是越多越好,而是每个技术都要对应一个业务问题。

    KnowHub 选择 Spring Cloud,是为了解决多服务拆分和统一入口问题。选择 MySQL,是为了保存业务数据。选择 pgvector,是为了做向量检索。选择 RabbitMQ,是为了让文档索引异步化。选择 MinIO,是为了让多服务共享上传文件。选择 Redis,是为了缓存和幂等。选择 Sentinel,是为了保护 AI 问答接口。

    同时,我们也区分了 rag-demo-monolith 和 rag-platform。前者用于理解单体阶段的 RAG 主链路,后者是最终的 Spring Cloud 企业级实践项目。

    下一章,我们会正式进入从单体到微服务的演进,看看为什么一个 RAG Demo 要拆成 Gateway、Auth、Knowledge、Task 和 Common 模块。

    思考题

  • 为什么不建议初学者一开始就直接写 Spring Cloud 多服务?
  • MySQL 和 pgvector 在 KnowHub 中分别负责什么?
  • 为什么 RabbitMQ 消息里不应该存放完整文档内容?
  • MinIO 解决了本地文件存储的什么问题?
  • Gateway 和 Nacos 在微服务架构中分别承担什么职责?
  • 如果 task-service 部署在 Linux,而文件保存在 Windows 本地目录,会发生什么问题?
  • 为什么 Docker Compose 对项目交付和复现很重要?
  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » 第2章 技术选型、环境搭建与项目结构
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!