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

角色 IP 部署内容
数据库服务器 192.168.223.22 MariaDB + node_exporter

应用服务器1

192.168.223.21 ZrLog + Tomcat + node_exporter
应用服务器2 192.168.223.24 ZrLog + Tomcat + node_exporter
代理服务器 1 192.168.223.20 HAProxy + Keepalived + node_exporter
代理服务器 2 192.168.223.23 HAProxy + Keepalived + node_exporter
监控服务器 192.168.223.25 Prometheus + Grafana

二、基础环境优化(所有机器)

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

关闭防火墙

2.2 安装基础依赖

dnf  install -y   wget  vim  tree net-tools zip 

三、部署 MariaDB(192.168.223.22)

安装MariaDB(阿里云源)

初始化数据库并配置ZrLog权限

四、部署 ZrLog 应用服务器

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

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

下载 Maven 3.9.6(适配JDK 11)或者解压并重命名

配置全局环境变量

加载阿里云镜像下载源

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

执行Maven打包(-DskipTests跳过测试,加快构建速度)

4.3复制 War 包并清理旧数据

解压apache-tomcat安装包

复制War包到Tomcat webapps目录,重命名为ROOT.war(直接访问根路径)

 清理Tomcat旧解压文件(避免冲突)

启动Tomcat

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

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

5.1 调整 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

5.2创建邮箱

5.3Keepalived 配置

192.168.223.20 配置(同原文档)

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 配置(同原文档)

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

5.4 创建 Keepalived 通知脚本

验证

六、验证与访问

6.1 基础验证

检查HAProxy后端健康状态

查看HAProxy Master1和HAProxy Master2的ip

正常状态

  • 20 节点:持有 VIP1(100)(VI_1 Master),不持有 VIP2(101)(VI_2 Backup);

  • 23 节点:持有 VIP2(101)(VI_2 Master),不持有 VIP1(100)(VI_1 Backup);

  • 客户端访问 VIP1 → 20 节点,访问 VIP2 → 23 节点,两台服务器同时承载业务

邮件通知是否正常

故障模拟

  • 若 20 节点宕机:23 节点的 VI_1 优先级(90)成为最高,自动接管 VIP1(100),此时 23 节点同时持有 VIP1 和 VIP2;

  • 若 23 节点宕机:20 节点的 VI_2 优先级(90)成为最高,自动接管 VIP2(101),此时 20 节点同时持有两个 VIP;

  • 故障恢复后,优先级高的节点会重新接管对应 VIP(默认抢占模式)

上面所有的配置都来自部署zrlog-HAProxy-Keepalived双主双从

下面部署Prometheus + Grafana

七、部署Prometheus + Grafana过程

7.1 安装 Prometheus(加入一台新机器)

安装基本工具关闭防火墙等安全措施

下载 Prometheus 包

wget https://github.com/prometheus/prometheus/releases/download/v2.51.2/prometheus-2.51.2.linux-amd64.tar.gz

解压

 创建配置目录并赋权

 配置 Prometheus(严格保证YAML缩进/语法)

校验

启动 Prometheus(后台运行,绑定所有网卡)并校验

7.2 安装 Grafana(192.168.223.25)

添加 Grafana 官方源(解决包不存在问题)

安装 Grafana 及依赖

启动并设置开机自启

检查端口监听并查看 Grafana 日志(排查启动故障)

7.3 安装 node_exporter(所有被监控节点数据库节点除外)

下载 node_exporter 包

wget https://github.com/prometheus/node_exporter/releases/download/v1.8.0/node_exporter-1.8.0.linux-amd64.tar.gz

解压 启动node_exporter(后台运行,绑定所有网卡)并校验状态

7.4安装 mysqld_exporter(仅数据库服务器 192.168.223.22)

解压并创建认证配置文件(存放MySQL账号) 后台启动 mysqld_exporter(默认端口9104)

校验启动

八、Web 页面配置

8.1访问地址

服务 地址 默认账号 注意事项
Prometheus http://192.168.223.25:9090 无需登录 确保服务器防火墙 / SELinux 已关闭
Grafana http://192.168.223.25:3000 admin / admin 首次登录强制修改密码

查看Prometheus的节点信息

3.2 Grafana 配置步骤

访问地址登录

位置 面板标题 PromQL 可视化类型
服务器 CPU 使用率 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[1m])) * 100) Time series
服务器内存使用率 100 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100) Time series
MySQL 当前连接数 mysql_global_status_threads_connected Stat(大数字)
MySQL QPS irate(mysql_global_status_queries[5m]) Time series

完成如图所示

Logo

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

更多推荐