#!/bin/bash # ============================================================ # 高可用集群部署脚本 # 用法: ./deploy-ha.sh # node-id: 1, 2, 3 # action: init, start, stop, restart, status # ============================================================ set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 日志函数 log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } # 检查参数 if [ $# -lt 2 ]; then echo "用法: $0 " echo "node-id: 1, 2, 3" echo "action: init, start, stop, restart, status, mysql-master, mysql-slave, redis-master, redis-slave" exit 1 fi NODE_ID=$1 ACTION=$2 ENV_FILE="config/.env.node-0${NODE_ID}" # 检查环境文件 if [ ! -f "$ENV_FILE" ]; then log_error "环境文件不存在: $ENV_FILE" exit 1 fi # 加载环境变量 log_info "加载环境变量: $ENV_FILE" export $(grep -v '^#' $ENV_FILE | xargs) log_info "==========================================" log_info "节点ID: $NODE_ID" log_info "主机IP: $HOST_IP" log_info "操作: $ACTION" log_info "==========================================" # 初始化函数 init_node() { log_step "初始化节点 $NODE_ID..." # 创建必要目录 log_info "创建数据目录..." mkdir -p data/mysql data/redis data/nacos data/rocketmq data/minio logs/nginx # 复制配置文件 log_info "配置文件准备..." # MySQL配置 if [ "$NODE_ID" == "1" ]; then cp config/mysql/my-master.cnf config/mysql/my.cnf log_info "MySQL配置: 主节点" else cp config/mysql/my-slave.cnf config/mysql/my.cnf log_info "MySQL配置: 从节点" fi # Redis配置 if [ "$NODE_ID" == "1" ]; then cp config/redis/redis-master.conf config/redis/redis.conf log_info "Redis配置: 主节点" else cp config/redis/redis-slave.conf config/redis/redis.conf fi # RocketMQ Broker配置 if [ "$NODE_ID" == "2" ]; then cp config/rocketmq/broker-a.conf config/rocketmq/broker.conf log_info "RocketMQ配置: Broker-A" elif [ "$NODE_ID" == "3" ]; then cp config/rocketmq/broker-b.conf config/rocketmq/broker.conf log_info "RocketMQ配置: Broker-B" fi # 设置Docker网络 log_info "创建Docker网络..." docker network create ha-network 2>/dev/null || true log_info "节点初始化完成!" } # 启动基础设施 start_infrastructure() { log_step "启动基础设施..." # 按顺序启动服务 log_info "启动MySQL..." docker compose --env-file $ENV_FILE up -d mysql sleep 30 log_info "等待MySQL就绪..." until docker exec mysql mysqladmin ping -h localhost -uroot -p${MYSQL_ROOT_PASSWORD} --silent 2>/dev/null; do log_warn "等待MySQL启动..." sleep 5 done log_info "MySQL已就绪" # 初始化数据库 (仅主节点) if [ "$NODE_ID" == "1" ]; then log_info "初始化数据库..." docker exec -i mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} < sql/init.sql 2>/dev/null || true log_info "数据库初始化完成" fi log_info "启动Redis..." docker compose --env-file $ENV_FILE up -d redis redis-sentinel sleep 10 log_info "启动Nacos..." docker compose --env-file $ENV_FILE up -d nacos sleep 30 log_info "等待Nacos就绪..." until curl -s http://localhost:8848/nacos/v1/console/health/liveness | grep -q "UP" 2>/dev/null; do log_warn "等待Nacos启动..." sleep 5 done log_info "Nacos已就绪" log_info "启动RocketMQ NameServer..." docker compose --env-file $ENV_FILE up -d rmqnamesrv sleep 10 # Broker仅Node-02和Node-03启动 if [ "$NODE_ID" != "1" ]; then log_info "启动RocketMQ Broker..." docker compose --env-file $ENV_FILE up -d rmqbroker sleep 10 fi log_info "启动MinIO..." docker compose --env-file $ENV_FILE up -d minio sleep 10 log_info "启动Sentinel..." docker compose --env-file $ENV_FILE up -d sentinel log_info "基础设施启动完成!" } # 启动微服务 start_microservices() { log_step "启动微服务..." log_info "启动网关服务..." docker compose --env-file $ENV_FILE up -d video-gateway sleep 15 log_info "启动认证服务..." docker compose --env-file $ENV_FILE up -d video-auth sleep 15 log_info "启动用户服务..." docker compose --env-file $ENV_FILE up -d video-user sleep 15 log_info "启动内容服务..." docker compose --env-file $ENV_FILE up -d video-content sleep 15 log_info "启动评论服务..." docker compose --env-file $ENV_FILE up -d video-comment sleep 15 log_info "启动推荐服务..." docker compose --env-file $ENV_FILE up -d video-recommend sleep 15 log_info "启动管理后台服务..." docker compose --env-file $ENV_FILE up -d video-admin log_info "微服务启动完成!" } # 启动Nginx start_nginx() { log_step "启动Nginx负载均衡..." docker compose --env-file $ENV_FILE up -d nginx log_info "Nginx启动完成!" } # 停止所有服务 stop_all() { log_step "停止所有服务..." docker compose --env-file $ENV_FILE down log_info "所有服务已停止" } # 查看状态 check_status() { log_step "服务状态检查..." echo "" docker compose --env-file $ENV_FILE ps echo "" log_info "检查服务健康状态..." services=("video-gateway:9000" "video-auth:9001" "video-user:9002" "video-content:9003" "video-comment:9004" "video-recommend:9005" "video-admin:9006") for service in "${services[@]}"; do name=$(echo $service | cut -d':' -f1) port=$(echo $service | cut -d':' -f2) if curl -s "http://localhost:$port/actuator/health" | grep -q "UP" 2>/dev/null; then log_info "$name: ${GREEN}健康${NC}" else log_warn "$name: ${YELLOW}未响应${NC}" fi done } # 配置MySQL主从复制 setup_mysql_replication() { log_step "配置MySQL主从复制..." if [ "$NODE_ID" == "1" ]; then log_info "配置主节点..." # 创建复制用户 docker exec mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} <;" echo "START SLAVE;" echo "" fi } # 配置Redis主从复制 setup_redis_replication() { log_step "配置Redis主从复制..." if [ "$NODE_ID" != "1" ]; then log_info "配置从节点连接主节点..." docker exec redis redis-cli -a ${REDIS_PASSWORD} REPLICAOF 192.168.1.101 6379 log_info "Redis从节点配置完成" else log_info "当前为主节点,无需配置" fi } # 初始化MinIO init_minio() { log_step "初始化MinIO..." # 等待MinIO就绪 until curl -s http://localhost:9000/minio/health/live > /dev/null 2>&1; do log_warn "等待MinIO启动..." sleep 5 done log_info "创建存储桶..." docker run --rm --network ha-network minio/mc <