# Debian 12 高可用集群部署手册 ## 一、环境准备 ### 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) | ### 1.2 Debian 12 安装建议 下载地址: https://www.debian.org/distrib/ 推荐使用 **Debian 12 Netinst** 最小化安装: - 选择 "无图形界面" 安装 - 仅安装 SSH server 和标准系统工具 - 使用 LVM 分区,便于扩展 ### 1.3 系统初始化 在每台虚拟机上执行以下操作: ```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" ``` --- ## 二、部署步骤 ### 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 镜像 (三个节点都需要执行) 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 # 先只启动基础设施 (MySQL, Redis, Nacos 等) docker compose -f docker-compose-node-01.yml up -d mysql redis redis-sentinel nacos rmqnamesrv rmqbroker 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 # 启动基础设施 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 从节点,数据库会通过主从复制自动同步,无需手动初始化。 ```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 # 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 退出 # 验证数据库已自动创建 docker exec mysql mysql -uroot -proot123456 -e "SHOW DATABASES;" ``` ### 2.7 配置 MySQL 主从复制 #### 在 Node-01 (主节点) 创建复制用户 ```bash docker exec 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 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 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) 1. **创建命名空间**: 命名空间 → 新建命名空间 → 命名空间ID: `public`, 命名空间名: `公共命名空间` 2. **添加配置文件**: 配置管理 → 配置列表 → 创建配置 - Data ID: `video-gateway.yaml` - Group: `DEFAULT_GROUP` - 配置内容: 参考 `config/nacos-config/` 目录下的配置文件 3. **重复以上步骤添加其他服务的配置** ### 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 ``` --- ## 三、端口分配汇总 ### 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 | 对象存储API | | **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),避免与微服务端口冲突 - **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;" ``` ### 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`) --- ## 七、日常运维 ### 7.1 日志查看 ```bash # 查看服务日志 docker logs -f --tail 100 video-gateway docker logs -f --tail 100 video-auth # 查看所有服务状态 docker compose -f docker-compose-node-01.yml ps ``` ### 7.2 服务重启 ```bash # 重启单个服务 docker restart video-gateway # 重启所有服务 docker compose -f docker-compose-node-01.yml restart ``` ### 7.3 数据备份 ```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 # 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 │ │ └─────────────────┘ └─────────────────┘ │ (主节点) (从节点) └─────────────────────────────────────────────────────────────────────────────┘ ```