一、架构概述

🔧 架构目标

通过一套简洁稳定的方案,实现以下功能:

  • 单VIP高可用访问:外部用户只访问一个域名 / IP;

  • Nginx负载均衡:在两台服务器间分担请求;

  • Java后端 + Vue前端 完整分离部署;

  • Keepalived健康检测:故障自动切换,保证服务不中断;

  • 会话保持:通过 ip_hash 确保同一用户始终访问同一台后端。


二、架构拓扑

外部用户
    ↓ (DNS: your-domain.com → 192.168.1.10)
    ↓
[虚拟IP: 192.168.1.10]
    ├── 服务器A (192.168.1.100) [主]
    │   ├── Nginx(负载均衡+静态资源)
    │   ├── Vue应用(端口8080)
    │   └── Java服务(端口8081)
    │
    └── 服务器B (192.168.1.200) [备]
        ├── Nginx(负载均衡+静态资源)
        ├── Vue应用(端口8080)
        └── Java服务(端口8081)

Keepalived 在两台服务器间保持心跳,当主机异常时,VIP 自动切换 到备用机。

三、环境准备

✅ 基础环境

组件 说明
OS CentOS 7.x
Nginx 反向代理 + 静态资源分发
Java 8+ 后端应用运行环境
Vue 构建产物 前端打包文件
Keepalived 实现VIP漂移与健康检查

四、服务部署

4.1 目录规划

/opt/vue-app/           # Vue前端
/opt/java-app/          # Java后端
/usr/local/nginx/       # Nginx安装目录
/etc/keepalived/        # Keepalived配置

4.2 Java服务配置

1️⃣ 放置应用
mkdir -p /opt/java-app
cp app.jar /opt/java-app/

2️⃣ 创建 systemd 启动项

cat > /etc/systemd/system/java-app.service << EOF
[Unit]
Description=Java Application Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/java-app
ExecStart=/usr/bin/java -jar app.jar --server.port=8081
Environment=SPRING_PROFILES_ACTIVE=prod
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable java-app
systemctl start java-app

4.3 Vue前端部署

1️⃣ 放置前端文件
mkdir -p /opt/vue-app/dist
# 将 Vue 打包后的 dist 文件上传到此目录

2️⃣ 启动本地静态文件服务

cat > /etc/systemd/system/vue-app.service << EOF
[Unit]
Description=Vue Application Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/vue-app
ExecStart=/usr/bin/python3 -m http.server 8080
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable vue-app
systemctl start vue-app

五、Nginx 配置(负载均衡 + 静态代理)

编辑主配置文件:

vi /usr/local/nginx/conf/nginx.conf

完整内容如下 👇

user nginx;
worker_processes auto;
error_log /usr/local/nginx/logs/error.log warn;
pid /usr/local/nginx/logs/nginx.pid;

events {
    worker_connections 1024;
    use epoll;
}

http {
    include mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" '
                    'upstream: $upstream_addr';

    access_log /usr/local/nginx/logs/access.log main;

    sendfile on;
    keepalive_timeout 65;
    client_max_body_size 100m;

    # Vue集群
    upstream vue_frontend {
        ip_hash;
        server 127.0.0.1:8080;
        server 192.168.1.200:8080;
    }

    # Java集群
    upstream java_backend {
        ip_hash;
        server 127.0.0.1:8081;
        server 192.168.1.200:8081;
    }

    server {
        listen 80;
        server_name _;

        # Vue 静态文件
        location / {
            root /opt/vue-app/dist;
            try_files $uri $uri/ @vue_proxy;
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        location @vue_proxy {
            proxy_pass http://vue_frontend;
            include proxy_params;
        }

        # Java API代理
        location /api/ {
            proxy_pass http://java_backend;
            include proxy_params;
            proxy_connect_timeout 5s;
            proxy_read_timeout 30s;
            proxy_send_timeout 30s;

            # 跨域支持
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
            if ($request_method = 'OPTIONS') { return 204; }
        }

        # 健康检查
        location /health {
            access_log off;
            return 200 "healthy\n";
        }

        # Nginx状态监控
        location /nginx_status {
            stub_status on;
            access_log off;
            allow 127.0.0.1;
            allow 192.168.1.0/24;
            deny all;
        }
    }
}

保存并启动:

systemctl enable nginx
systemctl start nginx

六、Keepalived 高可用配置

6.1 主机配置 /etc/keepalived/keepalived.conf.

! Configuration File for keepalived

global_defs {
    router_id server_a
    script_user root
    enable_script_security
}

vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 2
    fall 3
    rise 2
}

vrrp_script chk_java_app {
    script "/etc/keepalived/check_java_app.sh"
    interval 3
    fall 2
    rise 1
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.10/24
    }
    track_script {
        chk_nginx
        chk_java_app
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}

备用机只需将这部分替换:

state BACKUP
priority 100
router_id server_b

6.2 健康检查脚本

/etc/keepalived/check_nginx.sh
#!/bin/bash
if ! pgrep -x "nginx" >/dev/null; then
    systemctl restart nginx
    sleep 2
fi
if ! curl -s http://127.0.0.1/health >/dev/null; then
    exit 1
fi
exit 0

七、启动与验证

7.1 启动所有服务

systemctl enable vue-app java-app nginx keepalived
systemctl start vue-app java-app nginx keepalived

7.2 验证主节点状态

ip addr show eth0 | grep 192.168.1.10
curl http://192.168.1.10/
curl http://192.168.1.10/api/health
curl http://192.168.1.10/nginx_status

八、故障转移测试

🔄 模拟主机故障

ssh 192.168.1.100 "systemctl stop java-app"

观察 VIP 是否自动切换到备机:

ssh 192.168.1.200 "ip addr show eth0 | grep 192.168.1.10"

恢复主机:

ssh 192.168.1.100 "systemctl start java-app"

九、监控脚本(可选)

/usr/local/bin/check_full_status.sh

#!/bin/bash
VIP="192.168.1.10"
SERVERS=("192.168.1.100" "192.168.1.200")

echo "=== 架构状态检查 ==="
echo "时间: $(date)"
echo "VIP: $VIP"

for server in "${SERVERS[@]}"; do
    echo -e "\n--- $server ---"
    for svc in nginx vue-app java-app keepalived; do
        echo -n "$svc: "
        ssh $server "systemctl is-active $svc"
    done
done

echo -e "\n=== 外部访问 ==="
curl -s http://$VIP/ >/dev/null && echo "前端: 正常" || echo "前端: 异常"
curl -s http://$VIP/api/health >/dev/null && echo "后端: 正常" || echo "后端: 异常"

🔚 总结

功能 实现方式
单VIP访问 Keepalived 提供虚拟IP
高可用切换 健康检查 + 自动漂移
负载均衡 Nginx upstream + ip_hash
前后端分离 Vue静态资源 + Java REST API
故障自愈 脚本自动重启关键服务
会话保持 用户IP哈希绑定同一节点
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐