点击展开目录
这是一个基于多语言技术栈构建的 IT 智能文章推荐与知识问答系统,主要包含以下框架:
- Spring(Java)
- GoZero(Go)
- NestJS(Node.js)
- FastAPI(Python)
所有服务通过 SpringCloud Gateway 统一网关进行访问,实现了服务治理、认证授权等功能。
- 基于 SpringBoot 和 MybatisPlus 实现文章发布、修改等操作,文章的创建和显示都支持 Markdown
- 基于 SpringBoot 和 MybatisPlus 实现用户、分类、评论、点赞、收藏、关注等业务模块
- 基于 SpringBoot 和 Redis 进行文章分类,用户状态/Token的管理操作
- 基于 SpringBoot 和 AOP 技术权限校验实现用户端和管理端
- 基于 SpringCloud Gateway 和 JWT 实现 API 网关的统一认证和权限控制
- 基于 Redis Token Bucket 算法在网关层实现 API 限流和防刷功能
- 基于 GoZero 聚合 ElasticSearch、pgvector 向量检索和 Neo4j 图谱增强,实现关键词、语义和关系融合的文章搜索
- 基于 GoZero 和 GORM/sqlx 实现文章相关数据获取和同步(双 ORM 并存)
- 基于 GoZero 和 WebSocket/SSE 实现用户实时聊天功能和消息通知
- 基于 NestJS 和 Mongoose 进行文章操作日志和 API 日志的查看和分析
- 基于 NestJS 和 TypeORM 实现文章下载的文章和用户数据获取
- 基于 FastAPI 和 ClickHouse 技术栈实现系统数据的相关分析
- 基于 FastAPI 和 SQLAlchemy 进行文章相关数据的获取和同步
- 基于 FastAPI 和 LangChain 实现 RAG 文章检索增强和 Tools 调用 SQL、MongoDB、Neo4j,支持 GPT/Gemini/DeepSeek 进行多模型选择
- 基于 FastAPI 和 Neo4j 实现文章、用户、分类、标签、点赞、收藏、评论、关注等实体关系图谱,用于关系查询和图谱推荐
- 基于 NestJS 和 Spring 实现 GitHub OAuth 登录/注册,NestJS 处理 GitHub 授权回调并创建/关联用户,Spring 生成站内登录票据,支持首次 GitHub 登录自动注册,前端通过一次性 ticket 换取 JWT
| 项目 | 说明 |
|---|---|
| 框架 | SpringBoot 3.x + MyBatisPlus |
| 数据库 | MySQL(demo 库,user/article/category/comment 等核心表) |
| 缓存 | Redis |
| 消息队列 | RabbitMQ |
| 注册中心 | Nacos |
| 构建工具 | Maven / Gradle |
| 主要功能 | 用户认证(密码登录/邮箱登录/Token 管理)、文章 CRUD、分类管理、评论点赞收藏关注、权限校验 |
| 代码位置 | spring/ |
| 项目 | 说明 |
|---|---|
| 框架 | GoZero |
| 数据库 | MySQL(同步 Spring 数据) |
| 搜索引擎 | Elasticsearch(文章搜索) |
| 实时通信 | WebSocket(用户聊天)/ SSE(消息通知) |
| 注册中心 | Nacos |
| 构建工具 | Go Modules |
| 主要功能 | 文章搜索引擎、ES 数据同步、用户实时聊天、消息通知 |
| 代码位置 | gozero/ |
| 项目 | 说明 |
|---|---|
| 框架 | NestJS + Fastify |
| 数据库 | MySQL(TypeORM 用户/文章/下载)、MongoDB(Mongoose 文章日志/API 日志) |
| 缓存 | Redis(ioredis) |
| 消息队列 | RabbitMQ |
| 注册中心 | Nacos |
| 运行时 | Node.js / Bun |
| 主要功能 | 文章/API 操作日志、Word/PDF 下载、文件上传(OSS)、GitHub OAuth 登录、定时任务 |
| 代码位置 | nestjs/ |
| 项目 | 说明 |
|---|---|
| 框架 | FastAPI + SQLAlchemy |
| 数据库 | MySQL(数据同步)、ClickHouse(数据分析)、PostgreSQL + pgvector(RAG 向量存储)、Neo4j(知识图谱) |
| 消息队列 | RabbitMQ |
| 注册中心 | Nacos |
| 运行时 | Python 3.12+ |
| 主要功能 | 数据分析与统计、RAG 文章检索增强、Neo4j 知识图谱、AI Agent(SQL/MongoDB/向量搜索/图谱查询)、多模型(GPT/Gemini/DeepSeek) |
| 代码位置 | fastapi/ |
| 项目 | 说明 |
|---|---|
| 框架 | SpringCloud Gateway |
| 注册中心 | Nacos(服务发现 + 负载均衡) |
| 缓存 | Redis |
| 主要功能 | 统一入口、JWT 认证鉴权、路径路由、API 限流(Redis Token Bucket)、用户信息透传 |
| 网关白名单 | 登录/注册/验证码/GitHub OAuth 等无需认证的路径 |
| 代码位置 | gateway/ |
前端点击 "GitHub 登录" 按钮
-> GET /github/authorize?redirect=/profile (NestJS)
-> 浏览器跳转 GitHub 授权页
-> 用户授权后 GitHub 回调 GET /github/callback (NestJS)
-> NestJS 获取 GitHub 用户信息,创建或关联本地用户
-> NestJS 通过 Nacos 调用 Spring POST /users/github/token-ticket
-> Spring 生成一次性 ticket,存入 Redis(TTL 60秒)
-> NestJS 重定向到前端 /oauth/github/success?ticket=xxx
-> 前端 POST /users/github/token (Spring)
-> Spring 验证 ticket 后返回 JWT(access + refresh token)
-> 前端保存 token,登录完成
网关负责路由:
/github/**-> NestJS(GitHub OAuth 流程)/users/github/token-> Spring(token 换取)
前端输入用户名和密码
-> POST /users/login
Content-Type: application/json
Body: { "username": "hcsy", "password": "123456" }
-> Spring 校验用户名和密码(bcrypt 匹配)
-> 校验通过后,调用 TokenService 生成 JWT(access token + refresh token)
-> 将 session 信息写入 Redis(user:access / user:session)
-> 返回 UserLoginVO(含 accessToken / refreshToken / userId / username / sessionId)
-> 前端保存 token,后续请求在 Authorization 头携带 Bearer token
Body 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | 是 | 用户名 |
| password | string | 是 | 密码 |
返回结构与 GitHub 登录的 token 换取接口一致。
前置:用户需要先有已验证的邮箱(注册时填写或后续绑定)
-> GET /users/email/send?email=xxx@example.com&type=login(发送验证码)
-> Spring 校验邮箱是否存在,存在则发送验证码到该邮箱
前端输入邮箱和验证码
-> POST /users/email-login
Content-Type: application/json
Body: { "email": "xxx@example.com", "verificationCode": "123456" }
-> Spring 校验验证码是否正确且未过期
-> 校验通过后,调用 TokenService 生成 JWT
-> 返回 UserLoginVO(结构同上)
-> 前端保存 token
发送验证码接口:
GET /users/email/send?email=xxx@example.com&type=login
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| string | 是 | 注册时填写的邮箱 | |
| type | string | 否 | 固定传 login |
邮箱验证码登录接口:
POST /users/email-login
Content-Type: application/json
Body 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| string | 是 | 邮箱地址 | |
| verificationCode | string | 是 | 收到的 6 位验证码 |
验证码有效期默认为 5 分钟,发送间隔为 60 秒。
- SpringBoot:Java 后端框架,支撑系统核心业务服务
- GoZero:Golang 后端框架,支持系统高并发服务
- NestJS:Node.js 后端框架,支撑系统日志处理服务
- FastAPI:Python 后端服务,支撑系统数据分析和 Agent 服务
- Spring Cloud Gateway:API 网关
- JWT:身份验证
- Nacos:服务发现与配置中心
- MySQL:关系型数据库,系统核心数据库
- PostgreSQL:RAG 向量数据库
- MongoDB:非关系型数据库,系统日志数据库
- Neo4j:图数据库,存储文章、用户、分类、标签等实体关系
- ElasticSearch:搜索引擎,系统搜索优化
- Redis:缓存服务和状态管理
- RabbitMQ:异步消息队列
- ClickHouse:大数据存储与分析
- WebSocket:用户实时聊天
- SSE:实时通知未读消息
- LangChain:大模型调用和 RAG 框架
- 阿里云百炼平台
- Close AI
- 阿里云 OSS
- GitHub OAuth(GitHub 第三方登录/注册)
- Java 17+
- Maven 3.6+
- Gradle 9.3+(可选,但推荐用于 Java 项目构建)
- Go 1.23+
- Node.js 20+
- Bun 1.2+(可选)
- Python 3.12+
- uv 0.9+(可选)
- MySQL 8.0+
- PostgreSQL + pgvector 15.4+
- MongoDB 5.0+
- Neo4j 5.x+
- ElasticSearch 7.12.1+
- Redis 6.0+
- RabbitMQ 3.8+
- ClickHouse 21.8+(可选)
提示: 推荐使用
setup.sh配置脚本自动完成以下所有安装步骤。如果需要手动配置,可以按照下面的步骤逐个模块进行。
cd spring # 进入文件夹
cd gateway # 进入网关
mvn clean install # 下载依赖
gradle wrapper # 生成项目专用 Gradle,运行自动下载依赖cd gozero/app # 进入文件夹
go mod tidy # 安装依赖
go install github.com/zeromicro/go-zero/tools/goctl@latest # 安装 goctl 代码生成工具cd nestjs # 进入文件夹
npm install # 安装npm包
bun install # 或者使用bun安装# 使用标准 venv 和 requirements.txt
cd fastapi
# 创建虚拟环境
python3 -m venv venv
# 激活虚拟环境
source venv/bin/activate
# 安装依赖
pip install -r requirements.txt
# 使用 uv 进行项目管理
cd fastapi
# 配置 uv 虚拟环境
uv venv --python /usr/bin/python3.11 # 创建虚拟环境时指定 Python
# 激活虚拟环境
source .venv/bin/activate
# 同步依赖(可以使用国内镜像)
uv sync项目使用 uv 进行依赖管理,配置文件为
pyproject.toml。镜像源配置在~/.config/uv/uv.toml,内容如下
[[index]]
name = "aliyun"
url = "https://mirrors.aliyun.com/pypi/simple"
default = true
为了简化项目初始化过程,我们提供了自动化配置脚本 scripts/setup.sh,可以自动检测环境、安装依赖并配置所有模块。
# 1. 使用便捷脚本调用(推荐)
./mix setup
# 或直接调用
./scripts/setup.sh运行脚本后会出现以下交互界面:
# 根据提示选择要配置的模块
# 选项:
# 1) Spring - 配置 SpringBoot 服务
# 2) GoZero - 配置 GoZero 服务
# 3) NestJS - 配置 NestJS 服务
# 4) FastAPI - 配置 FastAPI 服务
# 5) 全部 - 配置所有模块-
环境检查
- 自动检测 Python、Go、Java、Node.js 等必要工具的安装状态和版本
- 如果缺少必要工具会给出明确提示
-
系统依赖管理(仅 FastAPI 模块需要)
- 自动检测并安装 PostgreSQL 开发库(
libpq-dev) - 自动安装编译工具(
build-essential、python3-dev) - 支持多种 Linux 发行版(Ubuntu/Debian、CentOS/RHEL、Fedora、Arch)
- 自动检测并安装 PostgreSQL 开发库(
-
模块化安装
- 支持选择性安装特定模块或全部安装
- 每个模块独立配置,互不影响
-
智能判断
- Spring: 自动检测是否有全局 Gradle 和 Maven,优先使用 Gradle(若两者都存在);同时安装两者的依赖以确保完整性
- Gateway: 支持 Gradle 和 Maven 两种构建工具
- GoZero: 自动安装 goctl(API/ORM 代码生成工具、API-First 方式代码生成和 Swagger 文档生成工具)
- FastAPI: 自动安装 uv 并自动创建 uv 虚拟环境并使用阿里镜像源加速安装
- 目录自动创建
- 自动创建 logs 目录(spring、gozero、nestjs、fastapi)
- 自动创建 static 目录(pic、excel、word)
./mix setup执行后将按以下流程进行:
- 检测操作系统 - 识别当前 Linux 发行版
- 检查环境 - 验证必要工具(Python、Go、Java、Node.js、npm)
- 创建目录 - 自动创建日志和静态文件目录
- 选择模块 - 交互式选择要配置的模块
- 安装依赖 - 根据选择自动安装各模块依赖
- 完成提示 - 显示后续配置步骤
- 首次运行: 建议首次配置时选择"全部"选项,确保所有依赖都正确安装
- 系统权限: 安装系统依赖时可能需要 sudo 权限
- 网络要求:
- Go 模块需要访问 GitHub 和 Go 代理
- Python 使用 uv 配置项目环境,使用阿里镜像源,国内访问速度较快
- npm 使用默认源,建议配置国内镜像(如淘宝镜像)
- 虚拟环境: FastAPI 会使用 uv 自动创建虚拟环境(venv),无需手动创建
脚本执行完成后,还需要:
- 配置各服务的环境变量文件(见下方"配置文件说明"章节,先参考
.env.example生成本地.env,Docker 则使用.env.docker) - 启动基础服务(MySQL、Redis、MongoDB、ElasticSearch、RabbitMQ、Nacos)
- 使用运行脚本启动服务(见"运行脚本配置"章节)
项目提供了基础依赖容器部署脚本,用于快速创建和管理 MySQL、PostgreSQL、Redis、MongoDB、ElasticSearch、Nacos、RabbitMQ 和 Neo4j 等服务,供下方微服务部署使用。
mix docker-services 用于创建、启动、查看和清理基础中间件容器;下面的 Docker 容器部署 章节才是应用服务编排内容。
# 创建所有容器
./mix docker-services up
# 查看容器状态
./mix docker-services status
# 查看容器日志
./mix docker-services logs <service>
# 停止所有容器
./mix docker-services stop
# 删除所有容器
./mix docker-services delete
# 显示帮助信息
./mix docker-services help脚本会自动创建以下 Docker 容器(密码均为默认值,可通过 .env 文件自定义):
| 服务 | 端口 | 用户名 | 默认密码 | 说明 |
|---|---|---|---|---|
| MySQL | 3306 | root | 123456 | 关系型数据库 |
| PostgreSQL | 5432 | postgres | 123456 | 向量数据库(含 pgvector) |
| Redis | 6379 | - | 123456 | 缓存服务 |
| MongoDB | 27017 | root | 123456 | 非关系型数据库 |
| ClickHouse | 8123, 9002 | hcsy | 123456 | 大数据分析数据库 |
| ElasticSearch | 9200, 9300 | - | - | 搜索引擎(7.12.1) |
| Nacos | 8848, 9848 | - | - | 服务发现与配置中心 |
| RabbitMQ | 5672, 15672 | hcsy | 123456 | 消息队列(管理界面 15672) |
| Neo4j | 7474, 7687 | neo4j | 12345678 | 知识图谱数据库 |
所有容器密码均支持通过项目根目录 .env 文件自定义,脚本会优先读取 .env 中的变量,未设置时使用默认值:
# .env 文件示例
DB_PASSWORD=你的数据库密码 # MySQL 和 PostgreSQL 密码
REDIS_PASSWORD=你的Redis密码 # Redis 密码
MONGO_PASSWORD=你的MongoDB密码 # MongoDB 密码
CLICKHOUSE_USER=hcsy # ClickHouse 用户名
CLICKHOUSE_PASSWORD=你的密码 # ClickHouse 密码
RABBITMQ_USER=hcsy # RabbitMQ 用户名
RABBITMQ_PASSWORD=你的密码 # RabbitMQ 密码
NEO4J_PASSWORD=你的Neo4j密码 # Neo4j 密码| 服务 | 宿主机目录 |
|---|---|
| MySQL | ~/mysql/data, ~/mysql/conf, ~/mysql/init |
| PostgreSQL | ~/pgdata |
| Redis | ~/redis_data |
| MongoDB | ~/mongo_data |
| ClickHouse | ~/clickhouse/data, ~/clickhouse/logs |
| ElasticSearch | Docker Volume:es-data, es-plugins |
| RabbitMQ | Docker Volume:mq-plugins |
| Neo4j | ~/neo4j/data, ~/neo4j/conf, ~/neo4j/logs, ~/neo4j/import |
- 首次创建: 首次执行
docker-services up时会自动创建 Docker 网络hcsy和所有数据持久化目录 - 数据持久化: 所有容器的数据都会持久化到宿主机目录
- 密码配置: 建议在
.env文件中统一配置密码,避免使用默认密码 - ElasticSearch: 首次创建后会提示是否安装 IK 分词器(可选)
- ClickHouse: 端口 9002 映射到容器内 9000(避免与其他服务冲突),需设置
ulimit nofile=262144 - Nacos: 自动生成
nacos/custom.env配置文件,MySQL 密码与DB_PASSWORD同步 - 权限问题: 如果遇到权限错误,可能需要使用
sudo或将用户加入 docker 组 - Neo4j: 默认用户为
neo4j,默认密码为12345678,Browser 地址为http://localhost:7474,Bolt 地址为bolt://localhost:7687 - 如果有额外创建的组件,按照个人的配置改动配置文件
每个服务都可以独立运行:
使用 Maven 运行:
# 运行Spring服务
cd spring
mvn clean install # 构建项目
mvn spring-boot:run # 启动项目
# 运行网关服务
cd gateway
mvn clean install # 构建项目
mvn spring-boot:run # 启动项目使用 Gradle 运行(推荐):
# 运行Spring服务
cd spring
gradle bootRun # 启动项目
# 网关服务
cd gateway
gradle bootRun # 启动项目# 运行 GoZero 服务
cd gozero/app
go build -o bin/gozero main.go # 构建项目
go run main.go # 运行项目使用 npm 运行:
# 运行NestJS服务
cd nestjs
npm run node:start # npm development 模式运行
npm run node:start:dev # npm watch 模式运行
npm run node:start:debug # npm debug 模式运行
npm run node:start:prod # npm production 模式运行使用 bun 运行:
cd nestjs
npm run bun:start # bun 运行
npm run bun:dev # bun watch 模式运行
npm run bun:prod # bun production 模式运行使用 venv 运行:
# 运行FastAPI服务
cd fastapi
source venv/bin/activate # 激活虚拟环境
python main.py使用 uv 运行:
# 运行FastAPI服务
cd fastapi
uv run python main.py
# 或指定 Python 版本
uv run --python 3.12 python main.py本项目按服务拆分测试代码,各服务的测试入口和运行方式如下。
- Spring
cd spring
mvn test只运行某个测试:
export INTERNAL_TOKEN_TEST_TOKEN=实际Token
cd spring
mvn -Dtest=InternalTokenUtilTest test- GoZero
cd gozero/app
go test ./...只运行某个测试:
export INTERNAL_TOKEN_TEST_TOKEN=实际Token
cd gozero/app
go test ./common/utils -run 'TestGenerateInternalToken|TestValidateInternalToken' -v- NestJS
cd nestjs
npm test只运行某个测试:
export INTERNAL_TOKEN_TEST_TOKEN=实际Token
cd nestjs
npx jest src/common/utils/internalToken.util.spec.ts- FastAPI
cd fastapi
pytest只运行某个测试:
export INTERNAL_TOKEN_TEST_TOKEN=实际Token
cd fastapi
pytest tests/core/auth/test_internal_token.py- Spring:测试文件放在
spring/src/test/java下,命名建议使用*Test.java。 - GoZero:测试文件放在同包目录下,命名使用
_test.go,测试函数使用TestXxx。 - NestJS:测试文件放在
nestjs/src下,命名使用*.spec.ts,默认使用 Jest。 - FastAPI:测试文件放在
fastapi/tests下,命名使用test_*.py,默认使用 pytest。 - 其他说明:生成测试参数可以写死在代码中,但是敏感信息的参数建议使用环境变量提供。
所有运行脚本已组织到 scripts/ 目录中,便于项目管理和维护。
# 查看帮助信息
./mix help
# ===== 开发环境 =====
# 使用多窗格 tmux 布局启动所有服务(推荐用于开发调试)
./mix multi
# 使用顺序窗口模式启动所有服务
./mix seq
# 停止所有 tmux 服务
./mix stop
# ===== Seq 模式下使用指定构建工具启动服务 =====
# 使用 Gradle 构建并启动 Java 服务(推荐,更快)
./mix seq --java-build gradle
# 使用 Maven 构建并启动 Java 服务
./mix seq --java-build maven
# 使用 Bun 启动 NestJS 服务(推荐,比 npm 快)
./mix seq --node-runtime bun
# 使用 npm 启动 NestJS 服务
./mix seq --node-runtime npm
# 使用 UV 启动 FastAPI 服务(推荐,比 python 快)
./mix seq --python-runtime uv
# 使用 Python 启动 FastAPI 服务
./mix seq --python-runtime python
# 交互式模式:让用户选择构建工具
./mix seq -i
# ===== GoZero 代码生成 =====
# 生成 GoZero API 代码(默认使用 gozero/template/goctl 模板)
./mix goctl-api
# 生成 API 代码并同步生成 Swagger/OpenAPI
./mix goctl-api -s
# ORM 默认是 dry-run,只打印将要执行的 goctl 命令
./mix goctl-orm
# 真正生成 ORM 代码
./mix goctl-orm -s
# 真正生成 ORM,并为新表生成项目 GormCrud 风格 custom model
./mix goctl-orm -s --gorm
# 只生成指定 SQL 文件
./mix goctl-orm -s --gorm -pattern user.sql
# ===== Docker 容器环境 =====
# 构建并启动所有微服务容器
./mix docker up
# 构建并启动特定服务容器
./mix docker up spring gozero
# 仅构建镜像
./mix docker build
# 推送所有镜像到远程仓库
./mix docker push --prefix docker.io/yourname
# 推送指定服务镜像到远程仓库
./mix docker push --prefix registry.example.com/team --tag v1.0.0 spring gozero
# 查看容器状态
./mix docker status
# 查看容器日志
./mix docker logs spring
# 停止所有容器
./mix docker stop
# ===== 生产环境 =====
# 构建所有服务到 dist/ 目录
./mix build
# 启动所有已构建的服务(后台运行)
./mix start
# 启动指定的服务
./mix start spring gateway
./mix start fastapi gozero
# 查看已构建服务的运行状态
./mix status
# 查看指定服务的运行状态
./mix status spring gozero
# 重启所有已构建的服务
./mix restart
# 重启指定的服务
./mix restart fastapi
./mix restart spring gateway nestjs
# 停止所有已构建的服务
./mix stop-dist
# 停止指定的服务
./mix stop-dist spring fastapi
# 查看服务的最新日志(只支持查看单个服务)
./mix logs spring
./mix logs fastapi
./mix logs gozero构建工具参数说明:
-
--java-build gradle|maven:选择 Java 构建工具(Spring/Gateway)gradle:使用 Gradle(推荐,更快)maven:使用 Maven(可选)- 默认值:
gradle(如果已安装)
-
--node-runtime bun|npm:选择 Node.js 运行时(NestJS)bun:使用 Bun(推荐,比 npm 快 4-8 倍)npm:使用 npm(可选)- 默认值:
bun(如果已安装)
-
--python-runtime uv|python:选择 Python 运行时(FastAPI)uv:使用 UV(推荐,更快且支持虚拟环境)python:使用原生 Python(可选)- 默认值:
uv(如果已安装)
-
-i/--interactive:交互式模式,让用户选择每个服务的工具
# 启动所有服务(PowerShell)
PowerShell -ExecutionPolicy Bypass -File .\scripts\run.ps1如果需要直接调用 scripts/ 目录下的脚本:
# 启动服务(多窗格布局) - 使用 Gradle 构建
./scripts/run_multi.sh
# 或指定构建工具参数(推荐)
./scripts/run.sh --java-build gradle --node-runtime bun --python-runtime uv
# 启动服务(顺序窗口布局)
./scripts/run.sh
# 交互式选择工具
./scripts/run.sh -i
# 停止所有服务
./scripts/stop.sh
# 构建所有服务
./scripts/build.sh
# 管理分布式部署的服务
# 启动所有服务或指定服务
./scripts/dist-control.sh start # 启动所有
./scripts/dist-control.sh start spring gozero # 启动指定
# GoZero 代码生成
./scripts/goctl-api-init.sh
./scripts/goctl-orm-init.sh
# 参数会透传给 gozero/script/goctl 下的实际生成脚本
./scripts/goctl-api-init.sh -s
./scripts/goctl-orm-init.sh -s --gorm -pattern user.sql
# 停止所有服务或指定服务
./scripts/dist-control.sh stop # 停止所有
./scripts/dist-control.sh stop fastapi # 停止指定
# 查看所有服务状态或指定服务状态
./scripts/dist-control.sh status # 查看所有
./scripts/dist-control.sh status spring # 查看指定
# 重启所有服务或指定服务
./scripts/dist-control.sh restart # 重启所有
./scripts/dist-control.sh restart nestjs # 重启指定
# 查看单个服务的最新日志
./scripts/dist-control.sh logs spring
./scripts/dist-control.sh logs fastapirun.sh 脚本参数:
| 参数 | 选项 | 说明 |
|---|---|---|
--java-build |
gradle / maven |
Java 项目构建工具(Spring/Gateway),默认 gradle |
--node-runtime |
bun / npm |
Node.js 运行时(NestJS),默认 bun |
--python-runtime |
uv / python |
Python 运行时(FastAPI),默认 uv |
-i / --interactive |
无 | 交互式模式,提示用户选择各服务的工具 |
-h / --help |
无 | 显示帮助信息 |
示例:
# 使用 Maven 和 npm 启动
./scripts/run.sh --java-build maven --node-runtime npm
# 使用 Python 启动 FastAPI
./scripts/run.sh --python-runtime python
# 交互式选择
./scripts/run.sh --interactive# 启动所有服务
.\scripts\run.ps1| 脚本 | 位置 | 功能 | 适用系统 |
|---|---|---|---|
mix |
项目根目录 | 便捷启动器,用于快速调用 scripts/ 下的脚本 | Linux/macOS |
run_multi.sh |
scripts/ | 使用 tmux 多窗格布局启动所有服务(推荐) | Linux/macOS |
run.sh |
scripts/ | 使用 tmux 顺序窗口模式启动所有服务 | Linux/macOS |
stop.sh |
scripts/ | 停止所有 tmux 服务 | Linux/macOS |
build.sh |
scripts/ | 编译所有服务到 dist/ 目录 | Linux/macOS |
dist-control.sh |
scripts/ | 管理打包后的分布式服务(支持服务指定) | Linux/macOS |
docker-services.sh |
scripts/ | 创建、启动、停止和清理基础中间件容器 | Linux/macOS |
docker-compose-up.sh |
scripts/ | 使用 Docker Compose 启动应用服务 | Linux/macOS |
docker-compose-down.sh |
scripts/ | 使用 Docker Compose 停止应用服务 | Linux/macOS |
build_and_run_services.sh |
scripts/ | 构建并运行服务容器 | Linux/macOS |
docker-push-images.sh |
scripts/ | 将已构建的 Docker 镜像推送到远程仓库 | Linux/macOS |
setup.sh |
scripts/ | 环境初始化和依赖安装 | Linux/macOS |
swag-init.sh |
scripts/ | 生成 GoZero Swagger 文档 | Linux/macOS |
goctl-api-init.sh |
scripts/ | 生成 GoZero API 代码,参数透传给 genApi.sh |
Linux/macOS |
goctl-orm-init.sh |
scripts/ | 生成 GoZero ORM 代码,参数透传给 genOrm.sh |
Linux/macOS |
run.ps1 |
scripts/ | PowerShell 脚本,启动所有服务 | Windows |
dist-control.sh 和 mix 支持以下服务名称:
spring- SpringBoot 服务gateway- Spring Cloud Gateway 网关服务fastapi- FastAPI 服务gozero- GoZero 服务nestjs- NestJS 服务
如不指定服务名称,则对所有服务进行操作。
- tmux 依赖:Linux/macOS 脚本依赖
tmux,请确保已安装 - 执行权限:Linux/macOS 脚本需要执行权限,可以通过
chmod +x scripts/*.sh来设置 - 相对路径:所有脚本都使用相对路径,可以在任何目录下调用项目的脚本
- 服务依赖:启动前请确保 MySQL、Redis、MongoDB、ElasticSearch、RabbitMQ、Nacos 等基础服务已运行
- logs 命令:仅支持查看单个服务的日志,如需查看多个服务请依次调用
本项目提供了统一的打包和部署脚本,可以一键打包所有微服务并统一管理。
方法一:使用便捷脚本
# 1. 一键打包所有服务
./mix build
# 2. 启动所有服务
./mix start
# 3. 查看服务状态
./mix status
# 4. 重启所有服务(代码更新后)
./mix restart
# 5. 停止所有服务
./mix stop-dist方法二:直接调用脚本
# 1. 一键打包所有服务
./scripts/build.sh
# 2. 启动所有服务
./scripts/dist-control.sh start
# 3. 查看服务状态
./scripts/dist-control.sh status
# 4. 重启所有服务
./scripts/dist-control.sh restart
# 5. 停止所有服务
./scripts/dist-control.sh stop打包后的文件统一位于 dist/ 目录,每个服务都包含配置文件、启动/停止脚本和日志文件。
-
mix(项目根目录)
- 便捷启动器,用于快速调用
scripts/下的脚本 - 支持开发环境和生产环境命令
- 便捷启动器,用于快速调用
-
scripts/build.sh
- 编译所有服务:Spring、Gateway、FastAPI、GoZero、NestJS
- 将编译结果打包到
dist/目录 - 包含编译错误检查和日志输出
-
scripts/dist-control.sh
- 管理打包后的分布式服务
- 支持的操作:
start、stop、status、restart、logs
项目提供了完整的 Docker 支持,可以为每个微服务构建镜像并创建容器。
# 1. 构建并启动所有微服务容器
./mix docker up
# 2. 查看容器状态
./mix docker status
# 3. 查看特定服务的日志
./mix docker logs spring
# 4. 停止所有微服务容器
./mix docker stopDocker 环境会优先读取每个服务目录下的 .env.docker,不会自动创建该文件。请根据需要手动准备 Docker 专用环境变量文件,本地开发仍然使用 .env。
Docker 启动时会把所有应用容器接入同一个 hcsy 网络,容器间地址请使用服务名:
gateway->8080spring->8081gozero->8082nestjs->8083fastapi->8084
基础组件在同一网络中的服务名为:
mysqlredismongodbesnacosmqpgvector-dbclickhouse
| 服务 | 端口 | 镜像名称 | 容器名称 | 技术栈 |
|---|---|---|---|---|
| Gateway | 8080 | mix-gateway:latest |
mix-gateway-container |
Java 17 + Alpine |
| Spring | 8081 | mix-spring:latest |
mix-spring-container |
Java 17 + Alpine |
| GoZero | 8082 | mix-gozero:latest |
mix-gozero-container |
Go 1.23 + Alpine |
| NestJS | 8083 | mix-nestjs:latest |
mix-nestjs-container |
Node 20 + Alpine |
| FastAPI | 8084 | mix-fastapi:latest |
mix-fastapi-container |
Python 3.12 |
# 仅构建特定服务的镜像
./mix docker build spring gozero
# 仅构建镜像,不启动容器
./scripts/build_and_run_services.sh --build-only
# 手动启动容器时指定配置文件
docker run -d --name mix-spring-custom \
--network hcsy \
-p 8081:8081 \
-v $(pwd)/spring/application.yaml:/app/application.yaml \
-v $(pwd)/spring/application-secret.yaml:/app/application-secret.yaml \
mix-spring:latest
# 查看容器日志
docker logs -f mix-spring-container
# 进入容器交互式终端
docker exec -it mix-spring-container bash
# 重启容器(应用新配置)
docker restart mix-spring-container目前 docker-compose.yml 仅包含 5 个应用服务:
- gateway
- spring
- gozero
- nestjs
- fastapi
第三方依赖(MySQL/Redis/MongoDB/ES/Nacos/RabbitMQ/ClickHouse/Neo4j)请继续使用现有启动脚本(如 ./scripts/docker-services.sh),并确保它们与同一 Docker 网络 hcsy 运行。
应用容器镜像将由 ./mix docker build 生成:
./mix docker build gateway spring gozero nestjs fastapi为了与 mix docker 启动一致,docker-compose 会挂载以下配置与日志目录:
spring/application.yaml -> /app/application.yamlgozero/etc -> /app/etcnestjs/application.yaml -> /app/application.yamlfastapi/application.yaml -> /app/application.yamllogs/<service> -> /app/logs/<service>static/pic,static/excel,static/upload
./scripts/docker-compose-up.sh 已自动创建目录并设置可写权限,避免 ENOENT application.yaml 与 permission denied 问题。
建议先构建镜像,再启动 Compose。
- Docker:>= 20.10
- docker-compose:或使用
docker compose(Docker CLI 集成)
# 启动依赖服务(如果尚未启动)
./scripts/docker-services.sh
# 启动应用服务(5 个)
./mix compose up./mix compose down./mix compose status./mix compose logs <service>docker-compose up -d --build
docker-compose down -vdocker-compose.yml:整套应用编排(数据库、缓存、消息队列、服务容器)scripts/docker-compose-up.sh:快速启动脚本scripts/docker-compose-down.sh:快速停止脚本scripts/docker-services.sh:创建和管理基础中间件容器scripts/build_and_run_services.sh:构建并运行服务容器
服务启动后可直接访问本地端口:
- Gateway: http://localhost:8080
- Spring: http://localhost:8081
- GoZero: http://localhost:8082
- NestJS: http://localhost:8083
- FastAPI: http://localhost:8084
# 查看某个服务实时日志
./mix compose logs spring
# 查看所有服务状态
./mix compose status
# 重启某个服务(可配合 docker-compose restart)
cd /home/hongch666/mix-web-demo
sudo docker-compose -f docker-compose.yml restart spring
# 进入容器调试
sudo docker exec -it mix-spring /bin/bash
# 清理未用镜像与容器
docker system prune -af- MySQL
- PostgreSQL
- 需要安装
pgvector插件
- 需要安装
- MongoDB
- Redis
- ElasticSearch
- RabbitMQ
- Nacos
- Neo4j
项目的 SQL 初始化脚本已经统一迁移到根目录的 db/ 目录下,按数据库类型拆分管理。
db/mysql/:MySQL 建表脚本,按表拆分为独立文件db/postgresql/:PostgreSQL 初始化脚本,主要用于扩展启用db/clickhouse/:ClickHouse 初始化脚本,主要用于映射库和物化视图db/mongodb/:MongoDB 初始化脚本,主要用于集合和索引创建db/es/:Elasticsearch 初始化脚本,主要用于索引和映射创建db/neo4j/:Neo4j 初始化脚本,主要用于创建唯一约束
如果后续新增数据库初始化内容,也请继续放到 db/ 下对应的数据库目录中,便于统一维护和查找
系统服务会自动创建,也可以先执行 db/mysql/ 下的SQL脚步创建数据库和基础表结构
LangChain 会自动创建,但需要先执行 db/postgresql/extensions.sql 启用 pgvector 扩展,并且执行 db/postgresql/init.sql创建对应数据库
数据库为 demo,集合为 articlelogs 和 apilogs,系统会自动创建;如需手动初始化,可执行 db/mongodb/init.js
索引名为 articles,系统同步数据时会自动创建;如需手动初始化,可执行 db/es/init.json
需要先执行 db/clickhouse/init.sql,其中包含 MySQL 映射库、本地表和物化视图的创建语句,MySQL 映射库需要修改为实际的 MySQL 连接信息
Neo4j 用于知识图谱,默认数据库无需额外指定
FastAPI 的同步任务会自动创建约束并将 MySQL 业务数据同步为图结构。
可在 Neo4j Browser 中手动执行初始化脚本 init.cypher,也可以在首次执行同步任务时自动创建约束
本项目按环境拆分配置文件:
.env.example:示例文件,保留全部变量名,用于复制生成本地配置.env:本地开发使用的真实配置文件,不建议提交敏感值.env.docker:Docker 容器使用的环境变量文件,脚本会在容器启动时读取它
所有配置值通过 ${VAR_NAME:default_value} 的格式在 YAML 文件中引用。
各服务的具体环境变量请直接参考对应的 .env.example,这里不再重复列出完整配置。
- Spring:
spring/.env.example、spring/.env.docker - GoZero:
gozero/app/.env.example、gozero/app/.env.docker - NestJS:
nestjs/.env.example、nestjs/.env.docker - FastAPI:
fastapi/.env.example、fastapi/.env.docker - Gateway:
gateway/.env.example、gateway/.env.docker
使用方式保持一致:
- 先复制
.env.example为本地.env - 再按实际环境填写真实值
- Docker 场景单独维护
.env.docker
-
密钥管理: 所有密钥信息(数据库密码、API KEY、JWT Secret 等)不应该提交到版本控制系统,应该在本地
.env文件中配置 -
示例文件: 新克隆项目后,先复制对应服务的
.env.example为.env,再填写真实值 -
Docker 文件: Docker 运行时读取
.env.docker,如果需要修改容器环境变量,请单独维护该文件,不要复用本地.env -
YAML 中的引用格式: 在各服务的
application.yaml配置文件中,使用以下格式引用环境变量:# YAML 中的使用示例 server: port: ${SERVER_PORT:8080} database: host: ${DB_HOST:localhost} password: ${DB_PASSWORD:default-password}
-
默认值: 格式
${VAR_NAME:default_value}中,冒号后面是默认值,当环境变量未设置时使用默认值 -
加载顺序: 本地启动时会自动从
.env文件加载环境变量,Docker 启动时会读取.env.docker,然后再解析 YAML 配置文件 -
JWT 密钥说明: 系统环境变量设置的 JWT 密钥至少为 32 位字符串
启动时会显示对应的 swagger 地址
- 在 config 包下的
SwaggerConfig.java中修改对应 Swagger 信息 - 使用
@Operation(summary = "spring自己的测试", description = "输出欢迎信息")设置对应接口 - 在
http://[ip和端口]/swagger-ui/index.html访问 Swagger 接口
本项目已采用 API-First 方式管理 Swagger 文档,所有 API 定义统一存放在 .api 文件中,使用 goctl 的内置 Swagger 生成工具自动生成文档。
使用方式:
-
在
gozero/api目录下对应的.api文件中使用@doc注释定义 API@doc( summary: "获取用户列表" description: "获取所有用户信息" ) get /users returns (UserListResp) -
在
gozero/app/main.go启动时会自动提供 Swagger UI- Swagger UI:
http://[ip和端口]:8082/swagger/index.html
- Swagger UI:
-
每次修改
.api文件后,运行以下命令重新生成 Swagger 文档:# 使用快捷方式 ./mix swag # 或直接调用脚本 cd gozero && bash script/swagger/genSwagger.sh
-
生成的 Swagger 文件位于
gozero/app/docs/目录 -
目前 Swagger 文档的描述、作者、版本信息和中文分组等相关 Swagger 内容存在问题,使用
/script/swager/fix.py脚本进行修复,修复后会覆盖原来的 Swagger 文件,如有需要可修改fix.py脚本中的相关内容
- 在
main.ts中修改对应 Swagger 信息 - 使用
@ApiOperation({ summary: '获取用户信息', description: '获取用户信息列表' })设置对应接口 - 在
http://[ip和端口]/api-docs访问 Swagger 接口
-
在
main.py中通过FastAPI的参数自定义全局 Swagger 信息,例如:app = FastAPI( title="FastAPI部分的Swagger文档集成", description="这是demo项目的FastAPI部分的Swagger文档集成", version="1.0.0" )
-
单个接口的描述可以通过路由装饰器的
description参数或函数 docstring 设置,例如:@router.get( "/fastapi", summary="这是接口简介", description="这是接口描述" ) def hello(): """ 这是接口的详细说明 """ return {"msg": "hello"}
-
启动 FastAPI 服务后,访问
http://[ip和端口]/docs查看 Swagger UI,或访问http://[ip和端口]/redoc查看 ReDoc 文档。
这个为当前项目的代码和文件等相关规范,建议遵守
- Spring 项目采用通用的三层架构,
/controller为对应接口,/service为对应实际逻辑(使用接口+实现形式),/mapper为对应数据库操作,并且使用依赖注入进行调用 - GoZero 项目采用通用的三层架构,
/handler为对应接口,/logic为对应实际逻辑,/model为对应数据库操作,并且使用svc依赖注入进行调用 - NestJS 项目采用默认的 module 划分格式,每个 module 有对应的
xxx.controller.ts、xxx.service.ts、xxx.module.ts文件,/dto、/entities、/schema放置对应的 DTO 类、数据库实体类、Mongoose 实体类,并且使用依赖注入进行调用 - FastAPI 项目采用官方推荐的目录结构,在app下实现代码,
api路由接口,services服务逻辑,crud为对应数据库操作,core放置核心功能模块,并且基于Depend函数和获取实例函数进行依赖注入调用
- Spring 项目将三层架构代码放置在
/api文件夹下,通用模块放置在/common文件夹下,注解和配置相关放置在/core文件夹下,基础设施相关放置在/infra文件夹下,和实体相关的模块放在/entity下,如/dto、/vo、/po - GoZero 项目将
.api设计文件放置在/api文件夹下,脚本放置在/scripts文件夹下,生成的代码放置在/app文件夹下,/app下采用GoZero的设计方式,/model下放置数据库实体和操作,/common下放置通用代码模块,/internal下放置业务相关的代码模块,/etc下放配置文件,/internal文件夹下按照/handler、/logic等GoZero的设计方式进行划分 - NestJS 项目的通用工具放置在
/common下,module 相关的工具模块放置在/modules下,接口相关的模块放置在/api下,和系统相关的模块放置在/framework下,如filters、guards、interceptors等 - FastAPI 项目的核心代码放置在
/app下,api下放置路由接口,services下放置服务逻辑,crud下放置数据库操作,core下放置核心功能模块,/models下放置实体相关的模块,/schemas下放置 Pydantic 模型 - 其他相关的文件夹命名尽可能沿用当前项目的设计
- Spring 项目采用驼峰命名方式,如
UserCreateDTO.java - GoZero 项目采用驼峰命名方式,如
userCreateDTO.go - NestJS 项目采用点号命名和驼峰命名混合使用的方式,驼峰命名区分模块名,点号区分功能,如
userCreate.dto.ts - FastAPI 项目采用驼峰命名方式,如
userCreateDTO.py
所有接口统一返回 application/json 格式,结构如下:
{
"code": 200,
"msg": "success",
"data": null
}| 字段 | 类型 | 说明 |
|---|---|---|
| code | int | 3 位 HTTP 状态码,与 HTTP 响应状态码一致 |
| msg | string | 描述信息/错误信息 |
| data | any | 业务数据,成功时返回,失败或无数据返回时为 null |
核心规则:
code= HTTP 响应状态码,不再统一返回 200- 成功时
code= 200,msg= "success" - 失败时
code为对应的 HTTP 状态码(如 400/401/403/404/409/422/429/500/502/503/504),msg为具体错误描述 - 成功时除查询接口和部分状态管理外,其他接口
data返回null - 失败时
data统一返回null - 不再有
error、timestamp、trace、path、requestId等额外字段
- Spring 项目使用全局异常处理类
GlobalExceptionHandler.java进行异常捕获和处理,业务异常统一抛出BusinessException异常 - GoZero 项目使用中间件
recoveryMiddleware.go进行异常捕获和处理,业务异常统一抛出BusinessError异常 - NestJS 项目使用全局异常过滤器
all-exceptions.filter.ts进行异常捕获和处理,业务异常统一抛出BusinessException异常 - FastAPI 项目使用
exceptionHandlers.py下的全局异常处理函数进行异常捕获和处理,业务异常统一抛出BusinessException异常
- Spring 项目使用
common/utils/Constants.java进行常量类管理,包括相关字符串和数字常量 - GoZero 项目使用
common/utils/constants.go进行常量管理,包括相关字符串和数字常量 - NestJS 项目使用
common/utils/constants.ts进行常量类管理,包括相关字符串和数字常量,当前模板字符串没有抽离常量 - FastAPI 项目使用
core/base/constants.py进行常量类管理,包括相关字符串和数字常量,当前模板字符串没有抽离常量
目前常量类均可根据需要进行扩展,尽可能使用常量类进行统一管理,避免硬编码。
- 统一使用 Cron 表达式的方式进行定时任务管理
- 遵循当前项目的定时任务设置方式
- 部分定时任务使用
logic封装定时任务的实际逻辑,在定时任务主文件调用logic - 定时任务建议使用分布式锁时,锁 Key 的命名规范为
lock:task:<业务>:<动作>
- FastAPI 部分使用
__init__.py文件导出对应的函数/类,导入使用的时候以包为导入路径 - FastAPI 部分需要在 app 创建时添加的相关组件(如 router、中间件、异常处理器)在
__init__.py导出对应列表或者字典,用于 app 创建时遍历添加 - FastAPI 部分的 app 创建在
app.py的create_app函数实现,lifespan 操作在lifespan.py实现,主函数只进行调用和uvicorn的启动 - GoZero 部分的初始化在
internel/boot文件夹创建,main 函数只进行调用,配置相关的初始化在svc文件夹下初始化执行 - NestJS 项目的 app 创建在
app目录下的createApp函数实现,main 函数只进行调用,app目录下包含app.module.ts的 NestJS 的包初始化 - Spring 项目的 Main 类只进行服务的启动,相关配置或初始化行为在
config目录下使用@Configuration注解实现
- Spring 项目使用
@ApiLog注解 +ApiLogAspect进行请求日志记录,并将日志发送到 RabbitMQ
- 机制: AOP 环绕切面获取请求方法/路径/参数,记录耗时并组装日志消息,最终写入日志并投递队列
- GoZero 项目使用
apiLogMiddleware中间件记录请求参数、路径、耗时,并发送 API 日志到 RabbitMQ,在handler中使用ApplyApiLog函数启用日志记录
- 机制: 中间件读取请求上下文与请求体,计算耗时并发送日志消息到队列
- NestJS 项目使用
@ApiLog装饰器 +ApiLogInterceptor记录日志并发送到消息队列
- 机制: 通过 Reflector 读取装饰器元数据,拦截请求提取参数与耗时,调用 MQ 服务发送日志
- FastAPI 项目使用
@log装饰器(支持ApiLogConfig)记录请求日志,耗时统计并发送到 RabbitMQ
- 机制: 装饰器从
Request提取方法/路径/参数,统计耗时,必要时包装流式响应并投递日志
- Spring 项目使用
@RequirePermission注解 +PermissionValidationAspect,支持角色校验、allowSelf、自定义业务类型与参数来源
- 机制: 切面从
UserContext取用户信息,解析路径/请求体参数,按业务类型与参数来源判断权限
- GoZero 项目暂无通用权限注解,中间件
InjectUserContext仅负责注入用户信息,权限校验主要在业务层处理
- 机制: 中间件只把
X-User-Id/X-Username注入到上下文,具体权限由 service/handler 自行校验
- NestJS 项目使用
@RequireAdmin装饰器 +RequireAdminGuard进行管理员权限校验
- 机制: Guard 读取装饰器元数据与 CLS 用户信息,调用用户服务判断是否管理员
- FastAPI 项目使用
@require_admin装饰器进行管理员权限校验
- 机制: 装饰器读取当前用户 ID 并查询用户角色,不满足条件抛出业务异常
- Spring 项目使用
@RequireInternalToken注解 +InternalTokenAspect校验X-Internal-Token,并通过 FeignDefaultHeaderInterceptor自动注入内部令牌
- 机制: Feign 拦截器生成内部 JWT 并写入请求头,切面解析并校验令牌及服务名称
- GoZero 项目使用
InternalTokenMiddleware校验内部令牌,支持验证指定服务名称
- 机制: 中间件从请求头读取 JWT,校验签名/过期/服务名,失败直接中断请求
- NestJS 项目使用
@RequireInternalToken装饰器 +InternalTokenGuard校验内部服务令牌
- 机制: Guard 从请求头提取 JWT,验证并检查指定服务名匹配
- FastAPI 项目使用
@requireInternalToken装饰器校验内部服务令牌,并支持指定服务名称
- 机制: 装饰器读取
X-Internal-Token,校验并将 claims 写入request.state
- Spring 项目使用 Feign 客户端
FastAPIClient/GoZeroClient/NestjsClient调用其他服务,DefaultHeaderInterceptor自动注入用户信息与内部令牌
- 机制: Feign 统一注入
X-User-Id/X-Username与内部 JWT,实现服务间安全调用
- GoZero 项目使用
ServiceDiscovery.CallService(Nacos 服务发现 + 负载均衡),自动注入用户信息与内部令牌
- 机制: 通过 Nacos 获取实例并轮询负载均衡,构建请求头后发起 HTTP 调用
- NestJS 项目使用
NacosService.call(Nacos 服务发现 + axios),自动注入用户信息与内部令牌
- 机制: Nacos 发现实例,自动拼装请求头并用 axios 请求下游服务
- FastAPI 项目使用
call_remote_service(Nacos 服务发现 + requests),自动注入用户信息与内部令牌
- 机制: 从 Nacos 获取服务实例,合并默认请求头后用 requests 发起调用
内部调用统一放到独立 client 层,client 按目标服务拆分,不按业务调用方拆分。底层通用 transport 与目标服务 client 分开存放。
核心规则:
- 存在独立的底层 transport 文件(GoZero/FastAPI/NestJS),与目标服务 client 分开存放
- 按目标服务拆分 client,不把所有调用塞进一个总 client
- client 返回完整的
{code, msg, data}响应结果,不做数据提取或响应解析 - transport 层统一校验 HTTP 状态码和业务
code是否为 200,非 200 则记录错误日志并抛出异常 - 响应数据的类型转换和解析由业务层或 client 包内的公开解析函数处理
各技术栈的 client 落位方式:
Spring
src/main/java/.../client/FastAPIClient.java # FastAPI Feign 接口
src/main/java/.../client/GoZeroClient.java # GoZero Feign 接口
src/main/java/.../client/NestjsClient.java # NestJS Feign 接口
src/main/java/.../client/fallback/ # 降级工厂目录
- Feign 接口文件使用
<TargetService>Client.java - 降级工厂放
fallback/目录
GoZero
app/common/client/client.go # 通用 transport(Nacos 发现+轮询负载均衡+熔断)
app/internal/client/fastapiClient/fastapiClient.go + type.go # FastAPI 客户端
app/internal/client/springClient/springClient.go + type.go # Spring 客户端
app/internal/client/nestjsClient/nestjsClient.go + type.go # NestJS 客户端
- 目录名
<targetService>Client/,结构体名<TargetService>Client - 每个目录内固定
<targetService>Client.go+type.go
NestJS
src/modules/client/client.module.ts # 客户端模块(统一注册并导出)
src/modules/client/springClient.service.ts # Spring 客户端
src/modules/client/gozeroClient.service.ts # GoZero 客户端
src/modules/client/fastapiClient.service.ts # FastAPI 客户端
- service 文件名
<targetService>Client.service.ts - service 类名
<TargetService>ClientService
FastAPI
app/core/client/client.py # 通用 transport(Nacos 发现+熔断+重试)
app/internal/clients/springClient.py # Spring 客户端
app/internal/clients/gozeroClient.py # GoZero 客户端
app/internal/clients/nestjsClient.py # NestJS 客户端
- 文件使用驼峰命名
<targetService>Client.py - 类名使用 PascalCase
<TargetService>Client
GoZero 代码生成统一通过根目录 mix 脚本调用,mix 会把参数透传到 scripts/goctl-api-init.sh 或 scripts/goctl-orm-init.sh,再由这两个脚本调用 gozero/script/goctl 下的实际生成脚本。
调用链如下:
./mix goctl-api [args...]
# -> scripts/goctl-api-init.sh [args...]
# -> gozero/script/goctl/genApi.sh [args...]
./mix goctl-orm [args...]
# -> scripts/goctl-orm-init.sh [args...]
# -> gozero/script/goctl/genOrm.sh [args...]项目内置 goctl 模板目录为 gozero/template/goctl,API 和 ORM 生成脚本默认都会使用该模板目录,不依赖开发机全局 goctl 模板。
常用命令:
# 生成 API 代码
./mix goctl-api
# 生成 API 代码,并同步生成 Swagger/OpenAPI
./mix goctl-api -s
# ORM dry-run,只打印将要执行的 goctl 命令
./mix goctl-orm
# 真正生成 ORM 代码
./mix goctl-orm -s
# 真正生成 ORM,并为新表生成项目 GormCrud 风格 custom model
./mix goctl-orm -s --gorm
# 只生成某一个 SQL
./mix goctl-orm -s --gorm -pattern user.sql
# 指定 SQL 目录、输出目录或模板目录
./mix goctl-orm -s --gorm -srcDir gozero/script/sql -outDir ./gozero/app/model
./mix goctl-api --template gozero/template/goctl
./mix goctl-orm -s --template gozero/template/goctl参数说明:
| 命令 | 参数 | 说明 |
|---|---|---|
goctl-api |
-s |
生成 API 代码后,同时生成 Swagger/OpenAPI |
goctl-api |
--template <path> |
指定 goctl 模板目录,默认 gozero/template/goctl |
goctl-orm |
-s |
执行生成;不加时只 dry-run 打印命令 |
goctl-orm |
--gorm |
为新表生成项目 GormCrud 风格 custom model,已有业务 model 不覆盖 |
goctl-orm |
-srcDir <path> |
指定 SQL 文件目录,默认 gozero/script/sql |
goctl-orm |
-outDir <path> |
指定 model 输出目录,默认 ./gozero/app/model |
goctl-orm |
-pattern <glob> |
指定 SQL 匹配规则,默认 *.sql |
goctl-orm |
--template <path> |
指定 goctl 模板目录,默认 gozero/template/goctl |
ORM 生成会按表名落到项目现有目录结构,例如 sub_category.sql 会生成到 gozero/app/model/subCategory。--gorm 主要用于新表初始化:它会把 goctl 默认 custom model 外壳替换成项目当前使用的 GormCrud 外壳,同时保留 *_gen.go 中由 goctl 生成的结构体和基础 SQLX 代码。
FastAPI 部分提供了基于 LangChain 的 AI Agent 工具,AI 模型可以通过这些工具进行数据查询和分析。
通过 MySQL 数据库进行数据查询和分析:
| 工具名称 | 功能 | 参数 | 说明 |
|---|---|---|---|
get_table_schema |
获取表结构 | 表名(可选) | 返回表的详细结构信息,包括列名、类型、主键、索引等;不提供表名则返回所有表的列表 |
execute_sql_query |
执行 SQL 查询 | SQL SELECT 语句 | 仅支持 SELECT 查询,自动进行用户隔离过滤,返回最多 500 行数据 |
基于 PostgreSQL + Qwen 嵌入模型的文章向量搜索:
| 工具名称 | 功能 | 参数 | 说明 |
|---|---|---|---|
search_articles |
向量语义搜索 | 问题或关键词 | 基于语义相似度搜索相关文章,返回相似度最高的 N 篇文章内容片段 |
查询系统日志和 API 调用记录:
| 工具名称 | 功能 | 参数 | 说明 |
|---|---|---|---|
list_mongodb_collections |
列出集合 | 无 | 获取 MongoDB 中所有的 collection 及其基本信息 |
query_mongodb |
通用查询 | JSON 格式查询参数 | 查询任意 collection,支持条件过滤和结果限制 |
MongoDB 查询参数格式示例:
{
"collection_name": "api_logs",
"filter_dict": { "user_id": 122, "status": { "$gte": 400 } },
"limit": 20
}基于 Neo4j 查询文章、用户、分类、标签之间的实体关系:
| 工具名称 | 功能 | 参数 | 说明 |
|---|---|---|---|
execute_knowledge_graph_query |
预定义图谱查询 | query_name、params |
查询文章详情、分类文章、作者文章、同分类相似文章、关注链推荐、热门文章、标签排行、个性化推荐 |
execute_custom_cypher_query |
自定义 Cypher 查询 | 只读 Cypher 语句 | 仅允许只读查询,用于复杂实体关系分析 |
预定义查询名称:
| 查询名称 | 说明 |
|---|---|
article_detail |
查询文章详情,包括作者、分类、标签 |
category_articles |
查询某个子分类下的热门文章 |
user_articles |
查询某个作者发布的文章 |
similar_articles_same_category |
查询同分类下的相似热门文章 |
user_interest_chain |
查询用户关注链上的兴趣文章 |
top_viewed_articles |
查询浏览量最高的文章 |
tag_graph |
查询标签关联文章数量排行 |
user_recommendation |
基于用户点赞/收藏标签做个性化推荐 |
适合触发知识图谱工具的问题示例:
知识图谱里标签关联文章最多的是哪些
查询文章 ID 为 1 的图谱详情,包括作者、分类和标签
和文章 ID 为 1 同分类的热门文章有哪些
根据知识图谱,推荐用户 ID 为 1 可能喜欢的文章
用户 ID 为 1 关注的人点赞过哪些文章
对应数据同步任务:
- 定时任务文件:
fastapi/app/internal/services/tasks/neo4jSyncTask.py - 手动触发接口:
POST /api_fastapi/task/sync-neo4j - Neo4j 客户端:
fastapi/app/core/db/neo4j.py
- 意图路由工具 (intentRouter.py): 用于自动识别用户意图并路由到不同的处理模块
- 用户权限管理 (userPermissionManager.py): 管理和校验用户权限,实现细粒度访问控制
- 需要通过Github官方OAuth Apps注册对应OAuth Apps
- 配置回调地址和前端地址为当前项目的地址(可使用localhost作为开发环境的地址)
- 获取Client ID和Client secrets并配置到环境变量
- 词云图的字体应进行配置对应字体的路径
-
Word 下载文件的模板路径在 NestJS 部分 yaml 配置文件中配置,使用
${字段名}进行模板书写,目前提供如下的示例 -
内容示例
${title} ${tags} ${content} -
PDF 下载需要使用下面指令安装
puppeteer的 Chrome 浏览器npx puppeteer browsers install chrome
-
当前 Word 下载只支持文章内容为纯文本,无法显示 Markdown 格式
- GoZero 部分的用户聊天相关模块的用户 id 都是字符串,包括数据库存储,请求参数和返回参数
- AI 服务目前只有三种,对应数据库
user表里面role为ai的用户,并且代码目前写死用户 id 为 1001/1002/1003;db/mysql/user.sql里也已补充这三条 AI 用户初始化数据,重复执行会按id跳过已有记录。
- Spring 部分的邮箱登录使用 QQ 邮箱配置发送,需单独配置 QQ 邮箱授权码。
-
GoZero 服务若使用
fresh修改热启动工具,可以在配置对应配置文件用于修改编译结果产生位置,示例如下# Fresh 热启动工具配置文件 # 将编译文件输出到系统临时目录,不污染项目目录 root=. # 输出到系统临时目录 (/tmp) 而不是项目目录 tmp_path=/tmp/fresh-runner build_name=runner-build build_path=/tmp/fresh-runner build_delay=1000 ignore_folder=assets,tmp,vendor,frontend/node_modules,logs,docs ignore_file=.DS_Store,.gitignore watch_path=. watch_ext=.go verbose=false
搜索入口由 GoZero 统一提供,默认搜索模式为 hybrid。当前搜索链路分为两层:
- ElasticSearch 负责关键词召回、过滤、高亮和基础业务排序。
- GoZero 在 ES 候选结果上按需调用 FastAPI 向量增强和 Neo4j 图谱增强,再进行最终融合重排。
GoZero 调用 ES 搜索时,ES 内部 script_score 会综合关键词相关性、内容质量、热度、作者影响力和新鲜度。
ES 候选综合评分公式如下:
其中:
-
$S_{es} = \frac{1}{1 + e^{-x}}$ (Sigmoid 归一化的 ElasticSearch 关键词相关性分数,0-1 范围) -
$S_{ai} = \frac{\text{AI评分}}{10.0}$ (0-1 范围,AI 评分范围为 0-10) -
$S_{user} = \frac{\text{用户评分}}{10.0}$ (0-1 范围,用户评分范围为 0-10) -
$S_{views} = \min\left(\frac{\text{阅读量}}{\text{maxViewsNormalized}}, 1.0\right)$ (阅读量归一化,0-1 范围) -
$S_{likes} = \min\left(\frac{\text{点赞量}}{\text{maxLikesNormalized}}, 1.0\right)$ (点赞量归一化,0-1 范围) -
$S_{collects} = \min\left(\frac{\text{收藏量}}{\text{maxCollectsNormalized}}, 1.0\right)$ (收藏量归一化,0-1 范围) -
$S_{follow} = \min\left(\frac{\text{作者关注数}}{\text{maxFollowsNormalized}}, 1.0\right)$ (作者粉丝数归一化,0-1 范围) -
$S_{recency}$ :文章新鲜度分数(基于创建时间)
文章新鲜度采用高斯衰减函数,使时间离当前越近的文章得分越高:
其中:
-
$\Delta t$ :文章创建时间与当前时间的差值(单位:天) -
$\sigma$ :时间衰减周期,默认由SEARCH_RECENCY_DECAY_DAYS=30配置
高斯衰减函数具有以下特性:
- 当
$\Delta t = 0$ (刚发布)时,$S_{\text{recency}} = 1.0$(新鲜度最高) - 当
$\Delta t = 30$ 天时,$S_{\text{recency}} \approx 0.606$(衰减至约 60.6%) - 当
$\Delta t = 60$ 天时,$S_{\text{recency}} \approx 0.135$(衰减至约 13.5%)
ES 内部权重配置说明:
| 因素 | 默认权重 | 配置项 | 说明 |
|---|---|---|---|
| ES 基础分数 | 0.25 | SEARCH_ES_SCORE_WEIGHT |
关键词匹配的基础相关性(通过 Sigmoid 归一化) |
| AI 评分 | 0.15 | SEARCH_AI_RATING_WEIGHT |
系统 AI 模型的内容质量评估(0-10 范围) |
| 用户评分 | 0.10 | SEARCH_USER_RATING_WEIGHT |
用户对文章的综合评价(0-10 范围) |
| 阅读量 | 0.08 | SEARCH_VIEWS_WEIGHT |
文章的浏览热度 |
| 点赞量 | 0.08 | SEARCH_LIKES_WEIGHT |
用户的认可度 |
| 收藏量 | 0.08 | SEARCH_COLLECTS_WEIGHT |
用户的收藏价值指数 |
| 作者关注数 | 0.04 | SEARCH_AUTHOR_FOLLOW_WEIGHT |
作者的影响力 |
| 文章新鲜度 | 0.22 | SEARCH_RECENCY_WEIGHT |
近期发布的内容获得更高排名 |
ES 内部权重总和为 1.0,确保评分结果的可比性和公平性。
ES 返回当前页候选文章后,GoZero 会对当前页候选进行二阶段增强:
- 向量增强:调用 FastAPI
/vector-search/enhance,基于 PostgreSQL + pgvector + LangChain 计算候选文章与搜索词的语义相似度,返回vectorScore、semanticReason、matchedChunks。 - 图谱增强:调用 FastAPI
/graph-search/enhance,基于 Neo4j 的用户兴趣、关注作者、同分类、候选标签相似、关键词标签命中等信号返回graphScore、reason、relations。 - 融合重排:GoZero 只对 ES 当前页候选重排,不改变
total。
融合前先对 ES 原始分做当前候选集归一化:
最终融合公式:
其中:
-
$S_{vector}$ :向量语义相似度分,范围 0-1;未命中时为 0。 -
$S_{graph}$ :图谱增强分,范围 0-1;未命中时为 0。 -
$W_{es} + W_{vector} + W_{graph} = 1$ 。 -
$W_{es}$ 不低于SEARCH_HYBRID_MIN_ES_WEIGHT,默认 0.55,保证 ES 关键词和业务排序仍是主排序来源。
默认权重:
| 融合信号 | 默认权重 | 配置项 | 说明 |
|---|---|---|---|
| ES 归一化分 | 0.55 | SEARCH_HYBRID_MIN_ES_WEIGHT |
关键词相关性、业务热度、新鲜度等综合排序基础 |
| 向量语义分 | 0.25 | SEARCH_VECTOR_SCORE_WEIGHT |
同义词、长句、自然语言问题的语义匹配 |
| 图谱增强分 | 0.20 | SEARCH_GRAPH_SCORE_WEIGHT |
用户兴趣、关注关系、标签和分类关系 |
动态调整规则:
mode=keyword:只使用 ES,W_{es}=1.0,不调用向量和图谱增强。- 未登录用户:关闭图谱权重;有关键词时向量权重可提升到 0.30,ES 保持主导。
- 已登录且有关键词:默认使用
ES 0.55 + Vector 0.25 + Graph 0.20。 - 已登录且空关键词:不启用向量增强,主要由 ES 业务排序和图谱增强承担推荐。
enableVector=false:强制关闭向量增强。enableGraph=false:强制关闭图谱增强。explain=false:保留分数字段,但清空semanticReason、matchedChunks、reason、relations等解释字段。
降级规则:
- ES 查询失败:搜索请求失败,不使用向量或图谱单独兜底,避免改变主搜索语义。
- 向量增强失败:记录 warning,保留 ES + Graph 或纯 ES 结果。
- 图谱增强失败:记录 warning,保留 ES + Vector 或纯 ES 结果。
- 向量和图谱都无结果或都失败:返回 ES 当前页原始排序,并补齐
esScore和finalScore。
本项目采用 MIT 许可证 进行开源。
MIT 许可证允许:
- 自由使用、修改和分发
- 商业和个人用途
- 专利使用
详见 LICENSE 文件