一、架构说明(兼容原双主双从)

角色 IP
数据库服务器 192.168.223.22
应用服务器1 192.168.223.21
应用服务器2 192.168.223.24
HAProxy  Master1 192.168.223.20
HAPRoxy Master2 192.168.223.23
VIP1 192.168.223.100
VIP2 192.168.223.101

二,基础环境配置

2.1 替换阿里云 YUM 源(替代本地光盘,更通用)

2.2 安装基础依赖(所有机器)

三、部署 MariaDB(192.168.223.22)

3.1安装MariaDB(阿里云源)并启动并设置开机自启

启动并设置开机自启且初始化数据库并配置ZrLog权限

四、部署 ZrLog 应用服务器

下载好需要的安装包

4.1 安装 JDK + Maven(配置阿里云镜像)

安装JDK 11  配置全局环境变量(永久生效) 生效并验证

下载 Maven 3.9.6(适配JDK 11)或者解压安装包

wget https://archive.apache.org/dist/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz

配置全局环境变量

编辑镜像源配置文件

4.2下载 ZrLog 源码并通过 Maven 编译

解压到指定目录,避免文件混乱

配置阿里云镜像(解决依赖下载慢/失败)写入全新的独立pom.xml(无需父POM,直接构建War包

cat > /root/zrlog-src/META-INF/maven/com.hibegin/package/pom.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 手动定义项目基本信息(替代父POM) -->
    <groupId>com.hibegin</groupId>
    <artifactId>zrlog-web</artifactId>
    <version>3.3.0</version>
    <packaging>war</packaging>
    <name>ZrLog Web</name>
    <description>ZrLog Blog System</description>

    <!-- 核心依赖(覆盖父POM的关键依赖) -->
    <dependencies>
        <!-- Servlet & JSP 核心 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <!-- Java EE 基础 -->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>8.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- 数据库驱动(ZrLog核心依赖) -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!-- 日志依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.13</version>
        </dependency>
    </dependencies>

    <!-- 构建配置(确保能打出可运行的War包) -->
    <build>
        <finalName>zrlog</finalName>
        <plugins>
            <!-- 编译插件(适配JDK11) -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <!-- War包插件(忽略缺失web.xml) -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                    <!-- 指向ZrLog的源码/资源目录(关键) -->
                    <webResources>
                        <resource>
                            <directory>/root/zrlog-src</directory>
                            <includes>
                                <include>WEB-INF/**/*</include>
                                <include>META-INF/**/*</include>
                                <include>**/*.jsp</include>
                                <include>**/*.html</include>
                                <include>**/*.css</include>
                                <include>**/*.js</include>
                            </includes>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
EOF

# 在 /root/zrlog-src/META-INF/maven/com.hibegin/package/目录下执行Maven打包(-DskipTests跳过测试,加快构建速度)

4.3复制 War 包并清理旧数据

解压Tomcat包

复制War包到Tomcat webapps目录,重命名为ROOT.war(直接访问根路径) 清理Tomcat旧解压文件(避免冲突)

4.4 启动 Tomcat 并验证

启动Tomcat 并查看启动日志(确认War包解压、服务无报错)

访问zrlog

五、HAProxy + Keepalived 适配调整(20/23 服务器)

5.1 调整 HAProxy 配置

下载HAProxy

调整配置

cat > /etc/haproxy/haproxy.cfg << 'EOF'
# global 段:全局配置(进程级参数)
global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    stats socket /var/lib/haproxy/stats
# defaults 段:为后续的 frontend/backend 设置默认参数,避免重复配置。
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option                  http-server-close
    option                  forwardfor except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

# listen stats 段:监控页面(可选)
# 提供可视化监控界面,查看后端节点健康状态、连接数等。
listen stats
    bind *:8080
    mode http
    stats enable
    stats uri /haproxy-stats
    stats auth admin:admin123
#frontend http-in 段:定义 HAProxy 接收请求的端口和转发规则。
frontend http-in
    bind *:80                      # 监听80端口(客户端访问的入口)
    default_backend zrlog_servers  # 所有请求默认转发到zrlog_servers后端
#backend zrlog_servers 段:定义后端服务器列表、负载均衡算法、健康检查规则。
#check:启用健康检查;inter 2000:每 2 秒检查一次;rise 2:连续 2 次健康则标记为可用;fall 3:连续 3 次失败则标记为不可用。
backend zrlog_servers
    balance roundrobin  # 负载均衡策略
    # 关键1:调整健康检查规则,匹配后端实际响应
    option httpchk GET / HTTP/1.1\r\nHost:\ zrlog.example.com  # 模拟带Host的请求(替换为你的ZrLog域名/IP)
    http-check expect status 200  # 若后端返回302,改为 http-check expect status 302
    # 关键2:放宽健康检查参数,避免误判
    server zrlog1 192.168.223.21:8080 check inter 5s fall 3 rise 2  # 检查间隔5s,3次失败才标记DOWN
    server zrlog2 192.168.223.24:8080 check inter 5s fall 3 rise 2
    # 关键3:转发关键请求头(ZrLog可能依赖)
    http-request set-header X-Real-IP %[src]
    http-request set-header X-Forwarded-For %[src]
EOF

重启HAProxy

5.2 Keepalived 配置(无变更,复用原双主配置)

创建 Shell 邮件发送脚本

下载

赋权 编辑邮箱的主配置文件

发送测试文件进行测试

5.3 配置keepalived

192.168.223.20 配置(同原文档)

下载keepaliveed

配置主配置文件

cat > /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
   router_id LVS_20  # 全局标识:当前Keepalived节点的唯一名称(自定义,建议含IP/主机名)
}

vrrp_instance VI_1 {  # 定义第一个VRRP实例(对应VIP1:192.168.223.100)
    state MASTER      # 初始状态:MASTER(主节点),但最终由priority决定实际角色
    interface ens160  # 绑定的网卡(必须和服务器实际网卡名一致,如ens33/eth0)
    virtual_router_id 51  # VRRP组ID(范围1-255):同一VIP的实例ID必须相同(20和23节点的VI_1都为51)
    priority 100      # 优先级(0-255):数值越高越优先成为Master,20节点VI_1优先级100 > 23节点的90
    advert_int 1      # VRRP通告间隔:1秒(节点间每秒发送一次心跳,确认对方存活)
    authentication {  # 认证配置:防止非法节点加入VRRP组
        auth_type PASS  # 认证类型:PASS(密码认证,另一种是AH,较少用)
        auth_pass 1111  # 认证密码:同一VRRP组(VI_1)的节点密码必须相同(20和23节点都为1111)
    }
    virtual_ipaddress {  # 该实例对应的VIP列表(可配置多个,空格分隔)
        192.168.223.100  # 核心:虚拟IP,客户端访问的入口
    }
    # 状态变化触发的脚本(自定义告警脚本,路径需存在且可执行)
    notify_master "/usr/local/bin/keepalived_notify.sh master"  # 成为Master时执行
    notify_backup "/usr/local/bin/keepalived_notify.sh backup"  # 成为Backup时执行
    notify_fault "/usr/local/bin/keepalived_notify.sh fault"    # 故障(如网卡宕机)时执行
}

vrrp_instance VI_2 {  # 定义第二个VRRP实例(对应VIP2:192.168.223.101)
    state BACKUP      # 初始状态:BACKUP(备节点)
    interface ens160  # 绑定同一块网卡(和VI_1一致)
    virtual_router_id 52  # VRRP组ID:VI_2的ID为52(和VI_1不同,避免冲突)
    priority 90       # 优先级:90 < 23节点VI_2的100,因此23节点是VI_2的Master
    advert_int 1      # 心跳间隔:1秒(和VI_1一致即可)
    authentication {
        auth_type PASS
        auth_pass 2222  # VI_2的认证密码(和VI_1不同,也可相同,建议区分)
    }
    virtual_ipaddress {
        192.168.223.101  # 第二个VIP
    }
    # 状态变化脚本(和VI_1共用同一个脚本,通过参数区分状态)
    notify_master "/usr/local/bin/keepalived_notify.sh master"
    notify_backup "/usr/local/bin/keepalived_notify.sh backup"
    notify_fault "/usr/local/bin/keepalived_notify.sh fault"
}
EOF

 在192.168.223.23主配置文件中配置

 192.168.223.23 配置(同原文档)
cat > /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
   router_id LVS_23  # 节点唯一标识(和20节点区分,如LVS_23)
}

vrrp_instance VI_1 {  # 对应20节点的VI_1(VIP1:100)
    state BACKUP      # 初始状态:BACKUP(备节点)
    interface ens160  # 网卡名必须和20节点一致
    virtual_router_id 51  # VRRP组ID:必须和20节点VI_1的51一致,否则无法组成同一组
    priority 90       # 优先级:90 < 20节点的100,因此20节点是VI_1的Master
    advert_int 1      # 心跳间隔:和20节点一致(1秒)
    authentication {
        auth_type PASS
        auth_pass 1111  # 认证密码:必须和20节点VI_1的1111一致,否则认证失败
    }
    virtual_ipaddress {
        192.168.223.100  # 同一VIP:100(和20节点VI_1一致)
    }
    # 状态脚本(和20节点路径一致,需确保脚本在23节点也存在)
    notify_master "/usr/local/bin/keepalived_notify.sh master"
    notify_backup "/usr/local/bin/keepalived_notify.sh backup"
    notify_fault "/usr/local/bin/keepalived_notify.sh fault"
}

vrrp_instance VI_2 {  # 对应20节点的VI_2(VIP2:101)
    state MASTER      # 初始状态:MASTER(主节点)
    interface ens160
    virtual_router_id 52  # VRRP组ID:必须和20节点VI_2的52一致
    priority 100      # 优先级:100 > 20节点的90,因此23节点是VI_2的Master
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 2222  # 认证密码:必须和20节点VI_2的2222一致
    }
    virtual_ipaddress {
        192.168.223.101  # 同一VIP:101
    }
    # 状态脚本
    notify_master "/usr/local/bin/keepalived_notify.sh master"
    notify_backup "/usr/local/bin/keepalived_notify.sh backup"
    notify_fault "/usr/local/bin/keepalived_notify.sh fault"
}
EOF

重启Keepalived

5.4创建 Keepalived 通知脚本

cat > /usr/local/bin/keepalived_notify.sh << 'EOF'
#!/bin/bash
# Keepalived 状态变更邮件通知脚本
# 参数:$1 = 状态(master/backup/fault)

# 配置参数
VIP="192.168.223.100"  # 你的 VIP 地址
TO_EMAIL="1341101176@qq.com"  # 收件邮箱
SUBJECT="【Keepalived 告警】节点状态变更"

# 拼接邮件内容
MESSAGE="
=====================================
Keepalived 节点状态变更通知
=====================================
节点状态:$1
VIP 地址:${VIP}
发生时间:$(date +'%Y-%m-%d %H:%M:%S')
=====================================
"

# 用 mailx 发送邮件
echo "${MESSAGE}" | mailx -s "${SUBJECT}" ${TO_EMAIL}

# 记录日志(可选,便于排查)
echo "$(date +'%Y-%m-%d %H:%M:%S') - 发送 Keepalived 状态邮件,状态:$1" >> /var/log/keepalived_mail.log
EOF

赋予执行权限

chmod +x /usr/local/bin/keepalived_notify.sh

查看两台主机的IP

六、验证与访问

6.1 基础验证

检查HAProxy后端健康状态

访问192.168.223.100和192.138.223.101

6.2模拟故障

20号机器故障

预期结果:23 节点同时显示192.168.223.100/32192.168.223.101/32(两个 VIP 均漂移到 23 节点)

23号机器故障

预期结果:20 节点同时显示192.168.223.100/32192.168.223.101/32(两个 VIP 均漂移到 20 节点)

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐