diff --git a/DEPLOY_1PANEL.md b/docs/DEPLOY_1PANEL.md similarity index 98% rename from DEPLOY_1PANEL.md rename to docs/DEPLOY_1PANEL.md index c2bf851..194e6cb 100644 --- a/DEPLOY_1PANEL.md +++ b/docs/DEPLOY_1PANEL.md @@ -404,7 +404,7 @@ docker logs --tail 200 haovp-nacos | 问题 | 处理 | | --- | --- | | `NACOS_AUTH_TOKEN` 相关报错 | 确认 `.env.1panel` 中 `NACOS_AUTH_TOKEN` 是 Base64,且解码后至少 32 字节 | -| `No DataSource set` | 先确认服务器上的 `backend/config/nacos/application-1panel.properties` 是“文件”而不是目录,再确认它被挂载到 `/home/nacos/conf/application.properties`,然后看 `haovp-nacos-init` 是否成功完成 | +| `No DataSource set` | 先确认服务器上的 `../backend/config/nacos/application-1panel.properties` 是“文件”而不是目录,再确认它被挂载到 `/home/nacos/conf/application.properties`,然后看 `haovp-nacos-init` 是否成功完成 | | 数据库连接失败 | 确认 `haovp-mysql` 正常,且 `haovp-nacos-init` 能连上 MySQL | | 业务服务短暂报 `nacos:9848 Connection refused` | Nacos 2.x 客户端会连接 `8848 + 1000 = 9848` 的 gRPC 端口。启动早期短暂失败后出现 `Success to connect a server [nacos:8848]` 即为自动恢复 | | 端口占用 | 确认宿主机 `8848` 未被其他服务占用,或修改 `NACOS_HTTP_PORT` | @@ -483,7 +483,7 @@ pull access denied for haovp/video-auth 解决方式: -1. 使用新版 `backend/docker-compose.1panel.yml`。 +1. 使用新版 `../backend/docker-compose.1panel.yml`。 2. 确认 `video-auth`、`video-user`、`video-content`、`frontend-web` 等本地构建服务只有 `build:`,没有 `image: haovp/...`。 3. 在 1Panel 中重新加载编排文件后再启动。 diff --git a/docs/Debian 12 高可用集群部署手册.md b/docs/Debian 12 高可用集群部署手册.md index 7f3abe9..85508ee 100644 --- a/docs/Debian 12 高可用集群部署手册.md +++ b/docs/Debian 12 高可用集群部署手册.md @@ -1,1110 +1,84 @@ -# Debian 12 高可用集群部署手册 +# Debian 12 多节点部署手册 -## 一、环境准备 +本文档描述仓库当前的三节点 Compose 部署。实际参数以 `backend/docker-compose-node-01.yml`、`docker-compose-node-02.yml`、`docker-compose-node-03.yml` 和 `backend/config` 为准。 -### 1.1 虚拟机配置要求 +## 节点职责 -| 节点 | IP地址 | CPU | 内存 | 磁盘 | 操作系统 | -|------|--------|-----|------|------|----------| -| Node-01 | 192.168.1.101 | 4核 | 8GB | 100GB | Debian 12 (Bookworm) | -| Node-02 | 192.168.1.102 | 4核 | 8GB | 100GB | Debian 12 (Bookworm) | -| Node-03 | 192.168.1.103 | 4核 | 8GB | 100GB | Debian 12 (Bookworm) | +默认拓扑为三台 Debian 12 主机: -### 1.2 Debian 12 安装建议 +| 节点 | 主要职责 | +| --- | --- | +| Node-01 | MySQL 主库、Redis 主节点、Nacos、RocketMQ NameServer/Broker、MinIO 业务写入点、网关和业务服务 | +| Node-02 | MySQL/Redis 从节点、Nacos、RocketMQ、MinIO 同步副本及业务服务副本 | +| Node-03 | MySQL/Redis 从节点、Nacos、RocketMQ Broker-B、MinIO 备用实例与监控 exporter | -下载地址: https://www.debian.org/distrib/ +节点 IP、网卡名和资源规格不是代码常量,部署前通过各节点环境文件设置。不要直接照抄旧文档中的密码或 IP。 -推荐使用 **Debian 12 Netinst** 最小化安装: -- 选择 "无图形界面" 安装 -- 仅安装 SSH server 和标准系统工具 -- 使用 LVM 分区,便于扩展 +## 前置条件 -### 1.3 系统初始化 +- 三节点安装 Docker Engine 和 Compose v2,时钟同步,节点间放行 Docker 网络所需端口。 +- 三节点使用相同代码版本、Nacos 认证参数、数据库密码、Redis 密码和 JWT secret。 +- Node-01 先准备 MySQL 主库和 Nacos schema;从节点不重复执行初始化 SQL。 -在每台虚拟机上执行以下操作: +## 配置 -```bash -# 切换到 root 用户 -su - - -# 上传 init-debian12.sh 脚本并执行 -chmod +x init-debian12.sh -./init-debian12.sh - -# 使环境变量生效 -source /etc/profile - -# 验证安装 -java -version -mvn -version -docker --version -docker compose version -``` - -### 1.4 网络配置 - -#### 配置静态 IP - -```bash -# 编辑网络配置 -vim /etc/network/interfaces - -# 添加以下内容 (根据实际网络调整) -#(VMware虚拟机版) -# Node-01 -# The primary network interface -auto ens33 -iface ens33 inet static - address 192.168.1.101 - netmask 255.255.255.0 - gateway 192.168.1.2 - dns-nameservers 8.8.8.8 114.114.114.114 - -# 重启网络 -systemctl restart networking -reboot -``` - -#### 配置主机名 - -```bash -# Node-01 -hostnamectl set-hostname node-01 -echo "192.168.1.101 node-01" >> /etc/hosts -echo "192.168.1.102 node-02" >> /etc/hosts -echo "192.168.1.103 node-03" >> /etc/hosts - -# Node-02 -hostnamectl set-hostname node-02 -# 添加 hosts... - -# Node-03 -hostnamectl set-hostname node-03 -# 添加 hosts... -``` - -#### 配置 SSH 免密登录 - -```bash -# 在 Node-01 生成密钥 -ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa - -# 分发公钥到其他节点 -ssh-copy-id root@192.168.1.102 -ssh-copy-id root@192.168.1.103 - -# 测试连接 -ssh node-02 "hostname" -ssh node-03 "hostname" -``` - ---- - -## 二、部署步骤 - -说明: -- 多虚拟机 HA 部署以 `docker-compose-node-01.yml`、`docker-compose-node-02.yml`、`docker-compose-node-03.yml` 为准。 -- 微服务端口以各模块的 `application.yml` 和 Nacos 中的 `video-*.yaml` 为准。 -- 根目录的 `backend/docker-compose.yml` 仅用于单机本地联调,允许在基础设施编排方式上与 HA 版不同,但服务端口和数据库编号应保持一致。 - -### 2.1 克隆项目 - -建议提前配置好 GitHub 账号和 SSH 密钥 - -```bash -# 在所有节点执行 -cd /opt -git clone <项目地址> HA-OVP -cd HA-OVP -``` - -### 2.2 构建项目 - -```bash -# 在 Node-01 执行 (只需执行一次) - -# 构建所有模块 -mvn clean install -Dmaven.test.skip=true - -# 构建 Sentinel 镜像(Node-01 执行一次即可) -cd sentinel-dashboard -docker build -t sentinel-dashboard:1.8.6 . -cd .. - -# 验证构建产物 -ls -la video-*/target/*.jar -``` - -### 2.3 同步构建产物 - -```bash -# 三个节点都需要安装 rsync -apt install rsync -y - -# 从 Node-01 同步到其他节点 -rsync -avz --progress /opt/HA-OVP/ root@192.168.1.102:/opt/HA-OVP/ -rsync -avz --progress /opt/HA-OVP/ root@192.168.1.103:/opt/HA-OVP/ -``` - -### 2.4 Node-01 部署 (主节点) - -#### 步骤 1: 启动基础设施 - -```bash -cd /opt/HA-OVP/backend - -# 先只启动基础设施 (MySQL, Redis, Nacos 等) -docker compose -f docker-compose-node-01.yml up -d mysql redis redis-sentinel nacos rmqnamesrv minio sentinel - -# 等待 MySQL 完全启动 (约 30-60 秒) -docker compose -f docker-compose-node-01.yml logs -f mysql -# 看到 "ready for connections" 后 Ctrl+C 退出 - -#停止 -docker compose -f docker-compose-node-01.yml down -v -``` - -#### 步骤 2: 验证数据库初始化 - -MySQL 容器启动时会自动执行 `sql/` 目录下的初始化脚本(通过 `docker-entrypoint-initdb.d` 挂载),无需手动初始化。 - -```bash -# 验证数据库已自动创建 -docker exec mysql mysql -uroot -proot123456 -e "SHOW DATABASES;" - -# 应看到以下数据库: -# - video_auth -# - video_user -# - video_content -# - video_comment -# - video_recommend -# - video_admin -# - nacos_config -``` - -#### 步骤 3: 等待 Nacos 启动 - -```bash -# 等待 Nacos 完全启动 -docker compose -f docker-compose-node-01.yml logs -f nacos -# 看到 "Nacos started successfully" 后 Ctrl+C 退出 - -# 创建 Nacos 用户 (重要!微服务需要认证) -# 注意:如果是首次启动,Nacos 默认用户是 nacos/nacos -# 访问控制台验证: http://192.168.1.101:8848/nacos -``` - -#### 步骤 4: 启动微服务 - -```bash -# 启动所有微服务 -docker compose -f docker-compose-node-01.yml up -d video-gateway video-auth video-user video-content video-comment video-recommend video-admin nginx - -# 查看微服务启动日志 -docker compose -f docker-compose-node-01.yml logs -f video-gateway -# 确认日志中没有错误,显示 "Started GatewayApplication" 表示成功 -``` - -#### 步骤 5: 验证 Node-01 服务状态 - -```bash -# 检查所有容器状态 -docker ps - -# 验证 Nacos 服务注册 -curl http://192.168.1.101:8848/nacos/v1/ns/service/list | grep -o '"name":"[^"]*"' - -# 验证微服务健康状态 -curl http://192.168.1.101:9000/actuator/health -curl http://192.168.1.101:9001/actuator/health -``` - -### 2.5 Node-02 部署 (从节点) - -**重要**:确保 Node-01 的所有服务正常运行后再部署 Node-02 - -#### 步骤 1: 启动基础设施 - -```bash -cd /opt/HA-OVP/backend - -# 启动基础设施 -docker compose -f docker-compose-node-02.yml up -d mysql redis redis-sentinel nacos rmqnamesrv rmqbroker minio sentinel - -# 等待 MySQL 和 Nacos 完全启动 -docker compose -f docker-compose-node-02.yml logs -f mysql -# 看到 "ready for connections" 后 Ctrl+C 退出 -``` - -#### 步骤 2: 启动微服务 - -**注意**: -- Node-02 作为 MySQL 从节点,数据库会通过主从复制自动同步,无需手动初始化。 -- 对象存储采用“方案A:Node-01 统一写入,Node-02 同步副本”,因此 `video-user` 与 `video-content` 的 MinIO 上传目标必须统一指向 `192.168.1.101:9100`。 -- Node-02 本地 MinIO 保留部署,但不再作为业务随机写入点。 - -```bash -# 等待 Nacos 启动后,启动微服务 -docker compose -f docker-compose-node-02.yml up -d video-gateway video-auth video-user video-content video-comment video-recommend video-admin - -# 查看日志,确认 Nacos 认证成功 (应显示 username='nacos') -docker compose -f docker-compose-node-02.yml logs -f video-gateway -``` - -### 2.6 Node-03 部署 (备份节点) - -```bash -cd /opt/HA-OVP/backend - -# Node-03 只部署基础设施 -docker compose -f docker-compose-node-03.yml up -d - -# 等待 MySQL 和 Nacos 启动 -docker compose -f docker-compose-node-03.yml logs -f mysql -# 看到 "ready for connections" 后 Ctrl+C 退出 - -``` - -### 2.7 配置 MySQL 主从复制 - -#### 在 Node-01 (主节点) 创建复制用户 - -```bash -docker exec -i mysql mysql -uroot -proot123456 << 'EOF' -CREATE USER IF NOT EXISTS 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'repl_password_2024'; -GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; -FLUSH PRIVILEGES; -SHOW MASTER STATUS; -EOF -``` - -#### 在 Node-02 和 Node-03 (从节点) 配置主从 - -```bash -# 在 Node-02 执行 -docker exec -i mysql mysql -uroot -proot123456 << 'EOF' -CHANGE MASTER TO - MASTER_HOST='192.168.1.101', - MASTER_USER='repl', - MASTER_PASSWORD='repl_password_2024', - MASTER_AUTO_POSITION=1; -START SLAVE; -SHOW SLAVE STATUS\G; -EOF - -# 确认 Slave_IO_Running 和 Slave_SQL_Running 都为 Yes - -# 配置完成后,启用只读模式 (重要!) -docker exec mysql mysql -uroot -proot123456 -e "SET GLOBAL read_only = ON; SET GLOBAL super_read_only = ON;" -``` - -```bash -# 在 Node-03 执行 (同上) -docker exec -i mysql mysql -uroot -proot123456 << 'EOF' -CHANGE MASTER TO - MASTER_HOST='192.168.1.101', - MASTER_USER='repl', - MASTER_PASSWORD='repl_password_2024', - MASTER_AUTO_POSITION=1; -START SLAVE; -SHOW SLAVE STATUS\G; -EOF - -docker exec mysql mysql -uroot -proot123456 -e "SET GLOBAL read_only = ON; SET GLOBAL super_read_only = ON;" -``` - -### 2.8 配置 Redis 主从复制 - -```bash -# 在 Node-02 执行 -docker exec redis redis-cli -a redis_HA_Cluster_2024 REPLICAOF 192.168.1.101 6379 - -# 在 Node-03 执行 -docker exec redis redis-cli -a redis_HA_Cluster_2024 REPLICAOF 192.168.1.101 6379 - -# 验证主从状态 (在 Node-01 执行) -docker exec redis redis-cli -a redis_HA_Cluster_2024 INFO replication | grep -E "role|connected_slaves" -``` - -### 2.9 配置 Nacos - -访问 http://192.168.1.101:8848/nacos (账号: nacos/nacos) - -#### 方式一:SQL 脚本初始化(推荐) - -```bash -# 在 Node-01 执行,初始化所有配置到 Nacos 数据库 -docker exec -i mysql mysql -uroot -proot123456 nacos_config < /opt/HA-OVP/sql/nacos-config-init.sql - -# 验证配置是否导入成功 -docker exec mysql mysql -uroot -proot123456 -e "SELECT data_id FROM nacos_config.config_info;" -``` - -SQL 脚本会自动创建以下配置: - -| Data ID | 说明 | -|---------|------| -| common.yaml | 公共配置(MySQL连接池、MyBatis、Feign等) | -| common-redis-dev.yaml | 开发环境 Redis 单机配置 | -| common-redis-ha.yaml | 生产环境 Redis Sentinel 配置 | -| video-gateway.yaml | Gateway 服务专属配置 | -| video-auth.yaml | Auth 服务专属配置 | -| video-user.yaml | User 服务专属配置 | -| video-content.yaml | Content 服务专属配置 | -| video-comment.yaml | Comment 服务专属配置 | -| video-recommend.yaml | Recommend 服务专属配置 | -| video-admin.yaml | Admin 服务专属配置 | - -#### 方式二:控制台手动创建 - -1. **创建命名空间**: 命名空间 → 新建命名空间 → 命名空间ID: `public`, 命名空间名: `公共命名空间` -2. **添加配置文件**: 配置管理 → 配置列表 → 创建配置 - - Data ID: `common.yaml` - - Group: `DEFAULT_GROUP` - - 配置内容: 参考 `sql/nacos-config-init.sql` 中的内容 -3. **重复以上步骤添加其他配置文件** - -#### 配置架构说明 - -配置采用分层加载模式: - -``` -application.yml (本地,极简) -├── common.yaml (公共配置) -├── common-redis-${profile}.yaml (按环境的Redis配置) -└── ${spring.application.name}.yaml (服务专属配置) -``` - -**环境切换**:通过 `SPRING_PROFILES_ACTIVE` 环境变量 -- `dev`: 加载 `common-redis-dev.yaml`(单机Redis) -- `ha`: 加载 `common-redis-ha.yaml`(Sentinel哨兵) - -**配置热更新**:修改 Nacos 中的配置后,服务会自动感知并更新,无需重启! - -### 2.10 初始化 MinIO - -```bash -# 安装 mc 客户端 -wget https://dl.min.io/client/mc/release/linux-amd64/mc -chmod +x mc -mv mc /usr/local/bin/ - -# 配置别名 (注意端口是 9100) -mc alias set myminio http://192.168.1.101:9100 minioadmin minioadmin123 - -# 创建存储桶 -mc mb myminio/video-platform --ignore-existing - -# 设置公开访问策略 -mc anonymous set download myminio/video-platform - -# 验证 -mc ls myminio -``` - -#### 对象存储高可用方案(方案A) - -当前生产部署不采用 MinIO 真正分布式集群模式,而采用更稳定的“单写入点 + 副本同步”方案: - -- `Node-01 MinIO (192.168.1.101:9100)`:唯一业务写入点,也是前端统一读取入口 -- `Node-02 MinIO (192.168.1.102:9100)`:同步副本,仅用于灾备,不作为业务随机写入点 -- 前端媒体访问统一使用 `http://192.168.1.101:9100/video-platform` -- `video-user`、`video-content` 服务的 MinIO 上传目标统一配置为 `MINIO_HOST=192.168.1.101`、`MINIO_PORT=9100` - -#### MinIO 同步脚本 - -仓库已提供同步脚本: - -```bash -/opt/HA-OVP/backend/scripts/minio-sync-node01-to-node02.sh -``` - -脚本作用: - -- 将 `Node-01` 的 `video-platform` 桶内容镜像同步到 `Node-02` -- 适用于头像、封面、视频文件的对象复制 - -#### 配置定时同步任务 - -在 `Node-01` 上配置 cron,每 5 分钟同步一次: - -```bash -crontab -e - -*/5 * * * * /bin/bash /opt/HA-OVP/backend/scripts/minio-sync-node01-to-node02.sh >> /var/log/minio-sync.log 2>&1 -``` - -检查定时任务: - -```bash -crontab -l -tail -f /var/log/minio-sync.log -``` - -#### 手动执行一次同步 - -首次部署完成后,建议在 `Node-01` 手动执行一次: - -```bash -cd /opt/HA-OVP/backend -bash scripts/minio-sync-node01-to-node02.sh -``` - -#### 说明 - -- 该方案可以避免“上传成功但另一节点读取 404”的问题 -- 该方案属于“对象存储主节点写入 + 副本节点同步”的高可用实现 -- 严格意义上,这不是 MinIO 分布式纠删码集群,而是适合当前资源条件的稳定答辩版方案 - ---- - -## 三、端口分配汇总 - -### 3.1 各节点端口分配 - -| 服务 | Node-01 | Node-02 | Node-03 | 说明 | -|------|---------|---------|---------|------| -| **MySQL** | 3306 | 3306 | 3306 | 数据库主从 | -| **Redis** | 6379 | 6379 | 6379 | 缓存主从 | -| **Redis Sentinel** | 26379 | 26379 | 26379 | 哨兵监控 | -| **Nacos** | 8848 | 8848 | 8848 | 配置中心集群 | -| **RocketMQ NameServer** | 9876 | 9876 | 9876 | NameServer集群 | -| **RocketMQ Broker** | - | 10911 | 10911 | Broker双主 | -| **MinIO API** | 9100 | 9100 | 9000 | Node-01 为统一写入与读取入口,Node-02 为同步副本 | -| **MinIO Console** | 9101 | 9101 | 9001 | 对象存储控制台 | -| **Sentinel Dashboard** | 8880 | 8880 | 8880 | 熔断控制台 | -| **video-gateway** | 9000 | 9000 | - | API网关 | -| **video-auth** | 9001 | 9001 | - | 认证服务 | -| **video-user** | 9002 | 9002 | - | 用户服务 | -| **video-content** | 9003 | 9003 | - | 内容服务 | -| **video-comment** | 9004 | 9004 | - | 评论服务 | -| **video-recommend** | 9005 | 9005 | - | 推荐服务 | -| **video-admin** | 9006 | 9006 | - | 管理后台 | -| **Nginx** | 80 | - | - | 负载均衡 | - -### 3.2 端口说明 - -- **MinIO 端口调整**: Node-01 和 Node-02 的 MinIO 端口改为 9100(API) 和 9101(Console),避免与微服务端口冲突 -- **MinIO 访问策略**: 所有业务上传统一写入 Node-01 MinIO,Node-02 通过同步脚本保持副本一致性 -- **Node-03**: 仅部署基础设施,不部署微服务,作为热备份节点 - ---- - -## 四、验证部署 - -### 4.1 检查服务状态 - -```bash -# 检查 Docker 容器状态 -docker ps - -# 检查 Nacos 服务注册 -curl http://192.168.1.101:8848/nacos/v1/ns/service/list - -# 检查 MySQL 主从 -docker exec mysql mysql -uroot -proot123456 -e "SHOW SLAVE STATUS\G" | grep Running - -# 检查 Redis 主从 -docker exec redis redis-cli -a redis_HA_Cluster_2024 INFO replication | grep role - -# 检查 Sentinel 状态 -docker exec redis-sentinel redis-cli -p 26379 SENTINEL master mymaster -``` - -### 4.2 访问控制台 - -| 服务 | 地址 | 账号密码 | -|------|------|---------| -| Nacos | http://192.168.1.101:8848/nacos | nacos/nacos | -| Sentinel | http://192.168.1.101:8880 | sentinel/sentinel | -| MinIO Console | http://192.168.1.101:9101 | minioadmin/minioadmin123 | -| API Gateway | http://192.168.1.101:9000 | - | - -### 4.3 API 测试 - -```bash -# 获取验证码 -curl http://192.168.1.101:9000/auth/captcha - -# 健康检查 -curl http://192.168.1.101:9000/actuator/health -curl http://192.168.1.102:9000/actuator/health -``` - ---- - -## 五、高可用测试 - -### 5.1 测试服务故障转移 - -```bash -# 停止 Node-01 的网关 -docker stop video-gateway - -# 测试 API (应该自动切换到 Node-02) -curl http://192.168.1.102:9000/auth/captcha - -# 恢复服务 -docker start video-gateway -``` - -### 5.2 测试 Redis 主从切换 - -```bash -# 停止 Node-01 的 Redis -docker stop redis - -# 查看 Sentinel 日志 (自动将从节点提升为主) -docker logs redis-sentinel - -# 验证新的主节点 -docker exec redis redis-cli -a redis_HA_Cluster_2024 INFO replication - -# 恢复 Redis (会自动变为从节点) -docker start redis -``` - -### 5.3 测试 Nacos 集群 - -```bash -# 停止 Node-01 的 Nacos -docker stop nacos - -# 验证服务注册仍然可用 -curl http://192.168.1.102:8848/nacos/v1/ns/service/list - -# 恢复 Nacos -docker start nacos -``` - ---- - -## 六、常见问题 - -### Q1: Docker 镜像拉取失败 - -```bash -# 配置国内镜像源 -vim /etc/docker/daemon.json -# 添加镜像加速器 - -# 重启 Docker -systemctl restart docker -``` - -### Q2: Nacos 集群无法启动 - -```bash -# 检查时间同步 -apt-get install -y ntpdate -ntpdate pool.ntp.org - -# 检查数据库连接 -docker exec mysql mysql -uroot -proot123456 -e "SHOW DATABASES;" -``` - -### Q3: 内存不足 - -```bash -# 查看内存使用 -free -h - -# 调整 JVM 参数 -# 编辑 config/.env.node-xx 文件中的 JAVA_OPTS -JAVA_OPTS=-Xms128m -Xmx256m -``` - -### Q4: 端口冲突 - -```bash -# 查看端口占用 -ss -tlnp | grep -E '3306|6379|8848|9000|9002' - -# 停止冲突服务 -systemctl stop mysql -systemctl stop redis -``` - -### Q5: 微服务报 "user not found!" 错误(Nacos 认证失败) - -**问题描述**:微服务启动时报错 `com.alibaba.nacos.api.exception.NacosException: user not found!` - -**原因**:Spring Boot 3.x 默认不加载 `bootstrap.yml` 文件,导致 Nacos 认证配置未生效。 - -**解决方案**:已在 docker-compose 中添加 Spring 环境变量: - -```yaml -environment: - - SPRING_CLOUD_NACOS_DISCOVERY_USERNAME=nacos - - SPRING_CLOUD_NACOS_DISCOVERY_PASSWORD=nacos - - SPRING_CLOUD_NACOS_CONFIG_USERNAME=nacos - - SPRING_CLOUD_NACOS_CONFIG_PASSWORD=nacos -``` - -**验证**:启动后日志应显示 `username='nacos'` 而不是 `username=''` - -### Q6: MySQL 从节点初始化失败 - -**问题描述**:MySQL 从节点容器启动报错 `The MySQL server is running with the --super-read-only option` - -**原因**:MySQL 从节点配置了 `read_only=ON`,阻止了容器初始化脚本执行(创建数据库、用户等)。 - -**解决方案**: -1. 确保 `config/mysql/my-slave.cnf` 中已注释掉 `read_only` 和 `super_read_only` -2. 如果已经启动失败,需要删除数据卷重新初始化: - -```bash -# 停止容器 -docker compose -f docker-compose-node-02.yml down - -# 删除 MySQL 数据卷 -docker volume rm ha-ovp_mysql_data - -# 重新启动 -docker compose -f docker-compose-node-02.yml up -d -``` - -3. 主从复制配置完成后,手动启用只读模式: - -```bash -docker exec mysql mysql -uroot -proot123456 -e "SET GLOBAL read_only = ON; SET GLOBAL super_read_only = ON;" -``` - -#### 主从复制异常修复(复制元数据损坏) - -如果从节点执行 `START SLAVE` 或 `START REPLICA` 时报错类似: +从 `backend/.env.example` 复制一份部署环境文件,至少设置: ```text -Replica failed to initialize applier metadata structure from the repository +MYSQL_ROOT_PASSWORD +MYSQL_APP_USER +MYSQL_APP_PASSWORD +REDIS_PASSWORD +MINIO_ACCESS_KEY +MINIO_SECRET_KEY +MINIO_BUCKET +USER_JWT_SECRET +ADMIN_JWT_SECRET +SERVICE_AUTH_TOKEN +NACOS_USERNAME +NACOS_PASSWORD +NACOS_AUTH_TOKEN ``` -说明复制元数据已损坏,需要重建从库复制配置。 +同时为每个节点设置 `HOST_IP`、`NACOS_SERVERS`、`REDIS_SENTINEL_NODES`;Node-02/03 的业务服务将数据库和 MinIO 写入目标指向 Node-01。仓库提供的 `backend/scripts/minio-sync-node01-to-node02.sh` 只负责 Node-01 到 Node-02 的对象镜像,Node-03 实例不应被描述为已自动同步。所有 secret 必须是部署方自行生成的值。 + +## 启动顺序 + +在 Node-01: ```bash -# 在 Node-02 执行 -docker exec -i mysql mysql -uroot -proot123456 << 'EOF' -STOP REPLICA; -RESET REPLICA ALL; -CHANGE REPLICATION SOURCE TO - SOURCE_HOST='192.168.1.101', - SOURCE_PORT=3306, - SOURCE_USER='repl', - SOURCE_PASSWORD='repl_password_2024', - SOURCE_AUTO_POSITION=1, - GET_SOURCE_PUBLIC_KEY=1; -START REPLICA; -SHOW REPLICA STATUS\G; -EOF - -# 确认以下字段为正常状态 -# Replica_IO_Running: Yes -# Replica_SQL_Running: Yes -# Seconds_Behind_Source: 0 - -# 恢复从库只读 -docker exec mysql mysql -uroot -proot123456 -e "SET GLOBAL read_only = ON; SET GLOBAL super_read_only = ON;" +cd backend +docker compose --env-file .env -f docker-compose-node-01.yml up -d ``` -Node-03 修复方式相同,只需将命令执行节点换为 Node-03。 - -### Q7: RocketMQ NameServer 健康检查失败 - -**问题描述**:RocketMQ NameServer 容器显示 unhealthy - -**原因**:容器内缺少 `nc` (netcat) 命令 - -**解决方案**:已修改健康检查命令使用 `pgrep`: - -```yaml -healthcheck: - test: ["CMD-SHELL", "pgrep -f 'NamesrvStartup' || exit 1"] -``` - -### Q8: Redis Sentinel 报 "Read-only file system" 错误 - -**问题描述**:Redis Sentinel 无法写入配置文件 - -**解决方案**:已修改为将配置文件复制到可写的数据卷: - -```yaml -volumes: - - sentinel_data:/data - - ./config/redis/sentinel.conf:/usr/local/etc/redis/sentinel.conf -command: sh -c "cp /usr/local/etc/redis/sentinel.conf /data/sentinel.conf && redis-sentinel /data/sentinel.conf" -``` - -### Q9: Redis 日志文件路径错误 - -**问题描述**:Redis 启动报错 `Can't open the log file` - -**解决方案**:修改 `config/redis/redis-master.conf` 和 `redis-slave.conf`: - -```conf -# 将 logfile /var/log/redis/redis-server.log 改为 -logfile "" -``` - -### Q10: Nacos 集群模式报 "dataSource or tableName is null" - -**问题描述**:Nacos 集群模式启动失败 - -**解决方案**:确保 docker-compose 中添加了 `SPRING_DATASOURCE_PLATFORM=mysql` 环境变量: - -```yaml -environment: - - MODE=cluster - - SPRING_DATASOURCE_PLATFORM=mysql - - MYSQL_SERVICE_HOST=mysql - - MYSQL_SERVICE_PORT=3306 - - MYSQL_SERVICE_DB_NAME=nacos_config -``` - -### Q11: RocketMQ Broker 启动失败报 NullPointerException - -**问题描述**:RocketMQ Broker 启动时报错: -``` -java.lang.NullPointerException - at org.apache.rocketmq.broker.schedule.ScheduleMessageService.configFilePath -``` - -**原因**: -1. Docker 命名卷权限问题:官方镜像以 `rocketmq` 用户 (UID 3000) 运行,但命名卷默认属于 root -2. 存储路径配置问题:`delayOffsetStorePath` 等路径指向不存在的子目录 - -**解决方案**: - -1. 在 docker-compose 中添加 `user: root`: -```yaml -rmqbroker: - image: apache/rocketmq:5.1.4 - user: root # 添加此行 - container_name: rmqbroker -``` - -2. 清理旧数据并重启: -```bash -docker compose -f docker-compose-node-02.yml rm -f -s rmqbroker -docker volume rm ha-ovp_rmqbroker_store ha-ovp_rmqbroker_logs -docker compose -f docker-compose-node-02.yml up -d rmqbroker -``` - -### Q12: Nacos 服务注册显示 Docker 内部 IP(假高可用问题) - -**问题描述**: -- Nacos 控制台显示服务实例 IP 为 `172.18.0.x` 等 Docker 内部 IP -- 同一服务在不同节点只显示 1 个实例(IP 冲突覆盖) -- 跨节点服务调用失败 - -**原因**:Docker 桥接网络中,每个容器获得内部虚拟 IP。微服务使用容器 IP 注册到 Nacos,导致: -1. 不同节点的容器可能获得相同 IP,Nacos 认为是同一实例 -2. Gateway 无法通过容器内部 IP 访问其他节点的服务 - -**解决方案**:在 docker-compose 中添加 `SPRING_CLOUD_NACOS_DISCOVERY_IP` 环境变量: - -```yaml -# Node-01 (192.168.1.101) -video-gateway: - environment: - - SPRING_CLOUD_NACOS_DISCOVERY_IP=${HOST_IP:-192.168.1.101} - -# Node-02 (192.168.1.102) -video-gateway: - environment: - - SPRING_CLOUD_NACOS_DISCOVERY_IP=${HOST_IP:-192.168.1.102} -``` - -**验证**:重启微服务后,Nacos 控制台应显示真实宿主机 IP(如 `192.168.1.101:9000`、`192.168.1.102:9000`) - -### Q13: Sentinel 控制台显示容器内部 IP 或实例失联 - -**问题描述**: -- Sentinel 控制台显示机器列表 IP 为 `172.18.0.x` 等 Docker 内部 IP -- 部分实例显示"失联"状态,健康实例数不正确 -- 跨节点无法进行限流降级 - -**原因**:与 Nacos 问题类似,Sentinel 客户端使用容器内部 IP 注册到 Dashboard,导致跨节点无法通信。 - -**解决方案**:在 docker-compose 中添加 `SPRING_CLOUD_SENTINEL_TRANSPORT_CLIENT_IP` 环境变量: - -```yaml -# Node-01 (192.168.1.101) -video-gateway: - environment: - - SPRING_CLOUD_SENTINEL_TRANSPORT_CLIENT_IP=${HOST_IP:-192.168.1.101} - -# Node-02 (192.168.1.102) -video-gateway: - environment: - - SPRING_CLOUD_SENTINEL_TRANSPORT_CLIENT_IP=${HOST_IP:-192.168.1.102} -``` - -**注意**:环境变量名必须是 `SPRING_CLOUD_SENTINEL_TRANSPORT_CLIENT_IP`,对应 Spring 属性 `spring.cloud.sentinel.transport.client-ip`。 - -**重要**:还需要配置以下两项: - -1. **端口映射**:每个微服务需要映射 Sentinel 通信端口(默认从 8719 开始) -2. **端口指定**:通过 `SPRING_CLOUD_SENTINEL_TRANSPORT_PORT` 指定固定端口 - -```yaml -# Node-01 微服务 Sentinel 端口分配 -video-gateway: - ports: - - "9000:9000" - - "8719:8719" # Sentinel 端口 - environment: - - SPRING_CLOUD_SENTINEL_TRANSPORT_PORT=8719 - -video-auth: - ports: - - "9001:9001" - - "8720:8720" # Sentinel 端口 - environment: - - SPRING_CLOUD_SENTINEL_TRANSPORT_PORT=8720 - -# 以此类推: user=8721, content=8722, comment=8723, recommend=8724, admin=8725 - -# Node-02 微服务使用不同端口避免冲突: 8739-8745 -``` - -3. **Dashboard 统一地址**:Node-02 及其他节点的微服务必须连接 Node-01 的 Sentinel Dashboard: -```yaml -# Node-02 微服务 -environment: - - SENTINEL_DASHBOARD_HOST=192.168.1.101 # 指向 Node-01 - - SENTINEL_DASHBOARD_PORT=8880 # Dashboard 宿主机端口 -``` - -**验证**:重启微服务后,Sentinel 控制台应显示真实宿主机 IP,且所有实例状态为"健康" - -### Q14: 微服务报 Redis READONLY 错误 - -**问题描述**:微服务启动时报错: -``` -io.lettuce.core.RedisReadOnlyException: READONLY You can't write against a read only replica. -``` - -**原因**:微服务使用单机模式连接 Redis(`REDIS_HOST`/`REDIS_PORT`),直接连接到了 Redis 从节点,而从节点是只读的。 - -**解决方案**: - -1. 使用 Nacos 配置中心管理 Redis 配置,通过 `SPRING_PROFILES_ACTIVE` 区分环境: - - `dev`: 加载 `common-redis-dev.yaml`(单机模式) - - `ha`: 加载 `common-redis-ha.yaml`(Sentinel模式) - -2. 确保 docker-compose 中配置了正确的环境变量: -```yaml -environment: - - SPRING_PROFILES_ACTIVE=ha - - REDIS_PASSWORD=${REDIS_PASSWORD:-redis_HA_Cluster_2024} - - REDIS_SENTINEL_NODES=${REDIS_SENTINEL_NODES:-192.168.1.101:26379,192.168.1.102:26379,192.168.1.103:26379} -``` - -3. 确保 Nacos 中 `common-redis-ha.yaml` 配置正确: -```yaml -spring: - data: - redis: - password: ${REDIS_PASSWORD:redis_HA_Cluster_2024} - sentinel: - master: mymaster - nodes: ${REDIS_SENTINEL_NODES:192.168.1.101:26379,192.168.1.102:26379,192.168.1.103:26379} - password: ${REDIS_PASSWORD:redis_HA_Cluster_2024} -``` - -**验证**: -```bash -# 查看当前 Redis 主节点 -docker exec redis-sentinel redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster -``` - -### Q15: Nacos 配置不生效或配置冲突 - -**问题描述**:修改 Nacos 配置后服务没有更新,或启动时配置异常。 - -**原因**: -1. 本地 `application.yml` 与 Nacos 配置冲突 -2. 配置加载顺序问题 -3. `spring.config.import` 配置错误 - -**解决方案**: - -1. **确保本地 application.yml 极简**:只保留 Nacos 连接配置 -```yaml -spring: - application: - name: video-auth - profiles: - active: ${SPRING_PROFILES_ACTIVE:dev} - config: - import: - - optional:nacos:common.yaml?refreshEnabled=true - - optional:nacos:common-redis-${spring.profiles.active}.yaml?refreshEnabled=true - - optional:nacos:${spring.application.name}.yaml?refreshEnabled=true - cloud: - nacos: - discovery: - server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8848} - namespace: ${NACOS_NAMESPACE:} - username: ${NACOS_USERNAME:nacos} - password: ${NACOS_PASSWORD:nacos} -``` - -2. **配置加载顺序**: - - common.yaml(公共配置) - - common-redis-${profile}.yaml(环境配置) - - ${spring.application.name}.yaml(服务配置) - -3. **验证配置加载**: -```bash -# 查看服务启动日志 -docker logs video-auth 2>&1 | grep -i nacos -# 应看到类似: "Loading nacos config, dataId: common.yaml" -``` - -4. **强制刷新配置**:修改 Nacos 配置后,服务会自动感知更新(`refreshEnabled=true`) - -### Q16: 头像或封面上传成功但访问 404 - -**问题描述**: -- 用户头像上传接口返回成功 -- 但浏览器访问图片地址时返回 `404 Not Found` -- 常见于头像、视频封面等图片资源 - -**原因**: -- 对象被上传到了 `Node-02 MinIO` -- 前端固定从 `Node-01 MinIO` 读取 -- 由于两个 MinIO 实例不是分布式共享存储,导致对象只存在于上传节点 - -**解决方案**: - -1. 统一所有业务上传写入 `Node-01 MinIO`: -```yaml -MINIO_HOST=192.168.1.101 -MINIO_PORT=9100 -``` - -2. 在 `Node-01` 执行同步脚本,把对象同步到 `Node-02`: -```bash -cd /opt/HA-OVP/backend -bash scripts/minio-sync-node01-to-node02.sh -``` - -3. 配置 cron 定时同步,避免后续对象再次不一致: -```bash -*/5 * * * * /bin/bash /opt/HA-OVP/backend/scripts/minio-sync-node01-to-node02.sh >> /var/log/minio-sync.log 2>&1 -``` - -**说明**: -- 该方案是“统一写 Node-01 + 同步到 Node-02”的稳定方案 -- 不要将当前架构表述为真正的 MinIO 分布式集群 - ---- - -## 七、日常运维 - -### 7.1 日志查看 +在 Node-02 和 Node-03 使用各自环境文件和 compose 文件启动。先观察 MySQL、Redis、Nacos、NameServer、Broker、MinIO 健康,再启动或重建业务服务: ```bash -# 查看服务日志 -docker logs -f --tail 100 video-gateway -docker logs -f --tail 100 video-auth - -# 查看所有服务状态 +docker compose --env-file .env -f docker-compose-node-02.yml up -d +docker compose --env-file .env -f docker-compose-node-03.yml up -d docker compose -f docker-compose-node-01.yml ps ``` -### 7.2 服务重启 +业务服务统一使用 `SPRING_PROFILES_ACTIVE=ha`,端口为网关 `9000`、认证 `9001`、用户 `9002`、内容 `9003`、评论 `9004`、推荐 `9005`、管理 `9006`。 + +## 验证 ```bash -# 重启单个服务 -docker restart video-gateway - -# 重启所有服务 -docker compose -f docker-compose-node-01.yml restart +docker compose -f docker-compose-node-01.yml ps +curl http://:9000/actuator/health +curl http://:8848/nacos/v1/console/health/liveness ``` -### 7.3 数据备份 +在 Nacos 控制台确认每个业务服务注册了正确的宿主机 IP,而不是 Docker 内网地址;在 Redis Sentinel 中确认主节点;在 MySQL 中确认从库复制状态。停止 Node-01 后,先验证 Sentinel 提升与业务读写,再恢复节点。 -```bash -# MySQL 备份 -docker exec mysql mysqldump -uroot -proot123456 --all-databases > backup_$(date +%Y%m%d).sql +## 存储与高可用边界 -# Redis 备份 -docker exec redis redis-cli -a redis_HA_Cluster_2024 BGSAVE -docker cp redis:/data/dump.rdb redis_backup_$(date +%Y%m%d).rdb +- MySQL 使用主从复制,业务写入仍以主库为准。 +- Redis 使用主从 + Sentinel,业务服务通过 `common-redis-ha.yaml` 连接 Sentinel。 +- Nacos 使用三节点集群和共享 `nacos_config` 数据库。 +- MinIO 当前采用 Node-01 单写入点、Node-02 定时镜像副本的方案;Node-03 是备用实例,不是原生 MinIO 分布式纠删码集群。 +- RocketMQ 部署 NameServer 与 Broker-A/B;消息主题和 broker 配置以 `backend/config/rocketmq` 为准。 -# MinIO 备份 -mc mirror myminio/video-platform minio_backup_$(date +%Y%m%d) -``` +## 安全与备份 ---- - -## 八、性能调优 - -### 8.1 JVM 调优 - -根据实际内存调整 JVM 参数: - -```bash -# 8GB 内存服务器建议配置 -JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+UseG1GC - -# 16GB 内存服务器建议配置 -JAVA_OPTS=-Xms1g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:+UseG1GC -``` - -### 8.2 MySQL 调优 - -```bash -# 编辑 MySQL 配置 -vim config/mysql/my-master.cnf - -# 关键参数 -innodb_buffer_pool_size = 2G # 设置为物理内存的 50-70% -innodb_log_file_size = 512M -max_connections = 500 -``` - -### 8.3 Redis 调优 - -```bash -# 编辑 Redis 配置 -vim config/redis/redis-master.conf - -# 关键参数 -maxmemory 2gb -maxmemory-policy allkeys-lru -``` - ---- - -## 九、架构图 - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ 高可用集群架构 │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ │ Node-01 │ │ Node-02 │ │ Node-03 │ -│ │ 192.168.1.101 │ │ 192.168.1.102 │ │ 192.168.1.103 │ -│ ├─────────────────┤ ├─────────────────┤ ├─────────────────┤ -│ │ MySQL Master │ ──────▶ │ MySQL Slave │ ──────▶ │ MySQL Slave │ -│ │ Redis Master │ ◀────── │ Redis Slave │ ◀────── │ Redis Slave │ -│ │ Nacos Node1 │ ◀─────▶ │ Nacos Node2 │ ◀─────▶ │ Nacos Node3 │ -│ │ NameServer │ │ NameServer │ │ NameServer │ -│ │ MinIO :9100 │ │ Broker-A :10911 │ │ Broker-B :10911 │ -│ │ Sentinel :8880 │ │ MinIO :9100 │ │ MinIO :9000 │ -│ ├─────────────────┤ │ Sentinel :8880 │ │ Sentinel :8880 │ -│ │ Gateway :9000 │ ├─────────────────┤ └─────────────────┘ -│ │ Auth :9001 │ │ Gateway :9000 │ (备份节点) -│ │ User :9002 │ │ Auth :9001 │ -│ │ Content :9003 │ │ User :9002 │ -│ │ Comment :9004 │ │ Content :9003 │ -│ │ Recommend :9005 │ │ Comment :9004 │ -│ │ Admin :9006 │ │ Recommend :9005 │ -│ │ Nginx :80 │ │ Admin :9006 │ -│ └─────────────────┘ └─────────────────┘ -│ (主节点,统一对象写入点) (从节点,对象同步副本) -└─────────────────────────────────────────────────────────────────────────────┘ -``` +生产环境不要公开 MySQL、Redis、Nacos、RocketMQ 和 MinIO Console;仅暴露网关及前端站点。定期备份 MySQL 逻辑数据、Nacos 配置和 MinIO 对象,并在恢复演练后再进行版本升级。 diff --git a/docs/HAOVP接口列表.md b/docs/HAOVP接口列表.md index db05ecd..7587f7d 100644 --- a/docs/HAOVP接口列表.md +++ b/docs/HAOVP接口列表.md @@ -1,142 +1,23 @@ -# HAOVP接口列表 +# HAOVP 接口索引 -| 序号 | 接口名称 | 请求类型 | 接口路径 | 接口分组 | -| ---- | ---------------------------- | -------- | ----------------------------------------------- | --------------------------------------------------- | -| 1 | 用户登录 | POST | /auth/login | 根目录/video-auth/认证控制器 | -| 2 | 用户注册 | POST | /auth/register | 根目录/video-auth/认证控制器 | -| 3 | 生成验证码 | GET | /auth/captcha | 根目录/video-auth/认证控制器 | -| 4 | 刷新令牌 | POST | /auth/refresh | 根目录/video-auth/认证控制器 | -| 5 | 用户登出 | POST | /auth/logout | 根目录/video-auth/认证控制器 | -| 6 | 获取当前用户信息 | GET | /auth/current | 根目录/video-auth/认证控制器 | -| 7 | 根据ID获取用户名 | GET | /auth/username/{userId} | 根目录/video-auth/认证控制器 | -| 8 | 获取登录统计-管理接口 | GET | /auth/admin/login/stats | 根目录/video-auth/认证管理控制器-供管理后台调用 | -| 9 | 管理员重置用户密码-管理接口 | PUT | /auth/admin/reset-password/{userId} | 根目录/video-auth/认证管理控制器-供管理后台调用 | -| 10 | 锁定/解锁用户账号-管理接口 | PUT | /auth/admin/lock/{userId}/{locked} | 根目录/video-auth/认证管理控制器-供管理后台调用 | -| 11 | 关注用户 | POST | /user/follow/{followId} | 根目录/video-user/用户关注控制器 | -| 12 | 取消关注 | DELETE | /user/follow/{followId} | 根目录/video-user/用户关注控制器 | -| 13 | 获取用户关注列表 | GET | /user/follow/following/{userId} | 根目录/video-user/用户关注控制器 | -| 14 | 获取用户粉丝列表 | GET | /user/follow/followers/{userId} | 根目录/video-user/用户关注控制器 | -| 15 | 检查是否已关注 | GET | /user/follow/check/{followId} | 根目录/video-user/用户关注控制器 | -| 16 | 发送私信 | POST | /user/message | 根目录/video-user/用户私信控制器 | -| 17 | 获取私信列表(按会话分组) | GET | /user/message/list | 根目录/video-user/用户私信控制器 | -| 18 | 获取与指定用户的私信记录 | GET | /user/message/detail/{targetId} | 根目录/video-user/用户私信控制器 | -| 19 | 标记私信为已读 | PUT | /user/message/read/{senderId} | 根目录/video-user/用户私信控制器 | -| 20 | 获取未读私信数量 | GET | /user/message/unread/count | 根目录/video-user/用户私信控制器 | -| 21 | 初始化用户资料 | POST | /user/profile/init | 根目录/video-user/用户资料控制器 | -| 22 | 获取当前用户资料 | GET | /user/profile/current | 根目录/video-user/用户资料控制器 | -| 23 | 获取指定用户资料 | GET | /user/profile/public/{userId} | 根目录/video-user/用户资料控制器 | -| 24 | 更新用户资料 | PUT | /user/profile | 根目录/video-user/用户资料控制器 | -| 25 | 上传头像 | POST | /user/profile/avatar | 根目录/video-user/用户资料控制器 | -| 26 | 搜索用户 | GET | /user/profile/search | 根目录/video-user/用户资料控制器 | -| 27 | 增加用户视频数量 | POST | /user/profile/count/video/{userId}/{count} | 根目录/video-user/用户资料控制器 | -| 28 | 增加用户获赞数量 | POST | /user/profile/count/like/{userId}/{count} | 根目录/video-user/用户资料控制器 | -| 29 | 增加用户收藏数量 | POST | /user/profile/count/favorite/{userId}/{count} | 根目录/video-user/用户资料控制器 | -| 30 | 获取用户设置 | GET | /user/setting | 根目录/video-user/用户设置控制器 | -| 31 | 更新用户设置 | PUT | /user/setting | 根目录/video-user/用户设置控制器 | -| 32 | 获取通知列表 | GET | /user/notification/list | 根目录/video-user/用户通知控制器 | -| 33 | 标记通知为已读 | PUT | /user/notification/read | 根目录/video-user/用户通知控制器 | -| 34 | 标记指定通知为已读 | PUT | /user/notification/read/{notificationId} | 根目录/video-user/用户通知控制器 | -| 35 | 获取未读通知数量 | GET | /user/notification/unread/count | 根目录/video-user/用户通知控制器 | -| 36 | 发送用户通知 | POST | /user/notification/send/{userId}/{type} | 根目录/video-user/用户通知控制器 | -| 37 | 获取用户列表-管理接口 | GET | /user/profile/admin/list | 根目录/video-user/用户管理控制器-供管理后台调用 | -| 38 | 获取用户详情-管理接口 | GET | /user/profile/admin/{userId} | 根目录/video-user/用户管理控制器-供管理后台调用 | -| 39 | 禁用/启用用户-管理接口 | PUT | /user/profile/admin/status/{userId}/{status} | 根目录/video-user/用户管理控制器-供管理后台调用 | -| 40 | 重置用户密码-管理接口 | PUT | /user/profile/admin/reset-password/{userId} | 根目录/video-user/用户管理控制器-供管理后台调用 | -| 41 | 获取用户统计信息-管理接口 | GET | /user/profile/admin/stats | 根目录/video-user/用户管理控制器-供管理后台调用 | -| 42 | 获取标签列表 | GET | /content/tag/list | 根目录/video-content/标签控制器 | -| 43 | 分页获取标签列表 | GET | /content/tag/page | 根目录/video-content/标签控制器 | -| 44 | 添加标签 | POST | /content/tag | 根目录/video-content/标签控制器 | -| 45 | 更新标签 | PUT | /content/tag | 根目录/video-content/标签控制器 | -| 46 | 删除标签 | DELETE | /content/tag/{id} | 根目录/video-content/标签控制器 | -| 47 | 获取视频标签 | GET | /content/tag/video/{videoId} | 根目录/video-content/标签控制器 | -| 48 | 上传视频 | POST | /content/video/upload | 根目录/video-content/视频控制器 | -| 49 | 创建视频 | POST | /content/video | 根目录/video-content/视频控制器 | -| 50 | 获取视频详情(公开接口) | GET | /content/video/public/{id} | 根目录/video-content/视频控制器 | -| 51 | 获取视频列表(公开接口) | GET | /content/video/public/list | 根目录/video-content/视频控制器 | -| 52 | 获取视频详情 | GET | /content/video/{id} | 根目录/video-content/视频控制器 | -| 53 | 获取视频列表 | GET | /content/video/list | 根目录/video-content/视频控制器 | -| 54 | 更新视频信息 | PUT | /content/video | 根目录/video-content/视频控制器 | -| 55 | 删除视频 | DELETE | /content/video/{id} | 根目录/video-content/视频控制器 | -| 56 | 点赞视频 | POST | /content/video/like/{videoId} | 根目录/video-content/视频控制器 | -| 57 | 取消点赞 | DELETE | /content/video/like/{videoId} | 根目录/video-content/视频控制器 | -| 58 | 投币 | POST | /content/video/coin/{videoId} | 根目录/video-content/视频控制器 | -| 59 | 收藏视频 | POST | /content/video/favorite | 根目录/video-content/视频控制器 | -| 60 | 取消收藏 | DELETE | /content/video/favorite/{videoId} | 根目录/video-content/视频控制器 | -| 61 | 分享视频 | POST | /content/video/share/{videoId} | 根目录/video-content/视频控制器 | -| 62 | 播放记录 | POST | /content/video/play | 根目录/video-content/视频控制器 | -| 63 | 获取用户视频列表 | GET | /content/video/user/{userId} | 根目录/video-content/视频控制器 | -| 64 | 视频审核 | POST | /content/video/review/{videoId} | 根目录/video-content/视频控制器 | -| 65 | 增加视频评论数量 | POST | /content/video/count/comment/{videoId}/{count} | 根目录/video-content/视频控制器 | -| 66 | 发送弹幕 | POST | /content/danmaku | 根目录/video-content/弹幕控制器 | -| 67 | 获取视频指定时间段的弹幕 | GET | /content/danmaku/time | 根目录/video-content/弹幕控制器 | -| 68 | 获取视频所有弹幕 | GET | /content/danmaku/all/{videoId} | 根目录/video-content/弹幕控制器 | -| 69 | 获取分类树 | GET | /content/category/tree | 根目录/video-content/分类控制器 | -| 70 | 获取分类列表 | GET | /content/category/list | 根目录/video-content/分类控制器 | -| 71 | 添加分类 | POST | /content/category | 根目录/video-content/分类控制器 | -| 72 | 更新分类 | PUT | /content/category | 根目录/video-content/分类控制器 | -| 73 | 删除分类 | DELETE | /content/category/{id} | 根目录/video-content/分类控制器 | -| 74 | 获取用户收藏夹列表 | GET | /content/favorite/list | 根目录/video-content/收藏夹控制器 | -| 75 | 创建收藏夹 | POST | /content/favorite | 根目录/video-content/收藏夹控制器 | -| 76 | 更新收藏夹 | PUT | /content/favorite | 根目录/video-content/收藏夹控制器 | -| 77 | 删除收藏夹 | DELETE | /content/favorite/{id} | 根目录/video-content/收藏夹控制器 | -| 78 | 获取收藏夹中的视频 | GET | /content/favorite/{favoriteId}/videos | 根目录/video-content/收藏夹控制器 | -| 79 | 获取视频每日统计 | GET | /content/stat/daily/{videoId} | 根目录/video-content/视频统计控制器 | -| 80 | 获取视频播放趋势(按小时) | GET | /content/stat/play/trend/{videoId} | 根目录/video-content/视频统计控制器 | -| 81 | 获取视频互动统计 | GET | /content/stat/interaction/{videoId} | 根目录/video-content/视频统计控制器 | -| 82 | 获取视频列表-管理接口 | GET | /content/video/admin/list | 根目录/video-content/视频管理控制器-供管理后台调用 | -| 83 | 获取视频详情-管理接口 | GET | /content/video/admin/{videoId} | 根目录/video-content/视频管理控制器-供管理后台调用 | -| 84 | 审核视频-管理接口 | POST | /content/video/admin/review/{videoId} | 根目录/video-content/视频管理控制器-供管理后台调用 | -| 85 | 下架视频-管理接口 | PUT | /content/video/admin/disable/{videoId} | 根目录/video-content/视频管理控制器-供管理后台调用 | -| 86 | 获取视频统计信息-管理接口 | GET | /content/video/admin/stats | 根目录/video-content/视频管理控制器-供管理后台调用 | -| 87 | 获取分类列表-管理接口 | GET | /content/category/admin/list | 根目录/video-content/分类管理控制器-供管理后台调用 | -| 88 | 添加分类-管理接口 | POST | /content/category/admin | 根目录/video-content/分类管理控制器-供管理后台调用 | -| 89 | 更新分类-管理接口 | PUT | /content/category/admin | 根目录/video-content/分类管理控制器-供管理后台调用 | -| 90 | 删除分类-管理接口 | DELETE | /content/category/admin/{categoryId} | 根目录/video-content/分类管理控制器-供管理后台调用 | -| 91 | 获取首页推荐 | GET | /recommend/home | 根目录/video-recommend/推荐控制器 | -| 92 | 获取热门推荐 | GET | /recommend/hot | 根目录/video-recommend/推荐控制器 | -| 93 | 获取相似视频推荐 | GET | /recommend/similar/{videoId} | 根目录/video-recommend/推荐控制器 | -| 94 | 获取标签视频推荐 | GET | /recommend/tag/{tagId} | 根目录/video-recommend/推荐控制器 | -| 95 | 记录用户行为 | POST | /recommend/behavior | 根目录/video-recommend/推荐控制器 | -| 96 | 更新用户兴趣 | POST | /recommend/interest/update | 根目录/video-recommend/推荐控制器 | -| 97 | 添加回复 | POST | /comment/reply | 根目录/video-comment/回复控制器 | -| 98 | 获取评论的回复列表(公开接口) | GET | /comment/reply/public/list/{commentId} | 根目录/video-comment/回复控制器 | -| 99 | 获取评论的热门回复(公开接口) | GET | /comment/reply/public/hot/{commentId} | 根目录/video-comment/回复控制器 | -| 100 | 删除回复 | DELETE | /comment/reply/{id} | 根目录/video-comment/回复控制器 | -| 101 | 点赞回复 | POST | /comment/reply/like/{id} | 根目录/video-comment/回复控制器 | -| 102 | 取消点赞回复 | DELETE | /comment/reply/like/{id} | 根目录/video-comment/回复控制器 | -| 103 | 添加评论 | POST | /comment | 根目录/video-comment/评论控制器 | -| 104 | 获取评论列表(公开接口) | GET | /comment/public/list | 根目录/video-comment/评论控制器 | -| 105 | 获取评论详情(公开接口) | GET | /comment/public/detail/{id} | 根目录/video-comment/评论控制器 | -| 106 | 删除评论 | DELETE | /comment/{id} | 根目录/video-comment/评论控制器 | -| 107 | 点赞评论 | POST | /comment/like/{id} | 根目录/video-comment/评论控制器 | -| 108 | 取消点赞评论 | DELETE | /comment/like/{id} | 根目录/video-comment/评论控制器 | -| 109 | 置顶评论 | POST | /comment/top/{id} | 根目录/video-comment/评论控制器 | -| 110 | 取消置顶评论 | DELETE | /comment/top/{id} | 根目录/video-comment/评论控制器 | -| 111 | 获取评论统计信息(公开接口) | GET | /comment/public/stat/{videoId} | 根目录/video-comment/评论控制器 | -| 112 | 获取评论列表-管理接口 | GET | /comment/admin/list | 根目录/video-comment/评论管理控制器-供管理后台调用 | -| 113 | 获取评论详情-管理接口 | GET | /comment/admin/{commentId} | 根目录/video-comment/评论管理控制器-供管理后台调用 | -| 114 | 删除评论-管理接口 | DELETE | /comment/admin/{commentId} | 根目录/video-comment/评论管理控制器-供管理后台调用 | -| 115 | 获取评论统计信息-管理接口 | GET | /comment/admin/stats | 根目录/video-comment/评论管理控制器-供管理后台调用 | -| 116 | 获取验证码 | GET | /admin/auth/captcha | 根目录/video-admin/认证控制器 | -| 117 | 登录 | POST | /admin/auth/login | 根目录/video-admin/认证控制器 | -| 118 | 登出 | POST | /admin/auth/logout | 根目录/video-admin/认证控制器 | -| 119 | 获取当前用户信息 | GET | /admin/auth/info | 根目录/video-admin/认证控制器 | -| 120 | 获取管理员列表 | GET | /admin/user/list | 根目录/video-admin/管理员控制器 | -| 121 | 获取管理员详情 | GET | /admin/user/{id} | 根目录/video-admin/管理员控制器 | -| 122 | 添加管理员 | POST | /admin/user | 根目录/video-admin/管理员控制器 | -| 123 | 更新管理员 | PUT | /admin/user | 根目录/video-admin/管理员控制器 | -| 124 | 删除管理员 | DELETE | /admin/user/{id} | 根目录/video-admin/管理员控制器 | -| 125 | 启用/禁用管理员 | PUT | /admin/user/{id}/status/{status} | 根目录/video-admin/管理员控制器 | -| 126 | 重置密码 | PUT | /admin/user/{id}/reset-password | 根目录/video-admin/管理员控制器 | -| 127 | 获取用户列表 | GET | /admin/platform/user/list | 根目录/video-admin/用户管理控制器 | -| 128 | 获取用户详情 | GET | /admin/platform/user/{userId} | 根目录/video-admin/用户管理控制器 | -| 129 | 禁用/启用用户 | PUT | /admin/platform/user/{userId}/status/{status} | 根目录/video-admin/用户管理控制器 | -| 130 | 重置用户密码 | PUT | /admin/platform/user/{userId}/reset-password | 根目录/video-admin/用户管理控制器 | -| 131 | 获取视频列表 | GET | /admin/platform/content/video/list | 根目录/video-admin/内容管理控制器 | -| 132 | 获取视频详情 | GET | /admin/platform/content/video/{videoId} | 根目录/video-admin/内容管理控制器 | -| 133 | 审核视频 | POST | /admin/platform/content/video/review/{videoId} | 根目录/video-admin/内容管理控制器 | -| 134 | 下架视频 | PUT | /admin/platform/content/video/disable/{videoId} | 根目录/video-admin/内容管理控制器 | -| 135 | 获取分类列表 | GET | /admin/platform/content/category/list | 根目录/video-admin/内容管理控制器 | -| 136 | 添加分类 | POST | /admin/platform/content/category | 根目录/video-admin/内容管理控制器 | -| 137 | 更新分类 | PUT | /admin/platform/content/category | 根目录/video-admin/内容管理控制器 | -| 138 | 删除分类 | DELETE | /admin/platform/content/category/{categoryId} | 根目录/video-admin/内容管理控制器 | +接口以 `backend/*/src/main/java/**/controller/*Controller.java` 中的 Spring MVC 注解为唯一权威来源。此前的逐条静态清单与代码已发生偏差,现改为维护当前 Controller 路由索引,避免遗漏新增接口或保留已删除接口。 + +所有客户端业务请求默认经 `video-gateway:9000` 访问;以下为网关后的路径前缀。 + +| 服务 | Controller | 路由前缀 | +| --- | --- | --- | +| 认证 | `AuthController` / `AdminAuthController` | `/auth` / `/auth/admin` | +| 用户 | `UserProfileController` / `UserFollowController` / `UserMessageController` / `UserNotificationController` / `UserSettingController` / `AdminUserController` | `/user/profile`、`/user/follow`、`/user/message`、`/user/notification`、`/user/setting`、`/user/profile/admin` | +| 内容 | `VideoController` / `CategoryController` / `TagController` / `FavoriteController` / `DanmakuController` / `VideoStatController` | `/content/video`、`/content/category`、`/content/tag`、`/content/favorite`、`/content/danmaku`、`/content/stat` | +| 内容管理 | `AdminVideoController` / `AdminCategoryController` | `/content/video/admin` / `/content/category/admin` | +| 评论 | `CommentController` / `ReplyController` / `AdminCommentController` | `/comment` / `/comment/reply` / `/comment/admin` | +| 推荐 | `RecommendController` | `/recommend` | +| 管理端 | `AuthController` / `AdminUserController` / `AdminRoleController` / `UserManageController` / `ContentManageController` / `CommentManageController` / `DashboardController` | `/admin/auth`、`/admin/user`、`/admin/role`、`/admin/platform/user`、`/admin/platform/content`、`/admin/platform/comment`、`/admin/dashboard` | + +## 主要公开路由 + +网关白名单由 `video-gateway.yaml` 和 `GATEWAY_IGNORE_URLS` 配置控制,当前包含登录/注册/验证码/令牌刷新、公开视频与分类/标签/弹幕/统计、公开用户主页与搜索、公开评论回复以及推荐接口等。白名单属于安全配置,变更时必须同步审查网关过滤器和 Nacos 配置。 + +## 维护方式 + +新增或修改接口时,应同时更新 Controller 注释、DTO 校验和前端 `src/api` 调用;再检查网关公开路由是否需要调整。接口鉴权、参数和响应字段请直接查阅对应 Controller、DTO/VO 与 `Result`,不要依赖旧版本的 curl 示例。 diff --git a/docs/frontend-architecture.md b/docs/frontend-architecture.md index d6c063e..f11f87f 100644 --- a/docs/frontend-architecture.md +++ b/docs/frontend-architecture.md @@ -1,458 +1,31 @@ -# HA-OVP 前端项目文档 +# HAOVP 前端架构(当前版本) -## 项目概述 +前端包含两个独立的 Vue 3 + TypeScript + Vite 应用: -HA-OVP(高可用在线视频平台)前端系统包含两个独立的 Vue 3 项目: +- `frontend/video-frontend-web`:用户端,端口 3000 +- `frontend/video-frontend-admin`:管理端,端口 3100 -- **video-platform-web**: 用户端前台,面向普通用户 -- **video-platform-admin**: 管理端后台,面向管理员 +## 依赖 -## 技术栈 +两端共用 Vue Router 4、Pinia、Axios、Day.js、NProgress。用户端使用 Vant 4、Artplayer 5.1.7 和 `artplayer-plugin-danmuku` 5.1.0;管理端使用 Element Plus 2.6、ECharts 5.5 和 SortableJS。项目脚本使用 npm、pnpm 均可,具体以各目录 `package.json` 为准。 -### 共同技术 +## 目录职责 -| 类别 | 技术 | 版本 | -|------|------|------| -| 框架 | Vue 3 | ^3.4 | -| 语言 | TypeScript | ^5.0 | -| 构建工具 | Vite | ^5.0 | -| 状态管理 | Pinia | ^2.1 | -| 路由 | Vue Router | ^4.2 | -| HTTP客户端 | Axios | ^1.6 | -| 样式 | SCSS | - | -| 日期处理 | Day.js | ^1.11 | -| 进度条 | NProgress | ^0.2 | +两端均采用 `api`(接口封装)、`components`、`router`、`stores`、`types`、`utils`、`views` 分层。用户端额外包含视频、评论、弹幕和布局组件;管理端包含 dashboard、用户、视频审核、内容分类/标签、评论和系统管理页面。 -### 用户端前台 (video-platform-web) +## 请求与认证 -| 类别 | 技术 | 版本 | -|------|------|------| -| UI组件库 | Vant 4 | ^4.8 | -| 视频播放器 | DPlayer | - | +开发服务器将 `/api` 去前缀后代理到网关。代理地址由 `VITE_PROXY_TARGET` 控制,默认值是 `http://192.168.1.101:9000`。用户端和管理端分别使用独立的 Axios 封装、Token 存储和路由守卫;生产环境应通过 Nginx/OpenResty 将 `/api` 转发到网关,而不是直连业务服务。 -### 管理端后台 (video-platform-admin) - -| 类别 | 技术 | 版本 | -|------|------|------| -| UI组件库 | Element Plus | ^2.5 | -| 图标 | @element-plus/icons-vue | ^2.3 | -| 图表 | ECharts | ^5.5 | - -## 目录结构 - -### 用户端前台 - -``` -video-platform-web/ -├── public/ # 静态资源 -├── src/ -│ ├── api/ # API 接口封装 -│ │ ├── auth.ts # 认证相关 -│ │ ├── user.ts # 用户相关 -│ │ ├── video.ts # 视频相关 -│ │ ├── comment.ts # 评论相关 -│ │ ├── category.ts # 分类相关 -│ │ ├── danmaku.ts # 弹幕相关 -│ │ ├── favorite.ts # 收藏相关 -│ │ ├── recommend.ts # 推荐相关 -│ │ └── index.ts # 导出 -│ ├── assets/ # 资源文件 -│ ├── components/ # 公共组件 -│ │ ├── layout/ # 布局组件 -│ │ ├── video/ # 视频组件 -│ │ ├── comment/ # 评论组件 -│ │ └── danmaku/ # 弹幕组件 -│ ├── composables/ # 组合式函数 -│ ├── directives/ # 自定义指令 -│ ├── router/ # 路由配置 -│ ├── stores/ # Pinia 状态管理 -│ │ ├── user.ts # 用户状态 -│ │ ├── video.ts # 视频状态 -│ │ ├── favorite.ts # 收藏状态 -│ │ ├── message.ts # 消息状态 -│ │ ├── app.ts # 应用状态 -│ │ └── index.ts # 导出 -│ ├── styles/ # 全局样式 -│ ├── types/ # TypeScript 类型定义 -│ ├── utils/ # 工具函数 -│ ├── views/ # 页面组件 -│ │ ├── home/ # 首页 -│ │ ├── login/ # 登录注册 -│ │ ├── video/ # 视频相关 -│ │ ├── user/ # 用户相关 -│ │ ├── upload/ # 上传 -│ │ ├── message/ # 消息 -│ │ ├── favorite/ # 收藏 -│ │ ├── search/ # 搜索 -│ │ ├── layout/ # 布局 -│ │ └── error/ # 错误页 -│ ├── App.vue # 根组件 -│ └── main.ts # 入口文件 -├── package.json -├── vite.config.ts -└── tsconfig.json -``` - -### 管理端后台 - -``` -video-platform-admin/ -├── public/ # 静态资源 -├── src/ -│ ├── api/ # API 接口封装 -│ │ ├── auth.ts # 管理员认证 -│ │ ├── user.ts # 用户管理 -│ │ ├── video.ts # 视频管理 -│ │ ├── category.ts # 分类管理 -│ │ ├── comment.ts # 评论管理 -│ │ ├── admin.ts # 管理员管理 -│ │ ├── statistics.ts # 统计数据 -│ │ └── index.ts # 导出 -│ ├── assets/ # 资源文件 -│ ├── components/ # 公共组件 -│ │ ├── Breadcrumb.vue # 面包屑 -│ │ └── TagsView.vue # 标签页导航 -│ ├── composables/ # 组合式函数 -│ ├── directives/ # 自定义指令 -│ ├── router/ # 路由配置 -│ ├── stores/ # Pinia 状态管理 -│ │ ├── user.ts # 管理员状态 -│ │ ├── app.ts # 应用状态 -│ │ ├── tagsView.ts # 标签页状态 -│ │ └── index.ts # 导出 -│ ├── styles/ # 全局样式 -│ │ ├── index.scss # 主样式 -│ │ └── variables.scss # 变量定义 -│ ├── types/ # TypeScript 类型定义 -│ ├── utils/ # 工具函数 -│ │ ├── request.ts # HTTP 请求封装 -│ │ └── format.ts # 格式化工具 -│ ├── views/ # 页面组件 -│ │ ├── dashboard/ # 仪表盘 -│ │ ├── login/ # 登录 -│ │ ├── user/ # 用户管理 -│ │ ├── video/ # 视频管理 -│ │ ├── content/ # 内容管理 -│ │ ├── system/ # 系统管理 -│ │ ├── layout/ # 布局 -│ │ └── error/ # 错误页 -│ ├── App.vue # 根组件 -│ └── main.ts # 入口文件 -├── package.json -├── vite.config.ts -└── tsconfig.json -``` - -## 功能模块 - -### 用户端前台功能 - -#### 认证模块 -- 用户名/邮箱/手机号登录 -- 用户注册 -- 验证码验证 -- JWT Token 自动刷新 -- 登出功能 - -#### 首页模块 -- 视频推荐流 -- 热门视频榜单 -- 分类导航 -- 搜索功能 - -#### 视频模块 -- 视频播放(支持倍速、全屏、画中画) -- 弹幕系统(发送、显示、样式设置) -- 视频点赞/投币/收藏/分享 -- 相关视频推荐 -- 视频上传(拖拽上传、进度显示) -- 我的视频管理 - -#### 评论模块 -- 评论列表(分页、排序) -- 发表评论 -- 回复评论 -- 评论点赞 - -#### 用户模块 -- 个人中心 -- 个人主页 -- 编辑资料 -- 账号设置 - -#### 社交模块 -- 关注用户 -- 粉丝/关注列表 -- 私信功能 -- 消息通知 - -### 管理端后台功能 - -#### 认证模块 -- 管理员登录 -- 验证码验证 -- 登出功能 - -#### 仪表盘 -- 平台数据概览 -- 数据趋势图表 -- 待审核内容提醒 - -#### 用户管理 -- 用户列表(分页、搜索、筛选) -- 用户详情 -- 禁用/启用用户 -- 重置密码 - -#### 视频管理 -- 视频列表 -- 视频审核 -- 视频下架 - -#### 内容管理 -- 分类管理 -- 标签管理 -- 评论管理 - -#### 系统管理 -- 管理员管理 - -## API 接口 - -### 请求配置 - -所有 API 请求通过统一的 `request` 工具进行封装: - -```typescript -// 基础配置 -baseURL: '/api' // 用户端 -baseURL: '/api/admin' // 管理端 -timeout: 30000 - -// 请求拦截器 -- 自动添加 Authorization Header -- 显示加载进度 - -// 响应拦截器 -- 统一错误处理 -- Token 过期自动跳转登录 -``` - -### 用户端主要接口 - -| 模块 | 接口 | 说明 | -|------|------|------| -| 认证 | POST /auth/login | 登录 | -| 认证 | POST /auth/register | 注册 | -| 认证 | GET /auth/captcha | 获取验证码 | -| 用户 | GET /user/profile/current | 获取当前用户资料 | -| 用户 | PUT /user/profile | 更新用户资料 | -| 用户 | POST /user/follow/{id} | 关注用户 | -| 视频 | GET /content/video/public/list | 获取视频列表 | -| 视频 | GET /content/video/public/{id} | 获取视频详情 | -| 视频 | POST /content/video/upload | 上传视频 | -| 评论 | GET /comment/public/list | 获取评论列表 | -| 评论 | POST /comment | 发表评论 | -| 弹幕 | GET /content/danmaku/all/{videoId} | 获取弹幕 | -| 弹幕 | POST /content/danmaku | 发送弹幕 | -| 推荐 | GET /recommend/home | 首页推荐 | - -### 管理端主要接口 - -| 模块 | 接口 | 说明 | -|------|------|------| -| 认证 | POST /admin/auth/login | 管理员登录 | -| 用户 | GET /admin/platform/user/list | 用户列表 | -| 用户 | PUT /admin/platform/user/{id}/status/{status} | 更新用户状态 | -| 视频 | GET /admin/platform/content/video/list | 视频列表 | -| 视频 | POST /admin/platform/content/video/review/{id} | 审核视频 | -| 分类 | GET /admin/platform/content/category/list | 分类列表 | -| 评论 | GET /comment/admin/list | 评论列表 | -| 统计 | GET /statistics/dashboard | 仪表盘数据 | - -## 开发指南 - -### 环境要求 - -- Node.js >= 18.0 -- pnpm >= 8.0 (推荐) 或 npm >= 9.0 - -### 安装依赖 +## 启动和构建 ```bash -# 用户端 -cd video-platform-web -pnpm install +cd frontend/video-frontend-web && npm install && npm run dev +cd frontend/video-frontend-admin && npm install && npm run dev -# 管理端 -cd video-platform-admin -pnpm install +# 在各自目录执行 +npm run build +npm run preview ``` -### 开发运行 - -```bash -# 用户端 (端口 3000) -cd video-platform-web -pnpm dev - -# 管理端 (端口 3100) -cd video-platform-admin -pnpm dev -``` - -### 构建部署 - -```bash -# 构建 -pnpm build - -# 预览 -pnpm preview -``` - -### 代理配置 - -在 `vite.config.ts` 中配置后端代理: - -```typescript -server: { - port: 3000, // 或 3100 - proxy: { - '/api': { - target: 'http://localhost:9000', // 后端网关地址 - changeOrigin: true, - rewrite: (path) => path.replace(/^\/api/, '') - } - } -} -``` - -## 代码规范 - -### 命名规范 - -- 文件夹:kebab-case(如 `video-player`) -- Vue组件:PascalCase(如 `VideoPlayer.vue`) -- TypeScript文件:camelCase(如 `videoService.ts`) -- 常量:UPPER_SNAKE_CASE -- CSS类名:kebab-case - -### 组件规范 - -```vue - - - - - -``` - -### Git 提交规范 - -- `feat`: 新功能 -- `fix`: 修复bug -- `docs`: 文档更新 -- `style`: 代码格式 -- `refactor`: 重构 -- `test`: 测试 -- `chore`: 构建/工具 - -## 部署说明 - -### Nginx 配置示例 - -```nginx -# 用户端 -server { - listen 80; - server_name www.example.com; - - root /var/www/video-platform-web; - index index.html; - - location / { - try_files $uri $uri/ /index.html; - } - - location /api { - proxy_pass http://localhost:9000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - } -} - -# 管理端 -server { - listen 80; - server_name admin.example.com; - - root /var/www/video-platform-admin; - index index.html; - - location / { - try_files $uri $uri/ /index.html; - } - - location /api { - proxy_pass http://localhost:9000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - } -} -``` - -### 环境变量 - -创建 `.env.production` 文件: - -```env -VITE_API_BASE_URL=https://api.example.com -VITE_APP_TITLE=HAOVP -``` - -## 常见问题 - -### 1. 跨域问题 - -确保后端配置了 CORS,或在 Vite 代理中正确配置。 - -### 2. Token 过期 - -前端会自动检测 401 响应并跳转登录页。 - -### 3. 图片/视频上传失败 - -检查文件大小限制和 MinIO 配置。 - -## 更新日志 - -### v1.0.0 (2024-03) - -- 初始版本发布 -- 用户端完整功能 -- 管理端完整功能 +用户端播放器是 Artplayer,不再使用早期文档中的 DPlayer。管理端仪表盘接口由 `src/api/statistics.ts` 聚合用户、视频、评论和趋势数据,接口路径以当前 `src/api` 文件为准。 diff --git a/docs/nacos-config-guide.md b/docs/nacos-config-guide.md index 740638c..55e2891 100644 --- a/docs/nacos-config-guide.md +++ b/docs/nacos-config-guide.md @@ -1,129 +1,39 @@ -# Nacos 配置中心方案 +# Nacos 配置中心 -## 一、配置架构 +所有后端服务通过 `src/main/resources/application.yml` 导入以下配置: -### 1.1 配置文件结构 - -``` -application.yml (本地,极简) -├── Nacos: common.yaml (公共配置) -├── Nacos: common-redis-${profile}.yaml (按环境的Redis配置) -└── Nacos: ${spring.application.name}.yaml (服务专属配置) +```text +common.yaml +common-redis-${spring.profiles.active}.yaml +${spring.application.name}.yaml ``` -### 1.2 Data ID 设计 +其中 `${spring.application.name}` 为 `video-gateway`、`video-auth`、`video-user`、`video-content`、`video-comment`、`video-recommend` 或 `video-admin`。 -| Data ID | 说明 | -|---------|------| -| common.yaml | 公共配置(MySQL连接池、MyBatis、Feign等) | -| common-redis-dev.yaml | 开发环境Redis单机配置 | -| common-redis-ha.yaml | 生产环境Redis Sentinel配置 | -| video-gateway.yaml | Gateway服务专属配置 | -| video-auth.yaml | Auth服务专属配置 | -| video-user.yaml | User服务专属配置 | -| video-content.yaml | Content服务专属配置 | -| video-comment.yaml | Comment服务专属配置 | -| video-recommend.yaml | Recommend服务专属配置 | -| video-admin.yaml | Admin服务专属配置 | +## 环境切换 -## 二、使用方式 +- `SPRING_PROFILES_ACTIVE=dev`:连接开发环境 Redis 单机配置 +- `SPRING_PROFILES_ACTIVE=ha`:连接 Redis Sentinel 配置;节点列表通过 `REDIS_SENTINEL_NODES` 提供 -### 2.1 初始化 Nacos 配置 +配置优先级为:环境变量 > Nacos > 本地 `application.yml`。导入使用 `refreshEnabled=true`,发布 Nacos 配置后服务可动态刷新支持刷新的配置项。 -**方式一:执行 SQL 脚本** +## 初始化 + +Docker Compose 会挂载 `backend/sql/nacos-schema.sql` 和 `backend/sql/nacos-config-init.sql`。已有 MySQL 数据卷不会重复执行初始化脚本;需要补配置时,应在确认备份后通过 Nacos 控制台或 SQL 文件导入。 ```bash -# 连接 Nacos 数据库 -mysql -u root -p nacos_config < sql/nacos-config-init.sql +docker exec -i mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" nacos_config < backend/sql/nacos-config-init.sql ``` -**方式二:通过 Nacos 控制台手动创建** +命令中的密码必须来自当前部署环境变量,文档不提供默认生产密码。 -1. 登录 Nacos 控制台:http://localhost:8848/nacos(默认账号:nacos/nacos) -2. 进入「配置管理」->「配置列表」 -3. 点击「+」创建配置,Data ID 和内容参考 `sql/nacos-config-init.sql` +## 认证与地址 -### 2.2 环境切换 +Nacos 2.3.2 在 Compose 中启用认证。业务服务通过 `NACOS_HOST`、`NACOS_PORT`、`NACOS_USERNAME`、`NACOS_PASSWORD` 连接;跨主机部署还需设置 `NACOS_NAMESPACE`、`NACOS_GROUP` 和服务注册 IP 变量。不要把 Nacos、MySQL、Redis 管理端口直接暴露到公网。 -通过 `SPRING_PROFILES_ACTIVE` 环境变量切换环境: +## 排查顺序 -**开发环境:** -```yaml -environment: - - SPRING_PROFILES_ACTIVE=dev -``` -会加载 `common-redis-dev.yaml`,使用单机 Redis。 - -**生产/高可用环境:** -```yaml -environment: - - SPRING_PROFILES_ACTIVE=ha - - REDIS_SENTINEL_NODES=192.168.1.101:26379,192.168.1.102:26379,192.168.1.103:26379 -``` -会加载 `common-redis-ha.yaml`,使用 Sentinel 哨兵模式。 - -### 2.3 配置热更新 - -修改 Nacos 中的配置后,服务会自动感知并更新(`refreshEnabled=true`),无需重启! - -## 三、配置优先级 - -``` -环境变量 > Nacos 配置 > 本地 application.yml -``` - -## 四、本地开发 - -本地开发时,启动 Nacos 后: - -1. 确保 Nacos 中已有配置 -2. 启动服务,默认使用 `dev` profile -3. 自动连接开发环境的 Redis - -## 五、生产部署 - -```bash -# 1. 执行 SQL 初始化配置 -mysql -u root -p nacos_config < sql/nacos-config-init.sql - -# 2. 构建镜像 -mvn clean package -DskipTests -docker-compose -f docker-compose-node-01.yml build - -# 3. 启动服务 -docker-compose -f docker-compose-node-01.yml up -d -``` - -## 六、常见问题 - -### Q1: 配置没有生效? - -检查以下几点: -1. Nacos 是否正常运行 -2. 服务启动日志是否显示连接 Nacos 成功 -3. 配置的 Data ID 是否正确 -4. `spring.config.import` 是否正确配置 - -### Q2: 如何查看当前使用的配置? - -```bash -# 查看服务日志 -docker logs -f video-auth | grep -i nacos -``` - -### Q3: 如何动态修改配置? - -1. 登录 Nacos 控制台 -2. 找到对应配置 -3. 编辑并发布 -4. 服务自动感知更新 - -## 七、核心优势 - -| 优势 | 说明 | -|------|------| -| 配置集中管理 | 所有配置在 Nacos 统一管理 | -| 环境隔离 | 通过 profile 区分环境 | -| 热更新 | 修改配置无需重启 | -| 无需重构镜像 | 改配置只需在 Nacos 操作 | -| 代码精简 | 本地只留 Nacos 连接配置 | +1. `docker compose ps` 确认 MySQL 和 Nacos 健康。 +2. 查看服务日志中是否出现 Nacos 认证和配置导入成功。 +3. 在 Nacos 控制台核对 Data ID、Group、Namespace。 +4. 检查 `common-redis-dev.yaml` 或 `common-redis-ha.yaml` 是否与 `SPRING_PROFILES_ACTIVE` 一致。 diff --git a/docs/video-auth模块目录架构、功能及接口文档.md b/docs/video-auth模块目录架构、功能及接口文档.md index 9f59a0d..da3345b 100644 --- a/docs/video-auth模块目录架构、功能及接口文档.md +++ b/docs/video-auth模块目录架构、功能及接口文档.md @@ -1,269 +1,23 @@ -# video-auth模块目录架构、功能及接口文档 +# video-auth 模块 -## 一、目录架构 +认证服务端口为 `9001`。当前实现使用 Spring Security、JWT 和 Redis 管理用户认证状态;POM 同时引入 OAuth2 相关依赖,但当前前端认证流程以项目的登录、Access Token 和 Refresh Token 接口为准。 -``` -video-auth/ -├── src/ -│ ├── main/ -│ │ ├── java/ -│ │ │ └── com/nuaa/video/auth/ -│ │ │ ├── config/ # 配置类 -| | | │ ├── RedisConfig.java # Redis配置 -│ │ │ │ └── SecurityConfig.java # 安全配置 -│ │ │ ├── controller/ # 控制器 -│ │ │ │ └── AuthController.java # 认证控制器 -│ │ │ ├── dto/ # 数据传输对象 -│ │ │ │ ├── LoginDTO.java # 登录请求DTO -│ │ │ │ ├── RegisterDTO.java # 注册请求DTO -│ │ │ │ └── TokenInfoDTO.java # 令牌信息DTO -│ │ │ ├── entity/ # 实体类 -│ │ │ │ ├── AuthUser.java # 用户实体 -│ │ │ │ ├── AuthRole.java # 角色实体 -│ │ │ │ ├── AuthPermission.java # 权限实体 -│ │ │ │ ├── AuthUserRole.java # 用户角色关联实体 -│ │ │ │ └── AuthRolePermission.java # 角色权限关联实体 -│ │ │ ├── filter/ # 过滤器 -│ │ │ │ └── JwtAuthenticationFilter.java # JWT认证过滤器 -│ │ │ ├── mapper/ # MyBatis映射接口 -│ │ │ │ ├── AuthUserMapper.java # 用户Mapper -│ │ │ │ ├── AuthRoleMapper.java # 角色Mapper -│ │ │ │ ├── AuthPermissionMapper.java # 权限Mapper -│ │ │ │ ├── AuthUserRoleMapper.java # 用户角色Mapper -│ │ │ │ └── AuthRolePermissionMapper.java # 角色权限Mapper -│ │ │ ├── service/ # 服务层 -│ │ │ │ ├── AuthUserService.java # 用户服务接口 -│ │ │ │ ├── CaptchaService.java # 验证码服务接口 -│ │ │ │ └── impl/ # 实现类 -│ │ │ │ ├── AuthUserServiceImpl.java -│ │ │ │ └── CaptchaServiceImpl.java -│ │ │ ├── utils/ # 工具类 -│ │ │ │ ├── RedisUtils.java # Redis工具类 -│ │ │ │ └── JwtUtils.java # JWT工具类 -│ │ │ └── AuthApplication.java # 启动类 -│ │ └── resources/ -│ │ ├── mapper/ # MyBatis XML映射文件 -│ │ │ └── AuthUserMapper.xml -│ │ ├── application.yml # 配置文件 -│ │ ├── application-dev.yml # 开发环境配置 -└── pom.xml -``` +## 当前功能 -## 二、功能概述 +- 用户注册、登录、验证码、退出登录、获取当前用户与用户名查询 +- Access Token 与 Refresh Token 签发/刷新,Redis 保存并清理令牌索引 +- 管理用途的登录统计、账户锁定/解锁与密码重置 +- 通过 Feign 与用户服务协作完成注册后的资料初始化等流程 -### 1. 核心功能 +## 路由前缀 -- **用户认证**:登录、注册、令牌刷新、登出 -- **安全管理**:JWT生成与验证、密码加密 -- **角色权限**:用户角色和权限的管理 -- **验证码服务**:生成和验证图形验证码 +| Controller | 前缀 | 用途 | +| --- | --- | --- | +| `AuthController` | `/auth` | 用户认证与令牌操作 | +| `AdminAuthController` | `/auth/admin` | 认证侧管理操作 | -### 2. 业务流程 +完整请求方法和参数以两个 Controller 的 Spring MVC 注解及对应 DTO 为准。所有业务请求应经由网关 `9000` 访问,不要在前端直连 `9001`。 -1. **用户注册**:用户提交注册信息 → 验证码验证 → 创建用户 → 分配默认角色 -2. **用户登录**:用户提交登录信息 → 验证用户凭证 → 生成JWT令牌 → 缓存用户认证信息 -3. **认证鉴权**:请求携带JWT令牌 → JWT过滤器验证令牌 → 提取用户信息 → 设置安全上下文 → 授权访问 +## 配置 -## 三、接口文档 - -### 1. 用户登录 - -- **URI**: `/auth/login` -- **方法**: POST -- **描述**: 用户登录并获取令牌 -- **请求Body**: - ```json - { - "username": "admin", - "password": "admin123", - "captcha": "1a2b", - "captchaKey": "abcd1234" - } - ``` -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "accessToken": "eyJhbGciOiJIUzI1NiJ9...", - "refreshToken": "nQs6NGPzAJbfw5ddsSVGY2iqAomOmGW9", - "tokenType": "Bearer", - "expiresIn": 86400, - "userId": 1, - "username": "admin" - } - } - ``` -- **错误码**: - - `400`: 参数错误(如验证码错误) - - `401`: 用户名或密码错误 - - `403`: 账号已被禁用 - -### 2. 用户注册 - -- **URI**: `/auth/register` -- **方法**: POST -- **描述**: 注册新用户 -- **请求Body**: - ```json - { - "username": "newuser", - "password": "password123", - "confirmPassword": "password123", - "email": "user@example.com", - "phone": "13800138000", - "captcha": "1a2b", - "captchaKey": "abcd1234" - } - ``` -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": "注册成功" - } - ``` -- **错误码**: - - `400`: 参数错误(如密码不匹配、验证码错误) - - `1002`: 用户名已存在 - -### 3. 获取验证码 - -- **URI**: `/auth/captcha` -- **方法**: GET -- **描述**: 生成图形验证码 -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "captchaKey": "abcd1234", - "captchaImage": "data:image/png;base64,iVBORw0KGgoAAAANSUhEU..." - } - } - ``` - -### 4. 刷新令牌 - -- **URI**: `/auth/refresh` -- **方法**: POST -- **描述**: 使用刷新令牌获取新的访问令牌 -- **请求参数**: - - `refreshToken`: 刷新令牌字符串 -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "accessToken": "eyJhbGciOiJIUzI1NiJ9...", - "refreshToken": "new_refresh_token", - "tokenType": "Bearer", - "expiresIn": 86400, - "userId": 1, - "username": "admin" - } - } - ``` -- **错误码**: - - `401`: 刷新令牌无效或已过期 - -### 5. 用户登出 - -- **URI**: `/auth/logout` -- **方法**: POST -- **描述**: 用户登出,清除令牌 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` - -### 6. 获取当前用户信息 - -- **URI**: `/auth/current` -- **方法**: GET -- **描述**: 获取当前登录用户的详细信息 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "id": 1, - "username": "admin", - "email": "admin@example.com", - "phone": "13800138000", - "status": 1, - "lastLoginTime": "2024-03-30T12:30:45", - "lastLoginIp": "192.168.1.1", - "roles": ["USER_ADMIN"] - } - } - ``` -- **错误码**: - - `401`: 未授权 - - `404`: 用户不存在 - -## 四、数据库设计 - -认证模块涉及的主要数据库表: - -### 1. auth_user (用户表) -- `id`: 用户ID (主键) -- `username`: 用户名 -- `password`: 加密密码 -- `salt`: 加密盐值 -- `email`: 邮箱 -- `phone`: 手机号 -- `status`: 状态(0:禁用,1:正常) -- `last_login_time`: 最后登录时间 -- `last_login_ip`: 最后登录IP - -### 2. auth_role (角色表) -- `id`: 角色ID (主键) -- `name`: 角色名称 -- `code`: 角色编码 -- `description`: 角色描述 - -### 3. auth_permission (权限表) -- `id`: 权限ID (主键) -- `name`: 权限名称 -- `code`: 权限编码 -- `description`: 权限描述 - -### 4. auth_user_role (用户角色关联表) -- `id`: 主键 -- `user_id`: 用户ID (外键) -- `role_id`: 角色ID (外键) - -### 5. auth_role_permission (角色权限关联表) -- `id`: 主键 -- `role_id`: 角色ID (外键) -- `permission_id`: 权限ID (外键) - -## 五、认证流程说明 - -1. **JWT认证流程**: - - 用户登录成功后,服务端生成JWT令牌和刷新令牌 - - 客户端请求时在请求头中携带JWT令牌 - - 服务端通过JwtAuthenticationFilter验证令牌 - - 验证通过后,设置SecurityContext并放行请求 - -2. **权限校验流程**: - - 用户登录时加载其角色和权限 - - 将权限信息缓存到Redis中 - - 请求鉴权时从SecurityContext获取用户信息 - - 根据用户角色和权限决定是否允许访问 - -video-auth模块提供了完整的用户认证、授权和安全管理功能,为整个视频平台提供统一的身份验证服务。 \ No newline at end of file +服务从 Nacos 加载公共、Redis 和 `video-auth.yaml` 配置。JWT 密钥、过期时间、Nacos 认证和数据库/Redis 凭据均从环境变量或 Nacos 注入,文档不保留任何真实或默认生产值。 diff --git a/docs/video-common模块目录结构.md b/docs/video-common模块目录结构.md index d5c6872..a6bbaf8 100644 --- a/docs/video-common模块目录结构.md +++ b/docs/video-common模块目录结构.md @@ -1,34 +1,17 @@ -# video-common模块实现步骤和代码 +# video-common 模块 -基于Spring Boot 3.2.4、Spring Cloud 2023.0.1和Spring Cloud Alibaba 2023.0.1.0技术栈,完整实现video-common模块。 +`video-common` 是后端共享库,不独立启动,也不提供 HTTP 接口。当前源代码位于 `backend/video-common/src/main/java/com/nuaa/video/common`。 -## 目录结构设计 +## 当前职责 -首先,创建以下目录结构: +- `config`:Feign、MinIO、MyBatis-Plus、Redis、Web MVC 配置及自动填充处理器 +- `constants`:通用常量与安全常量 +- `exception`:`BusinessException` 和全局异常处理 +- `model`:统一返回体 `Result`、分页请求 `PageRequestDTO`、基础实体 `BaseEntity`、状态码枚举 +- `utils`:JWT、Redis、MinIO、分页、日期、字符串工具 -``` -video-common/ -├── src/ -│ ├── main/ -│ │ ├── java/ -│ │ │ └── com/ -│ │ │ └── nuaa/ -│ │ │ └── video/ -│ │ │ └── common/ -│ │ │ ├── annotation/ # 自定义注解 -│ │ │ ├── config/ # 配置类 -│ │ │ ├── constants/ # 常量定义 -│ │ │ ├── exception/ # 异常处理 -│ │ │ ├── model/ # 通用数据模型 -│ │ │ │ ├── dto/ # 数据传输对象 -│ │ │ │ ├── entity/ # 实体类 -│ │ │ │ ├── enums/ # 枚举类 -│ │ │ │ └── vo/ # 视图对象 -│ │ │ ├── utils/ # 工具类 -│ │ │ └── feign/ # Feign接口 -│ │ └── resources/ -│ │ └── META-INF/ -│ │ └── spring.factories # 自动配置 -│ └── test/ -└── pom.xml -``` +## 主要依赖 + +Spring Web、Validation、OpenFeign、Sentinel、MyBatis-Plus、MySQL Driver、Redis、MinIO、JJWT、Hutool 和 Lombok。自动配置入口仍为 `src/main/resources/META-INF/spring.factories`。 + +业务服务需依赖本模块,但不应在业务模块中复制统一响应、异常、JWT 或对象存储实现。 diff --git a/docs/video-content模块目录架构、功能及接口文档.md b/docs/video-content模块目录架构、功能及接口文档.md index 5ad7ae8..d61da96 100644 --- a/docs/video-content模块目录架构、功能及接口文档.md +++ b/docs/video-content模块目录架构、功能及接口文档.md @@ -1,230 +1,22 @@ -# video-content模块目录架构、功能及接口文档 +# video-content 模块 -## 一、目录架构 +内容服务端口为 `9003`,负责视频内容域,并依赖 MinIO、RocketMQ、Redis、MySQL、FFmpeg Java wrapper 与 Nacos。 -``` -video-content/ -├── src/ -│ ├── main/ -│ │ ├── java/ -│ │ │ └── com/nuaa/video/content/ -│ │ │ ├── config/ # 配置类 -│ │ │ │ ├── SecurityConfig.java # 安全配置 -│ │ │ │ ├── MinioConfig.java # MinIO配置 -│ │ │ │ └── FFmpegConfig.java # FFmpeg配置 -│ │ │ ├── controller/ # 控制器 -│ │ │ │ ├── VideoController.java # 视频控制器 -│ │ │ │ ├── CategoryController.java # 分类控制器 -│ │ │ │ ├── TagController.java # 标签控制器 -│ │ │ │ ├── DanmakuController.java # 弹幕控制器 -│ │ │ │ ├── FavoriteController.java # 收藏夹控制器 -│ │ │ │ └── VideoStatController.java # 视频统计控制器 -│ │ │ ├── entity/ # 实体类 -│ │ │ │ ├── ContentVideo.java # 视频信息实体 -│ │ │ │ ├── ContentCategory.java # 视频分类实体 -│ │ │ │ ├── ContentTag.java # 视频标签实体 -│ │ │ │ ├── ContentVideoTag.java # 视频标签关联实体 -│ │ │ │ ├── ContentDanmaku.java # 弹幕实体 -│ │ │ │ ├── ContentVideoLike.java # 视频点赞实体 -│ │ │ │ ├── ContentVideoCoin.java # 视频投币实体 -│ │ │ │ ├── ContentUserFavorite.java # 用户收藏夹实体 -│ │ │ │ ├── ContentVideoFavorite.java # 视频收藏实体 -│ │ │ │ ├── ContentVideoStatDaily.java # 视频每日统计实体 -│ │ │ │ ├── ContentVideoReview.java # 视频审核记录实体 -│ │ │ │ └── ContentVideoPlayRecord.java # 视频播放记录实体 -│ │ │ ├── mapper/ # Mapper接口 -│ │ │ │ ├── ContentVideoMapper.java -│ │ │ │ ├── ContentCategoryMapper.java -│ │ │ │ ├── ContentTagMapper.java -│ │ │ │ ├── ContentVideoTagMapper.java -│ │ │ │ ├── ContentDanmakuMapper.java -│ │ │ │ ├── ContentVideoLikeMapper.java -│ │ │ │ ├── ContentVideoCoinMapper.java -│ │ │ │ ├── ContentUserFavoriteMapper.java -│ │ │ │ ├── ContentVideoFavoriteMapper.java -│ │ │ │ ├── ContentVideoStatDailyMapper.java -│ │ │ │ ├── ContentVideoReviewMapper.java -│ │ │ │ └── ContentVideoPlayRecordMapper.java -│ │ │ ├── dto/ # DTO对象 -│ │ │ │ ├── VideoUploadDTO.java # 视频上传DTO -│ │ │ │ ├── VideoUpdateDTO.java # 视频更新DTO -│ │ │ │ ├── VideoQueryDTO.java # 视频查询DTO -│ │ │ │ ├── FavoriteDTO.java # 收藏DTO -│ │ │ │ ├── DanmakuDTO.java # 弹幕DTO -│ │ │ │ └── PlayRecordDTO.java # 播放记录DTO -│ │ │ ├── vo/ # VO对象 -│ │ │ │ ├── VideoInfoVO.java # 视频详情VO -│ │ │ │ ├── VideoListVO.java # 视频列表VO -│ │ │ │ ├── CategoryVO.java # 分类VO -│ │ │ │ ├── TagVO.java # 标签VO -│ │ │ │ ├── DanmakuVO.java # 弹幕VO -│ │ │ │ ├── FavoriteVO.java # 收藏夹VO -│ │ │ │ └── UploadResultVO.java # 上传结果VO -│ │ │ ├── service/ # 服务层 -│ │ │ │ ├── VideoService.java # 视频服务接口 -│ │ │ │ ├── CategoryService.java # 分类服务接口 -│ │ │ │ ├── TagService.java # 标签服务接口 -│ │ │ │ ├── DanmakuService.java # 弹幕服务接口 -│ │ │ │ ├── FavoriteService.java # 收藏夹服务接口 -│ │ │ │ ├── VideoStatService.java # 视频统计服务接口 -│ │ │ │ └── impl/ # 实现类 -│ │ │ │ ├── VideoServiceImpl.java -│ │ │ │ ├── CategoryServiceImpl.java -│ │ │ │ ├── TagServiceImpl.java -│ │ │ │ ├── DanmakuServiceImpl.java -│ │ │ │ ├── FavoriteServiceImpl.java -│ │ │ │ └── VideoStatServiceImpl.java -│ │ │ ├── utils/ # 工具类 -│ │ │ │ └── VideoProcessor.java # 视频处理工具类 -│ │ │ ├── feign/ # Feign客户端 -│ │ │ │ ├── UserFeignClient.java # 用户服务客户端 -│ │ │ │ └── UserFeignClientFallbackFactory.java # 降级工厂 -│ │ │ ├── mq/ # 消息队列 -│ │ │ │ ├── producer/ # 生产者 -│ │ │ │ │ └── VideoMessageProducer.java -│ │ │ │ └── consumer/ # 消费者 -│ │ │ │ └── VideoMessageConsumer.java -│ │ │ ├── filter/ # 过滤器 -│ │ │ │ └── JwtAuthenticationFilter.java # JWT认证过滤器 -│ │ │ ├── task/ # 定时任务 -│ │ │ │ └── VideoStatsSyncTask.java # 视频统计同步任务 -│ │ │ ├── enums/ # 枚举类 -│ │ │ │ ├── VideoStatusEnum.java # 视频状态枚举 -│ │ │ │ └── DanmakuPositionEnum.java # 弹幕位置枚举 -│ │ │ └── ContentApplication.java # 启动类 -│ │ └── resources/ -│ │ ├── mapper/ # MyBatis XML映射文件 -│ │ │ ├── ContentVideoMapper.xml -│ │ │ ├── ContentTagMapper.xml -│ │ │ ├── ContentVideoTagMapper.xml -│ │ │ ├── ContentDanmakuMapper.xml -│ │ │ ├── ContentVideoLikeMapper.xml -│ │ │ ├── ContentVideoCoinMapper.xml -│ │ │ ├── ContentUserFavoriteMapper.xml -│ │ │ ├── ContentVideoFavoriteMapper.xml -│ │ │ ├── ContentVideoStatDailyMapper.xml -│ │ │ ├── ContentVideoReviewMapper.xml -│ │ │ └── ContentVideoPlayRecordMapper.xml -│ │ ├── application.yml # 主配置文件 -│ │ └── application-dev.yml # 开发环境配置 -└── pom.xml # 项目依赖配置 -``` +## 当前功能与 Controller -## 二、核心功能概述 +| Controller | 前缀 | 功能 | +| --- | --- | --- | +| `VideoController` | `/content/video` | 上传、发布、详情/列表、编辑删除、点赞、投币、收藏、分享、播放、历史、用户视频与审核 | +| `CategoryController` | `/content/category` | 分类树和分类维护 | +| `TagController` | `/content/tag` | 标签分页与维护、视频标签查询 | +| `FavoriteController` | `/content/favorite` | 收藏夹及收藏夹视频 | +| `DanmakuController` | `/content/danmaku` | 弹幕发送、全量和时间段查询 | +| `VideoStatController` | `/content/stat` | 每日、播放趋势和互动统计 | +| `AdminVideoController` | `/content/video/admin` | 管理端视频查询、审核、下架、统计 | +| `AdminCategoryController` | `/content/category/admin` | 管理端分类维护 | -### 1. 视频管理 -- 视频上传与处理:上传视频文件,自动提取封面,处理视频元数据 -- 视频CRUD:创建、更新、删除、查询视频 -- 视频搜索与过滤:按分类、标签、关键词搜索视频 +## 注意事项 -### 2. 分类与标签管理 -- 分类树管理:支持多级分类结构 -- 标签管理:创建、更新、删除标签 -- 视频关联:将视频关联到分类和标签 - -### 3. 用户互动 -- 点赞功能:用户可点赞/取消点赞视频 -- 投币功能:用户可给视频投币 -- 收藏功能:用户可将视频收藏到不同收藏夹 -- 分享功能:记录视频分享行为 - -### 4. 弹幕系统 -- 发送弹幕:用户可在视频不同时间点发送弹幕 -- 查询弹幕:获取视频指定时间段或全部弹幕 - -### 5. 数据统计 -- 浏览数统计:记录视频播放次数和播放时长 -- 互动数据统计:包括点赞、投币、收藏、评论、分享等统计 -- 每日数据统计:记录视频每日增长数据 - -### 6. 视频审核 -- 自动审核:通过消息队列的审核流程 -- 人工审核:支持管理员手动审核视频 - -### 7. 收藏夹管理 -- 收藏夹CRUD:创建、更新、删除收藏夹 -- 收藏视频:将视频收藏到指定收藏夹 -- 浏览收藏:查看收藏夹中的视频 - -## 三、主要接口说明 - -### 1. 视频相关接口 - -| 接口路径 | 方法 | 功能描述 | 权限要求 | -| ----------------------------------- | ------ | ---------------- | ---------- | -| `/content/video/upload` | POST | 上传视频文件 | 登录用户 | -| `/content/video` | POST | 创建视频记录 | 登录用户 | -| `/content/video/{id}` | GET | 获取视频详情 | 公开 | -| `/content/video/list` | GET | 分页查询视频列表 | 公开 | -| `/content/video` | PUT | 更新视频信息 | 视频所有者 | -| `/content/video/{id}` | DELETE | 删除视频 | 视频所有者 | -| `/content/video/like/{videoId}` | POST | 点赞视频 | 登录用户 | -| `/content/video/like/{videoId}` | DELETE | 取消点赞 | 登录用户 | -| `/content/video/coin/{videoId}` | POST | 投币 | 登录用户 | -| `/content/video/favorite` | POST | 收藏视频 | 登录用户 | -| `/content/video/favorite/{videoId}` | DELETE | 取消收藏 | 登录用户 | -| `/content/video/share/{videoId}` | POST | 分享视频 | 登录用户 | -| `/content/video/play` | POST | 记录播放 | 登录用户 | -| `/content/video/user/{userId}` | GET | 获取用户视频列表 | 公开 | -| `/content/video/review/{videoId}` | POST | 审核视频 | 管理员 | - -### 2. 分类与标签接口 - -| 接口路径 | 方法 | 功能描述 | 权限要求 | -| ------------------------------ | ------ | ------------ | -------- | -| `/content/category/tree` | GET | 获取分类树 | 公开 | -| `/content/category/list` | GET | 获取分类列表 | 公开 | -| `/content/category` | POST | 添加分类 | 管理员 | -| `/content/category` | PUT | 更新分类 | 管理员 | -| `/content/category/{id}` | DELETE | 删除分类 | 管理员 | -| `/content/tag/list` | GET | 获取标签列表 | 公开 | -| `/content/tag/page` | GET | 分页获取标签 | 公开 | -| `/content/tag` | POST | 添加标签 | 管理员 | -| `/content/tag` | PUT | 更新标签 | 管理员 | -| `/content/tag/{id}` | DELETE | 删除标签 | 管理员 | -| `/content/tag/video/{videoId}` | GET | 获取视频标签 | 公开 | - -### 3. 弹幕接口 - -| 接口路径 | 方法 | 功能描述 | 权限要求 | -| -------------------------------- | ---- | ------------------ | -------- | -| `/content/danmaku` | POST | 发送弹幕 | 登录用户 | -| `/content/danmaku/time` | GET | 获取指定时间段弹幕 | 公开 | -| `/content/danmaku/all/{videoId}` | GET | 获取视频所有弹幕 | 公开 | - -### 4. 收藏夹接口 - -| 接口路径 | 方法 | 功能描述 | 权限要求 | -| --------------------------------------- | ------ | ------------------ | ---------------- | -| `/content/favorite/list` | GET | 获取用户收藏夹列表 | 登录用户 | -| `/content/favorite` | POST | 创建收藏夹 | 登录用户 | -| `/content/favorite` | PUT | 更新收藏夹 | 收藏夹所有者 | -| `/content/favorite/{id}` | DELETE | 删除收藏夹 | 收藏夹所有者 | -| `/content/favorite/{favoriteId}/videos` | GET | 获取收藏夹视频 | 根据收藏夹可见性 | - -### 5. 统计接口 - -| 接口路径 | 方法 | 功能描述 | 权限要求 | -| ------------------------------------- | ---- | ---------------- | ----------------- | -| `/content/stat/daily/{videoId}` | GET | 获取视频每日统计 | 视频所有者/管理员 | -| `/content/stat/play/trend/{videoId}` | GET | 获取视频播放趋势 | 视频所有者/管理员 | -| `/content/stat/interaction/{videoId}` | GET | 获取视频互动统计 | 视频所有者/管理员 | - -## 四、与其他模块的关联 - -1. **与User模块的关联** - - 通过`UserFeignClient`调用用户服务获取用户信息 - - 更新用户统计数据(视频数、获赞数、收藏数等) - - 用户操作视频内容(播放、点赞、收藏等) - -2. **与Comment模块的潜在关联** - - 视频评论数的统计关联 - - 评论系统会引用视频信息 - -3. **与Gateway模块的关联** - - 路由与权限控制 - - API请求分发 - -4. **与Auth模块的关联** - - 用户认证与鉴权 - - JWT令牌解析和使用 +- 媒体文件保存到 MinIO,访问路径由网关/前端 Nginx 的媒体代理规则处理。 +- RocketMQ 和 FFmpeg 是当前内容服务的 Maven 依赖;具体异步消息主题、上传限制与转码行为应以 `video-content.yaml`、`application-prod.yml` 及实现类为准。 +- 当前接口清单见 `HAOVP接口列表.md`;以 Controller 注解为最终准则。 diff --git a/docs/video-gateway模块目录结构.md b/docs/video-gateway模块目录结构.md index 028725d..dc17d01 100644 --- a/docs/video-gateway模块目录结构.md +++ b/docs/video-gateway模块目录结构.md @@ -1,38 +1,25 @@ -# video-gateway模块实现步骤和代码 +# video-gateway 模块 -API网关模块(video-gateway)实现,这是微服务架构中的入口点,负责请求路由、限流、鉴权等功能。 +网关服务端口为 `9000`,是所有前端请求的统一入口。路由、公开路径与部分运行参数在 Nacos 的 `video-gateway.yaml` 中维护。 -## 目录结构设计 +## 当前代码结构 -为video-gateway模块创建以下目录结构: - -``` -video-gateway/ -├── src/ -│ ├── main/ -│ │ ├── java/ -│ │ │ └── com/ -│ │ │ └── nuaa/ -│ │ │ └── video/ -│ │ │ └── gateway/ -│ │ │ ├── config/ # 配置类 -│ │ │ ├── filter/ # 过滤器 -│ │ │ ├── handler/ # 处理器 -│ │ │ └── GatewayApplication.java # 启动类 -│ │ └── resources/ -│ │ ├── application.yml # 主配置文件 -│ │ └── application-dev.yml # 开发环境配置 -└── pom.xml +```text +config/ + CorsConfig.java # CORS + DynamicRouteConfig.java # Nacos 动态路由 + GatewayFallbackConfig.java # Sentinel / 网关降级响应 + LoadBalancerConfig.java # 负载均衡配置 +filter/ + AuthGlobalFilter.java # JWT 与白名单校验 + RequestLogFilter.java # 请求日志 +handler/ + GlobalExceptionHandler.java # WebFlux 异常响应 ``` -gateway模块具备以下功能: +## 行为说明 -1. 基于Spring Cloud Gateway的路由功能 -2. JWT认证鉴权 -3. 基于Sentinel的流量控制和服务熔断 -4. CORS跨域支持 -5. 请求日志记录 -6. 全局异常处理 -7. 动态路由配置 - -这个网关将作为整个微服务架构的入口点,为各个微服务提供统一的API访问层。 \ No newline at end of file +- 通过 Nacos 服务发现将请求路由到认证、用户、内容、评论、推荐和管理服务。 +- `AuthGlobalFilter` 对非白名单路由校验 Bearer JWT;白名单以 `GATEWAY_IGNORE_URLS` / Nacos 配置为准。 +- 使用 Spring Cloud Gateway、Sentinel Gateway、Redis Reactive 和 Actuator;内存上传阈值由 `GATEWAY_MAX_IN_MEMORY_SIZE` 与 `GATEWAY_MULTIPART_MAX_IN_MEMORY_SIZE` 配置。 +- 网关不是业务接口的最终实现位置;接口权威定义在各业务服务 Controller。 diff --git a/docs/video-user模块目录架构、功能及接口文档.md b/docs/video-user模块目录架构、功能及接口文档.md index a9e8e37..46bd65c 100644 --- a/docs/video-user模块目录架构、功能及接口文档.md +++ b/docs/video-user模块目录架构、功能及接口文档.md @@ -1,751 +1,20 @@ -# video-user模块目录架构、功能及接口文档 +# video-user 模块 -## 一、目录架构 +用户服务端口为 `9002`,负责平台用户域,不负责登录凭据签发。 -``` -video-user/ -├── src/ -│ ├── main/ -│ │ ├── java/ -│ │ │ └── com/nuaa/video/user/ -│ │ │ ├── config/ # 配置类 -│ │ │ │ ├── FeignConfig.java # Feign配置类 -│ │ │ │ ├── MinioConfig.java # Minio配置类 -│ │ │ │ └── SecurityConfig.java # 安全配置类 -│ │ │ ├── controller/ # 控制器 -│ │ │ │ ├── UserProfileController.java # 用户资料控制器 -│ │ │ │ ├── UserFollowController.java # 用户关注控制器 -│ │ │ │ ├── UserMessageController.java # 用户私信控制器 -│ │ │ │ ├── UserNotificationController.java # 用户通知控制器 -│ │ │ │ └── UserSettingController.java # 用户设置控制器 -│ │ │ ├── dto/ # 数据传输对象 -│ │ │ │ ├── UserProfileDTO.java # 用户资料DTO -│ │ │ │ ├── UserMessageDTO.java # 用户私信DTO -│ │ │ │ └── UserSettingDTO.java # 用户设置DTO -│ │ │ ├── entity/ # 实体类 -│ │ │ │ ├── UserInfo.java # 用户信息实体 -│ │ │ │ ├── UserFollow.java # 用户关注实体 -│ │ │ │ ├── UserStatDaily.java # 用户每日统计实体 -│ │ │ │ ├── UserMessage.java # 用户私信实体 -│ │ │ │ ├── UserNotification.java # 用户通知实体 -│ │ │ │ └── UserSetting.java # 用户设置实体 -│ │ │ ├── feign/ # Feign客户端 -│ │ │ │ └── AuthFeignClient.java # 认证服务Feign客户端 -│ │ │ ├── filter/ # 过滤器 -│ │ │ │ └── JwtAuthenticationFilter.java # JWT认证过滤器 -│ │ │ ├── mapper/ # MyBatis映射接口 -│ │ │ │ ├── UserInfoMapper.java # 用户信息Mapper -│ │ │ │ ├── UserFollowMapper.java # 用户关注Mapper -│ │ │ │ ├── UserStatDailyMapper.java # 用户每日统计Mapper -│ │ │ │ ├── UserMessageMapper.java # 用户私信Mapper -│ │ │ │ ├── UserNotificationMapper.java # 用户通知Mapper -│ │ │ │ └── UserSettingMapper.java # 用户设置Mapper -│ │ │ ├── service/ # 服务层 -│ │ │ │ ├── UserInfoService.java # 用户信息服务接口 -│ │ │ │ ├── UserFollowService.java # 用户关注服务接口 -│ │ │ │ ├── UserMessageService.java # 用户私信服务接口 -│ │ │ │ ├── UserNotificationService.java # 用户通知服务接口 -│ │ │ │ ├── UserSettingService.java # 用户设置服务接口 -│ │ │ │ └── impl/ # 实现类 -│ │ │ │ ├── UserInfoServiceImpl.java -│ │ │ │ ├── UserFollowServiceImpl.java -│ │ │ │ ├── UserMessageServiceImpl.java -│ │ │ │ ├── UserNotificationServiceImpl.java -│ │ │ │ └── UserSettingServiceImpl.java -│ │ │ ├── vo/ # 视图对象 -│ │ │ │ ├── UserProfileVO.java # 用户资料VO -│ │ │ │ ├── UserMessageVO.java # 用户私信VO -│ │ │ │ └── UserNotificationVO.java # 用户通知VO -│ │ │ └── UserApplication.java # 启动类 -│ │ └── resources/ -│ │ ├── mapper/ # MyBatis XML映射文件 -│ │ │ ├── UserInfoMapper.xml -│ │ │ ├── UserFollowMapper.xml -│ │ │ ├── UserMessageMapper.xml -│ │ │ └── UserNotificationMapper.xml -│ │ ├── application.yml # 主配置文件 -│ │ └── application-dev.yml # 开发环境配置 -└── pom.xml -``` +## 当前功能与 Controller -## 二、功能概述 +| Controller | 前缀 | 功能 | +| --- | --- | --- | +| `UserProfileController` | `/user/profile` | 用户资料、头像上传、公开主页、用户搜索、计数维护 | +| `UserFollowController` | `/user/follow` | 关注、取消关注、关注/粉丝列表与状态查询 | +| `UserMessageController` | `/user/message` | 私信会话、明细、已读和未读数 | +| `UserNotificationController` | `/user/notification` | 站内通知与已读状态 | +| `UserSettingController` | `/user/setting` | 个人设置 | +| `AdminUserController` | `/user/profile/admin` | 管理端用户查询、状态和统计 | -### 1. 核心功能 +## 实现要点 -- **用户资料管理**:创建、查询、更新用户资料,上传头像 -- **用户关系管理**:关注/取消关注用户,查看关注列表和粉丝列表 -- **私信系统**:发送和接收私信,管理会话和消息状态 -- **通知系统**:管理用户收到的系统通知和用户互动通知 -- **用户设置**:管理用户隐私和通知偏好设置 -- **用户数据统计**:收集和查询用户活动统计信息 - -### 2. 业务流程 - -1. **用户资料流程**: - - 用户注册时,auth服务创建基本认证信息 - - auth服务通过Feign调用user服务创建用户资料 - - 用户可随时更新个人资料信息 - -2. **用户关系流程**: - - 用户关注他人,增加自己的关注数和对方的粉丝数 - - 系统为被关注用户创建通知 - - 用户可查看关注列表和粉丝列表 - -3. **私信流程**: - - 用户发送私信给其他用户 - - 接收用户收到未读消息通知 - - 用户可查看会话列表和详细私信记录 - -4. **通知流程**: - - 系统根据用户互动(点赞、评论、关注)创建通知 - - 用户可查看不同类型的通知 - - 用户可标记通知为已读 - -## 三、接口文档 - -### 1. 用户资料接口 - -#### 1.1 初始化用户资料 - -- **URI**: `/user/profile/init` -- **方法**: POST -- **描述**: 服务内部接口,初始化用户资料(由auth服务在用户注册时调用) -- **请求参数**: - - `userId`: 用户ID - - `username`: 用户名 -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` -- **错误码**: - - `400`: 参数错误 - - `500`: 服务器内部错误 - -#### 1.2 获取当前用户资料 - -- **URI**: `/user/profile/current` -- **方法**: GET -- **描述**: 获取当前登录用户的资料 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "id": 1, - "nickname": "用户昵称", - "avatar": "头像URL", - "gender": 1, - "birthday": "1990-01-01", - "signature": "个性签名", - "region": "地区", - "followerCount": 10, - "followingCount": 20, - "videoCount": 5, - "likeCount": 100, - "level": 3, - "vipLevel": 0, - "vipExpireTime": null, - "isFollowed": false, - "createTime": "2023-01-01T12:00:00" - } - } - ``` - -#### 1.3 获取指定用户资料 - -- **URI**: `/user/profile/public/{userId}` -- **方法**: GET -- **描述**: 获取指定用户的资料 -- **路径参数**: - - `userId`: 用户ID -- **响应**: 与获取当前用户资料相同 - -#### 1.4 更新用户资料 - -- **URI**: `/user/profile` -- **方法**: PUT -- **描述**: 更新当前用户资料 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **请求Body**: - ```json - { - "nickname": "新昵称", - "gender": 1, - "birthday": "1990-01-01", - "signature": "新的个性签名", - "region": "新的地区" - } - ``` -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` - -#### 1.5 上传头像 - -- **URI**: `/user/profile/avatar` -- **方法**: POST -- **描述**: 上传用户头像 -- **请求头**: - - `Authorization`: Bearer {accessToken} - - `Content-Type`: multipart/form-data -- **请求参数**: - - `file`: 图片文件 -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": "头像URL" - } - ``` - -#### 1.6 搜索用户 - -- **URI**: `/user/profile/search` -- **方法**: GET -- **描述**: 按关键词搜索用户 -- **请求参数**: - - `keyword`: 搜索关键词 - - `page`: 页码(默认1) - - `size`: 每页数量(默认10) -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "records": [ - { - "id": 1, - "nickname": "用户昵称", - "avatar": "头像URL", - "signature": "个性签名", - "followerCount": 10, - "followingCount": 20 - } - ], - "total": 100, - "size": 10, - "current": 1, - "pages": 10 - } - } - ``` - -### 2. 用户关注接口 - -#### 2.1 关注用户 - -- **URI**: `/user/follow/{followId}` -- **方法**: POST -- **描述**: 关注指定用户 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **路径参数**: - - `followId`: 要关注的用户ID -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` -- **错误码**: - - `400`: 参数错误(如已关注) - - `404`: 用户不存在 - -#### 2.2 取消关注 - -- **URI**: `/user/follow/{followId}` -- **方法**: DELETE -- **描述**: 取消关注指定用户 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **路径参数**: - - `followId`: 要取消关注的用户ID -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` - -#### 2.3 获取关注列表 - -- **URI**: `/user/follow/following/{userId}` -- **方法**: GET -- **描述**: 获取指定用户的关注列表 -- **路径参数**: - - `userId`: 用户ID -- **请求参数**: - - `page`: 页码(默认1) - - `size`: 每页数量(默认10) -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "records": [ - { - "id": 2, - "nickname": "被关注用户", - "avatar": "头像URL", - "signature": "个性签名", - "followerCount": 100, - "followingCount": 50, - "isFollowed": true - } - ], - "total": 20, - "size": 10, - "current": 1, - "pages": 2 - } - } - ``` - -#### 2.4 获取粉丝列表 - -- **URI**: `/user/follow/followers/{userId}` -- **方法**: GET -- **描述**: 获取指定用户的粉丝列表 -- **路径参数**: - - `userId`: 用户ID -- **请求参数**: - - `page`: 页码(默认1) - - `size`: 每页数量(默认10) -- **响应**: 与关注列表格式相同 - -#### 2.5 检查是否已关注 - -- **URI**: `/user/follow/check/{followId}` -- **方法**: GET -- **描述**: 检查当前用户是否已关注指定用户 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **路径参数**: - - `followId`: 被检查的用户ID -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": true // 或 false - } - ``` - -### 3. 用户私信接口 - -#### 3.1 发送私信 - -- **URI**: `/user/message` -- **方法**: POST -- **描述**: 发送私信给指定用户 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **请求Body**: - ```json - { - "receiverId": 2, - "content": "私信内容" - } - ``` -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` - -#### 3.2 获取私信会话列表 - -- **URI**: `/user/message/list` -- **方法**: GET -- **描述**: 获取当前用户的私信会话列表 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **请求参数**: - - `page`: 页码(默认1) - - `size`: 每页数量(默认10) -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "records": [ - { - "id": 100, - "senderId": 2, - "senderNickname": "发送者昵称", - "senderAvatar": "发送者头像URL", - "receiverId": 1, - "receiverNickname": "接收者昵称", - "receiverAvatar": "接收者头像URL", - "content": "最新消息内容", - "isRead": 0, - "createTime": "2023-05-20T14:30:00" - } - ], - "total": 5, - "size": 10, - "current": 1, - "pages": 1 - } - } - ``` - -#### 3.3 获取私信详情 - -- **URI**: `/user/message/detail/{targetId}` -- **方法**: GET -- **描述**: 获取与指定用户的私信记录 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **路径参数**: - - `targetId`: 目标用户ID -- **请求参数**: - - `page`: 页码(默认1) - - `size`: 每页数量(默认20) -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "records": [ - { - "id": 100, - "senderId": 1, - "senderNickname": "当前用户", - "senderAvatar": "头像URL", - "receiverId": 2, - "receiverNickname": "目标用户", - "receiverAvatar": "头像URL", - "content": "你好", - "isRead": 1, - "createTime": "2023-05-20T14:28:00" - }, - { - "id": 101, - "senderId": 2, - "senderNickname": "目标用户", - "senderAvatar": "头像URL", - "receiverId": 1, - "receiverNickname": "当前用户", - "receiverAvatar": "头像URL", - "content": "你好,很高兴认识你", - "isRead": 1, - "createTime": "2023-05-20T14:30:00" - } - ], - "total": 2, - "size": 20, - "current": 1, - "pages": 1 - } - } - ``` - -#### 3.4 标记私信为已读 - -- **URI**: `/user/message/read/{senderId}` -- **方法**: PUT -- **描述**: 标记来自指定发送者的所有私信为已读 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **路径参数**: - - `senderId`: 发送者用户ID -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` - -#### 3.5 获取未读私信数量 - -- **URI**: `/user/message/unread/count` -- **方法**: GET -- **描述**: 获取当前用户的未读私信数量 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": 5 - } - ``` - -### 4. 用户通知接口 - -#### 4.1 获取通知列表 - -- **URI**: `/user/notification/list` -- **方法**: GET -- **描述**: 获取用户通知列表 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **请求参数**: - - `type`: 通知类型(1:点赞,2:评论,3:关注,4:系统通知,可选) - - `page`: 页码(默认1) - - `size`: 每页数量(默认10) -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "records": [ - { - "id": 1, - "type": 3, - "content": "用户小明关注了你", - "relatedId": 123, - "isRead": 0, - "createTime": "2023-05-20T10:00:00" - } - ], - "total": 50, - "size": 10, - "current": 1, - "pages": 5 - } - } - ``` - -#### 4.2 标记所有通知为已读 - -- **URI**: `/user/notification/read` -- **方法**: PUT -- **描述**: 标记当前用户的所有通知为已读 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` - -#### 4.3 标记指定通知为已读 - -- **URI**: `/user/notification/read/{notificationId}` -- **方法**: PUT -- **描述**: 标记指定通知为已读 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **路径参数**: - - `notificationId`: 通知ID -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` - -#### 4.4 获取未读通知数量 - -- **URI**: `/user/notification/unread/count` -- **方法**: GET -- **描述**: 获取当前用户的未读通知数量 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": 10 - } - ``` - -### 5. 用户设置接口 - -#### 5.1 获取用户设置 - -- **URI**: `/user/setting` -- **方法**: GET -- **描述**: 获取当前用户的设置 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": { - "privacyLevel": 1, - "commentNotify": 1, - "likeNotify": 1, - "followNotify": 1, - "systemNotify": 1 - } - } - ``` - -#### 5.2 更新用户设置 - -- **URI**: `/user/setting` -- **方法**: PUT -- **描述**: 更新当前用户的设置 -- **请求头**: - - `Authorization`: Bearer {accessToken} -- **请求Body**: - ```json - { - "privacyLevel": 2, - "commentNotify": 1, - "likeNotify": 0, - "followNotify": 1, - "systemNotify": 1 - } - ``` -- **响应**: - ```json - { - "code": 200, - "message": "操作成功", - "data": null - } - ``` - -## 四、数据库表结构 - -### 1. user_info (用户信息表) -- `id`: bigint - 用户ID (主键) -- `nickname`: varchar(64) - 昵称 -- `avatar`: varchar(256) - 头像URL -- `gender`: tinyint - 性别(0:未知,1:男,2:女) -- `birthday`: date - 生日 -- `signature`: varchar(256) - 个性签名 -- `region`: varchar(128) - 地区 -- `follower_count`: int - 粉丝数 -- `following_count`: int - 关注数 -- `video_count`: int - 视频数 -- `like_count`: int - 获赞数 -- `coin_count`: int - 硬币数 -- `favorite_count`: int - 收藏数 -- `view_count`: bigint - 播放数 -- `level`: tinyint - 等级 -- `vip_level`: tinyint - VIP等级 -- `vip_expire_time`: datetime - VIP到期时间 -- `created_by`: varchar(64) - 创建人 -- `updated_by`: varchar(64) - 更新人 -- `create_time`: datetime - 创建时间 -- `update_time`: datetime - 更新时间 - -### 2. user_follow (用户关注表) -- `id`: bigint - 主键ID -- `user_id`: bigint - 用户ID -- `follow_id`: bigint - 关注用户ID -- `create_time`: datetime - 创建时间 - -### 3. user_stat_daily (用户每日统计表) -- `id`: bigint - 主键ID -- `user_id`: bigint - 用户ID -- `stat_date`: date - 统计日期 -- `follower_increment`: int - 新增粉丝数 -- `following_increment`: int - 新增关注数 -- `video_increment`: int - 新增视频数 -- `like_increment`: int - 新增获赞数 -- `coin_increment`: int - 新增硬币数 -- `favorite_increment`: int - 新增收藏数 -- `view_increment`: bigint - 新增播放数 -- `create_time`: datetime - 创建时间 - -### 4. user_message (用户私信表) -- `id`: bigint - 主键ID -- `sender_id`: bigint - 发送者ID -- `receiver_id`: bigint - 接收者ID -- `content`: text - 消息内容 -- `is_read`: tinyint - 是否已读(0:未读,1:已读) -- `create_time`: datetime - 创建时间 - -### 5. user_notification (用户通知表) -- `id`: bigint - 主键ID -- `user_id`: bigint - 用户ID -- `type`: tinyint - 通知类型(1:点赞,2:评论,3:关注,4:系统通知) -- `content`: text - 通知内容 -- `related_id`: bigint - 相关ID -- `is_read`: tinyint - 是否已读(0:未读,1:已读) -- `create_time`: datetime - 创建时间 - -### 6. user_setting (用户设置表) -- `id`: bigint - 主键ID -- `user_id`: bigint - 用户ID -- `privacy_level`: tinyint - 隐私等级(1:公开,2:仅关注,3:私密) -- `comment_notify`: tinyint - 评论通知(0:关闭,1:开启) -- `like_notify`: tinyint - 点赞通知(0:关闭,1:开启) -- `follow_notify`: tinyint - 关注通知(0:关闭,1:开启) -- `system_notify`: tinyint - 系统通知(0:关闭,1:开启) -- `created_by`: varchar(64) - 创建人 -- `updated_by`: varchar(64) - 更新人 -- `create_time`: datetime - 创建时间 -- `update_time`: datetime - 更新时间 - -## 五、调用示例 - -### 1. 获取用户资料 - -```bash -# 使用cURL -curl -X GET http://localhost:9002/user/profile/current \ - -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." - -# 使用JavaScript -fetch('http://localhost:9002/user/profile/current', { - headers: { - 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiJ9...' - } -}) -.then(response => response.json()) -.then(data => console.log(data)); -``` - -### 2. 关注用户 - -```bash -# 使用cURL -curl -X POST http://localhost:9002/user/follow/2 \ - -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." - -# 使用JavaScript -fetch('http://localhost:9002/user/follow/2', { - method: 'POST', - headers: { - 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiJ9...' - } -}) -.then(response => response.json()) -.then(data => console.log(data)); -``` - -video-user模块是整个视频平台的核心组成部分,它提供了完整的用户信息管理、社交互动和消息通知功能,为用户提供良好的社交体验。 \ No newline at end of file +- 使用 MyBatis-Plus、MySQL 与 Redis;头像通过共享 MinIO 工具上传。 +- 头像请求限制定义在 `application.yml`:默认单文件/请求 10 MB,业务头像大小默认 5 MB,可由环境变量覆盖。 +- 服务通过 Feign 与认证、内容等服务协作。前端经网关访问,不使用文档中的旧 `localhost:9002` 直连示例。 diff --git a/docs/基于Spring Cloud的高可用在线视频平台项目架构.md b/docs/基于Spring Cloud的高可用在线视频平台项目架构.md index 1a15c3d..7fc3660 100644 --- a/docs/基于Spring Cloud的高可用在线视频平台项目架构.md +++ b/docs/基于Spring Cloud的高可用在线视频平台项目架构.md @@ -1,995 +1,47 @@ -# 基于Spring Cloud的高可用在线视频平台项目架构 +# HAOVP 当前项目架构 -## 技术栈选型 +本文档根据仓库当前代码、Maven POM、Docker Compose 和前端配置整理,版本变更后应优先检查这些文件。 -根据2024年最新技术栈和Spring Cloud Alibaba 2023.0.1.0版本,选用以下组件: +## 技术栈 -- **框架基础**: - - Spring Boot 3.2.4 - - Spring Cloud 2023.0.1 - - Spring Cloud Alibaba 2023.0.1.0 +- Java 17、Spring Boot 3.2.4、Spring Cloud 2023.0.1、Spring Cloud Alibaba 2023.0.1.0 +- Spring Cloud Gateway、Nacos Discovery/Config、OpenFeign、LoadBalancer、Sentinel +- Spring Security、JWT、MyBatis-Plus 3.5.11、MySQL 8、Redis 7 +- RocketMQ 5.1.4(内容服务依赖)、MinIO(对象存储)、FFmpeg Java wrapper 0.8.0(内容服务依赖) +- Vue 3、TypeScript、Vite、Pinia;用户端使用 Vant 4、Artplayer + danmaku plugin,管理端使用 Element Plus、ECharts +- Docker Compose;Prometheus、Grafana、Micrometer Actuator 用于监控 -- **核心组件**: - - Nacos 2.3.2 (服务注册与配置中心) - - Sentinel 1.8.6 (流量控制) - - Seata 2.0.0 (分布式事务) - - RocketMQ 5.1.4 (消息队列) +项目当前没有 Seata 或 Spark 运行时依赖,不应在架构描述中宣称已使用分布式事务或 Spark 推荐。推荐服务目前基于用户行为权重、标签兴趣、视频相似度和热门策略组合推荐。 -- **其他组件**: - - Spring Cloud Gateway (API网关) - - OpenFeign (服务调用) - - Spring Security + OAuth2 + JWT (安全认证) - - MySQL 8.0 (主数据库) - - Redis 7.0 (缓存) - - MinIO (分布式文件存储) - - FFmpeg (视频处理) - - Prometheus + Grafana (监控) - - Docker + DockerCompose (容器化部署) +## 后端模块 -## IntelliJ IDEA 创建步骤 +| 模块 | 端口 | 职责 | +| --- | ---: | --- | +| video-gateway | 9000 | 统一入口、动态路由、JWT 校验、限流与 CORS | +| video-auth | 9001 | 用户认证、验证码、Access/Refresh Token、登录统计 | +| video-user | 9002 | 用户资料、关注、私信、通知、设置 | +| video-content | 9003 | 视频、分类、标签、上传、互动、弹幕、统计与审核接口 | +| video-comment | 9004 | 评论、回复、点赞、置顶与评论治理 | +| video-recommend | 9005 | 首页/热门/相似/标签推荐与用户行为兴趣 | +| video-admin | 9006 | 管理员认证、角色权限、用户/内容/评论管理、运营统计 | -### 1. 创建父工程 (Maven项目) +各服务的 `application.yml` 只保留启动参数和 Nacos 导入配置,环境相关数据位于 Nacos:`common.yaml`、`common-redis-{dev|ha}.yaml` 和服务同名 YAML。 -1. 打开IntelliJ IDEA,选择"File" -> "New" -> "Project" -2. 选择"Maven",点击"Next" -3. 填写项目信息: - - GroupId: `com.nuaa.video` - - ArtifactId: `video-platform` - - Version: `1.0.0` -4. 点击"Finish"创建项目 +## 请求链路 -5. 修改父工程pom.xml: - -```xml - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.4 - - - - com.nuaa.video - video-platform - 1.0.0 - pom - video-platform - 基于Spring Cloud的高可用在线视频平台 - - - 17 - UTF-8 - UTF-8 - 2023.0.1 - 2023.0.1.0 - - - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - - com.alibaba.cloud - spring-cloud-alibaba-dependencies - ${spring-cloud-alibaba.version} - pom - import - - - - - - video-common - video-gateway - video-auth - video-user - video-content - video-comment - video-recommend - video-admin - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - ${java.version} - ${java.version} - ${project.build.sourceEncoding} - - - - - +```text +用户端/管理端 -> video-gateway:9000 -> Nacos 服务发现 -> 业务微服务 + -> MySQL/Redis/MinIO/RocketMQ ``` -### 2. 创建公共模块 (video-common) +业务服务之间通过 OpenFeign 调用,服务不可用时使用 fallback;网关公开路由和白名单以 Nacos 中的 `video-gateway.yaml` 为准。 -1. 右键父工程 -> New -> Module -2. 选择"Maven",点击"Next" -3. 填写模块信息: - - Name: `video-common` - - Parent: `com.nuaa.video:video-platform` -4. 点击"Finish" +## 部署形态 -5. 修改video-common的pom.xml: +- 单机开发/演示:`backend/docker-compose.yml` 或 `docker-compose.1panel.yml` +- 多节点部署:`docker-compose-node-01.yml`、`docker-compose-node-02.yml`、`docker-compose-node-03.yml`,具体节点职责以对应 compose 文件和 Debian 部署手册为准 +- 当前 MinIO 高可用部署采用 Node-01 统一业务写入、Node-02 副本同步方案,不是 MinIO 原生纠删码集群 -```xml - - - - video-platform - com.nuaa.video - 1.0.0 - - 4.0.0 - - video-common - - - - - org.projectlombok - lombok - true - - - - - org.springframework.boot - spring-boot-starter-web - - - - - org.springframework.boot - spring-boot-starter-validation - - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-discovery - - - - - org.springframework.cloud - spring-cloud-starter-openfeign - - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - - - - com.baomidou - mybatis-plus-boot-starter - 3.5.5 - - - - - mysql - mysql-connector-java - 8.0.33 - - - - - org.springframework.boot - spring-boot-starter-data-redis - - - - - io.minio - minio - 8.5.7 - - - - - cn.hutool - hutool-all - 5.8.26 - - - - - io.jsonwebtoken - jjwt-api - 0.12.3 - - - io.jsonwebtoken - jjwt-impl - 0.12.3 - runtime - - - io.jsonwebtoken - jjwt-jackson - 0.12.3 - runtime - - - -``` - -### 3. 创建API网关模块 (video-gateway) - -1. 右键父工程 -> New -> Module -2. 选择"Maven",点击"Next" -3. 填写模块信息: - - Name: `video-gateway` - - Parent: `com.nuaa.video:video-platform` -4. 点击"Finish" - -5. 修改video-gateway的pom.xml: - -```xml - - - - video-platform - com.nuaa.video - 1.0.0 - - 4.0.0 - - video-gateway - - - - - org.springframework.cloud - spring-cloud-starter-gateway - - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-discovery - - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - - - - com.alibaba.cloud - spring-cloud-alibaba-sentinel-gateway - - - - - org.springframework.boot - spring-boot-starter-actuator - - - -``` - -6. 创建application.yml: - -```yaml -server: - port: 9000 - -spring: - application: - name: video-gateway - cloud: - nacos: - discovery: - server-addr: 5.180.253.115:8848 - namespace: public - group: DEFAULT_GROUP - gateway: - discovery: - locator: - enabled: true - lower-case-service-id: true - routes: - - id: video-auth - uri: lb://video-auth - predicates: - - Path=/auth/** - filters: - - StripPrefix=1 - - id: video-user - uri: lb://video-user - predicates: - - Path=/user/** - filters: - - StripPrefix=1 - - id: video-content - uri: lb://video-content - predicates: - - Path=/content/** - filters: - - StripPrefix=1 - - id: video-comment - uri: lb://video-comment - predicates: - - Path=/comment/** - filters: - - StripPrefix=1 - - id: video-recommend - uri: lb://video-recommend - predicates: - - Path=/recommend/** - filters: - - StripPrefix=1 - - id: video-admin - uri: lb://video-admin - predicates: - - Path=/admin/** - filters: - - StripPrefix=1 - sentinel: - transport: - dashboard: 5.180.253.115:8080 - port: 8719 - eager: true - scg: - fallback: - mode: response - response-body: '{"code":500,"message":"服务不可用,请稍后再试"}' - -management: - endpoints: - web: - exposure: - include: '*' -``` - -7. 创建主启动类`GatewayApplication.java`: - -```java -package com.nuaa.video.gateway; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -public class GatewayApplication { - public static void main(String[] args) { - SpringApplication.run(GatewayApplication.class, args); - } -} -``` - -### 4. 创建认证服务模块 (video-auth) - -1. 右键父工程 -> New -> Module -2. 选择"Maven",点击"Next" -3. 填写模块信息: - - Name: `video-auth` - - Parent: `com.nuaa.video:video-platform` -4. 点击"Finish" - -5. 修改video-auth的pom.xml: - -```xml - - - - video-platform - com.nuaa.video - 1.0.0 - - 4.0.0 - - video-auth - - - - com.nuaa.video - video-common - ${project.version} - - - - - org.springframework.boot - spring-boot-starter-oauth2-resource-server - - - - - org.springframework.security - spring-security-oauth2-authorization-server - 1.2.1 - - - -``` - -6. 创建application.yml: - -```yaml -server: - port: 9001 - -spring: - application: - name: video-auth - cloud: - nacos: - discovery: - server-addr: 5.180.253.115:8848 - namespace: public - group: DEFAULT_GROUP - sentinel: - transport: - dashboard: 5.180.253.115:8080 - port: 8720 - eager: true - datasource: - url: jdbc:mysql://5.180.253.115:3306/video_auth?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: sty@G458221 - driver-class-name: com.mysql.cj.jdbc.Driver - data: - redis: - host: 5.180.253.115 - port: 6379 - password: redis_EsJ8FX - database: 0 - -mybatis-plus: - mapper-locations: classpath:mapper/*.xml - configuration: - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - -jwt: - secret: video-platform-secret-key-2024-nuaa - expiration: 86400 - token-header: Authorization -``` - -7. 创建主启动类`AuthApplication.java`: - -```java -package com.nuaa.video.auth; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -public class AuthApplication { - public static void main(String[] args) { - SpringApplication.run(AuthApplication.class, args); - } -} -``` - -### 5. 创建用户服务模块 (video-user) - -1. 右键父工程 -> New -> Module -2. 选择"Maven",点击"Next" -3. 填写模块信息: - - Name: `video-user` - - Parent: `com.nuaa.video:video-platform` -4. 点击"Finish" - -5. 修改video-user的pom.xml: - -```xml - - - - video-platform - com.nuaa.video - 1.0.0 - - 4.0.0 - - video-user - - - - com.nuaa.video - video-common - ${project.version} - - - -``` - -6. 创建application.yml: - -```yaml -server: - port: 9002 - -spring: - application: - name: video-user - cloud: - nacos: - discovery: - server-addr: 5.180.253.115:8848 - namespace: public - group: DEFAULT_GROUP - sentinel: - transport: - dashboard: 5.180.253.115:8080 - port: 8721 - eager: true - datasource: - url: jdbc:mysql://5.180.253.115:3306/video_user?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: sty@G458221 - driver-class-name: com.mysql.cj.jdbc.Driver - data: - redis: - host: 5.180.253.115 - port: 6379 - password: redis_EsJ8FX - database: 1 - -mybatis-plus: - mapper-locations: classpath:mapper/*.xml - configuration: - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl -``` - -7. 创建主启动类`UserApplication.java`: - -```java -package com.nuaa.video.user; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -public class UserApplication { - public static void main(String[] args) { - SpringApplication.run(UserApplication.class, args); - } -} -``` - -### 6. 创建内容服务模块 (video-content) - -1. 右键父工程 -> New -> Module -2. 选择"Maven",点击"Next" -3. 填写模块信息: - - Name: `video-content` - - Parent: `com.nuaa.video:video-platform` -4. 点击"Finish" - -5. 修改video-content的pom.xml: - -```xml - - - - video-platform - com.nuaa.video - 1.0.0 - - 4.0.0 - - video-content - - - - com.nuaa.video - video-common - ${project.version} - - - - - org.apache.rocketmq - rocketmq-spring-boot-starter - 2.2.3 - - - - - net.bramp.ffmpeg - ffmpeg - 0.7.0 - - - -``` - -6. 创建application.yml: - -```yaml -server: - port: 9003 - -spring: - application: - name: video-content - cloud: - nacos: - discovery: - server-addr: 5.180.253.115:8848 - namespace: public - group: DEFAULT_GROUP - sentinel: - transport: - dashboard: 5.180.253.115:8080 - port: 8722 - eager: true - datasource: - url: jdbc:mysql://5.180.253.115:3306/video_content?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: root - driver-class-name: com.mysql.cj.jdbc.Driver - data: - redis: - host: 5.180.253.115 - port: 6379 - password: redis_EsJ8FX - database: 2 - rocketmq: - name-server: 5.180.253.115:9876 - producer: - group: video-content-group - -mybatis-plus: - mapper-locations: classpath:mapper/*.xml - configuration: - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - -minio: - endpoint: http://5.180.253.115:9002 - accessKey: minioadmin - secretKey: minioadmin - bucketName: video-platform -``` - -7. 创建主启动类`ContentApplication.java`: - -```java -package com.nuaa.video.content; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -public class ContentApplication { - public static void main(String[] args) { - SpringApplication.run(ContentApplication.class, args); - } -} -``` - -### 7. 创建评论服务模块 (video-comment) - -1. 右键父工程 -> New -> Module -2. 选择"Maven",点击"Next" -3. 填写模块信息: - - Name: `video-comment` - - Parent: `com.nuaa.video:video-platform` -4. 点击"Finish" - -5. 修改video-comment的pom.xml: - -```xml - - - - video-platform - com.nuaa.video - 1.0.0 - - 4.0.0 - - video-comment - - - - com.nuaa.video - video-common - ${project.version} - - - -``` - -6. 创建application.yml: - -```yaml -server: - port: 9004 - -spring: - application: - name: video-comment - cloud: - nacos: - discovery: - server-addr: 5.180.253.115:8848 - namespace: public - group: DEFAULT_GROUP - sentinel: - transport: - dashboard: 5.180.253.115:8080 - port: 8723 - eager: true - datasource: - url: jdbc:mysql://5.180.253.115:3306/video_comment?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: sty@G458221 - driver-class-name: com.mysql.cj.jdbc.Driver - data: - redis: - host: 5.180.253.115 - port: 6379 - password: redis_EsJ8FX - database: 3 - -mybatis-plus: - mapper-locations: classpath:mapper/*.xml - configuration: - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl -``` - -7. 创建主启动类`CommentApplication.java`: - -```java -package com.nuaa.video.comment; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -public class CommentApplication { - public static void main(String[] args) { - SpringApplication.run(CommentApplication.class, args); - } -} -``` - -### 8. 创建推荐服务模块 (video-recommend) - -1. 右键父工程 -> New -> Module -2. 选择"Maven",点击"Next" -3. 填写模块信息: - - Name: `video-recommend` - - Parent: `com.nuaa.video:video-platform` -4. 点击"Finish" - -5. 修改video-recommend的pom.xml: - -```xml - - - - video-platform - com.nuaa.video - 1.0.0 - - 4.0.0 - - video-recommend - - - - com.nuaa.video - video-common - ${project.version} - - - - - org.apache.spark - spark-mllib_2.12 - 3.4.1 - - - - - org.apache.commons - commons-math3 - 3.6.1 - - - -``` - -6. 创建application.yml: - -```yaml -server: - port: 9005 - -spring: - application: - name: video-recommend - cloud: - nacos: - discovery: - server-addr: 5.180.253.115:8848 - namespace: public - group: DEFAULT_GROUP - sentinel: - transport: - dashboard: 5.180.253.115:8080 - port: 8724 - eager: true - datasource: - url: jdbc:mysql://5.180.253.115:3306/video_recommend?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: sty@G458221 - driver-class-name: com.mysql.cj.jdbc.Driver - data: - redis: - host: 5.180.253.115 - port: 6379 - password: redis_EsJ8FX - database: 4 - -mybatis-plus: - mapper-locations: classpath:mapper/*.xml - configuration: - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl -``` - -7. 创建主启动类`RecommendApplication.java`: - -```java -package com.nuaa.video.recommend; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -public class RecommendApplication { - public static void main(String[] args) { - SpringApplication.run(RecommendApplication.class, args); - } -} -``` - -### 9. 创建管理后台模块 (video-admin) - -1. 右键父工程 -> New -> Module -2. 选择"Maven",点击"Next" -3. 填写模块信息: - - Name: `video-admin` - - Parent: `com.nuaa.video:video-platform` -4. 点击"Finish" - -5. 修改video-admin的pom.xml: - -```xml - - - - video-platform - com.nuaa.video - 1.0.0 - - 4.0.0 - - video-admin - - - - com.nuaa.video - video-common - ${project.version} - - - -``` - -6. 创建application.yml: - -```yaml -server: - port: 9006 - -spring: - application: - name: video-admin - cloud: - nacos: - discovery: - server-addr: 5.180.253.115:8848 - namespace: public - group: DEFAULT_GROUP - sentinel: - transport: - dashboard: 5.180.253.115:8080 - port: 8725 - eager: true - datasource: - url: jdbc:mysql://5.180.253.115:3306/video_admin?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai - username: root - password: sty@G458221 - driver-class-name: com.mysql.cj.jdbc.Driver - data: - redis: - host: 5.180.253.115 - port: 6379 - password: redis_EsJ8FX - database: 5 - -mybatis-plus: - mapper-locations: classpath:mapper/*.xml - configuration: - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl -``` - -7. 创建主启动类`AdminApplication.java`: - -```java -package com.nuaa.video.admin; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - -@SpringBootApplication -@EnableDiscoveryClient -public class AdminApplication { - public static void main(String[] args) { - SpringApplication.run(AdminApplication.class, args); - } -} -``` +## 配置原则 +环境变量 > Nacos 配置 > 本地 `application.yml`。JWT secret、数据库/Redis/Nacos/MinIO 凭据、RocketMQ 地址均不得写入源码或文档;使用 `.env` 或部署平台密钥注入。 diff --git a/docs/开发环境搭建.md b/docs/开发环境搭建.md index 2f54427..aed79f5 100644 --- a/docs/开发环境搭建.md +++ b/docs/开发环境搭建.md @@ -1,90 +1,75 @@ -## 开发环境步骤 +# 开发环境搭建 -**安装JDK 17** +本文档对应当前仓库结构。后端配置通过 Nacos 导入,开发环境默认使用 `dev` profile;不要再按旧文档分别启动带固定密码的 MySQL、Redis、MinIO 容器。 + +## 环境要求 + +- JDK 17 +- Maven 3.9+(或使用 IDE 的 Maven) +- Node.js 18+ +- Docker Engine 与 Docker Compose v2 + +## 启动基础设施 + +在仓库根目录执行: ```bash -# Ubuntu/Debian -sudo apt install openjdk-17-jdk - -# CentOS/RHEL -sudo yum install java-17-openjdk-devel +cd backend +cp .env.example .env +docker compose up -d mysql redis redis-sentinel nacos rmqnamesrv rmqbroker minio sentinel ``` -**安装Docker和Docker Compose** +`docker-compose.yml` 会初始化业务数据库和 Nacos schema;Nacos 配置由 `sql/nacos-config-init.sql` 导入。首次启动后确认 Nacos 健康,再启动业务服务。 + +常用基础设施端口: + +| 组件 | 端口 | +| --- | --- | +| MySQL | 3306 | +| Redis / Sentinel | 6379 / 26379 | +| Nacos(HTTP/gRPC) | 8848 / 9848 / 9849 | +| RocketMQ NameServer / Broker | 9876 / 10911 | +| MinIO API / Console | 9100 / 9101 | +| Sentinel Dashboard | 8880 | + +## 启动后端 + +后端模块端口固定为:网关 `9000`、认证 `9001`、用户 `9002`、内容 `9003`、评论 `9004`、推荐 `9005`、管理 `9006`。推荐使用 Docker Compose 一次启动: ```bash -# 安装Docker -curl -fsSL https://get.docker.com | sh -sudo systemctl enable --now docker - -# 安装Docker Compose -sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose -sudo chmod +x /usr/local/bin/docker-compose +cd backend +docker compose up -d --build video-gateway video-auth video-user video-content video-comment video-recommend video-admin ``` -**安装MySQL 8.0** +本地 IDE 启动时,先启动 Nacos 及依赖,并将 `SPRING_PROFILES_ACTIVE=dev`;各模块的 `application.yml` 会从 Nacos 加载 `common.yaml`、`common-redis-dev.yaml` 和对应服务配置。 + +## 启动前端 ```bash -docker run -d --name mysql8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=video_auth -v /data/mysql:/var/lib/mysql mysql:8.0 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci +cd frontend/video-frontend-web +npm install +npm run dev + +cd ../video-frontend-admin +npm install +npm run dev ``` -**安装Redis 7.0** +用户端默认端口 `3000`,管理端默认端口 `3100`。Vite 将 `/api` 代理到 `VITE_PROXY_TARGET`,未设置时为 `http://192.168.1.101:9000`;本地开发可在对应前端目录的 `.env.local` 设置为 `http://127.0.0.1:9000`。 + +## 构建与测试 ```bash -docker run -d --name redis7 -p 6379:6379 redis:7.0-alpine +cd backend +mvn test +mvn package -DskipTests + +cd ../frontend/video-frontend-web +npm run build +cd ../video-frontend-admin +npm run build ``` -**RocketMQ 5.1.4** - -```bash -# 先安装NameServer -docker run -d --name rmqnamesrv -p 9876:9876 apache/rocketmq:5.1.4 sh mqnamesrv - -# 再安装Broker -docker run -d --name rmqbroker --link rmqnamesrv:namesr -p 10909:10909 -p 10911:10911 -e "NAMESRV_ADDR=namesrv:9876" -e "JAVA_OPTS=-Duser.home=/opt" apache/rocketmq:5.1.4 sh mqbroker -c /home/rocketmq/rocketmq-5.1.4/conf/broker.conf -``` - -**minio** - -```bash -docker run -d --name minio -p 9002:9000 -p 9001:9001 -v /data/minio:/data -e "MINIO_ROOT_USER=minioadmin" -e "MINIO_ROOT_PASSWORD=minioadmin" quay.io/minio/minio server /data --console-address ":9001" -``` - -**安装Nacos 2.3.2** - -```bash -docker run -d --name nacos -p 8848:8848 -p 9848:9848 -p 9849:9849 -e MODE=standalone -e JVM_XMS=512m -e JVM_XMX=512m nacos/nacos-server:v2.3.2 -``` - -**Sentinel Dashboard 1.8.6** - -#### **使用官方发布的 JAR 包自行构建镜像** - -1. **创建 `Dockerfile`** - - ```bash - FROM eclipse-temurin:8-jre - - # 下载 Sentinel 1.8.6 官方 JAR - RUN wget -O /sentinel-dashboard.jar \ - https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar - - # 设置时区(可选) - RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone - - EXPOSE 8080 - CMD ["java", "-Dserver.port=8080", "-Dcsp.sentinel.dashboard.server=localhost:8080", "-jar", "/sentinel-dashboard.jar"] - ``` - -2. **构建镜像** - - ```bash - docker build -t sentinel-dashboard:1.8.6 . - ``` - -3. **运行容器** - - ```bash - docker run -d --name sentinel -p 8080:8080 sentinel-dashboard:1.8.6 - ``` +## 配置安全 +`.env`、Nacos 密码、JWT secret、MinIO 密钥和初始化管理员密码只应通过环境变量提供。文档中的地址均为示例,不要提交真实凭据。