在 RHEL/CentOS/Rocky Linux 9.x 系统(目标主机 192.168.223.20)上,通过「JDK11+Maven3.9.6」编译 ZrLog 源码生成 War 包,搭配 MariaDB(数据库)+Tomcat10(应用容器)+Nginx(反向代理)完成部署,最终实现浏览器访问 ZrLog 博客系统。
源码 → Maven 构建(依赖下载 + 编译 + 打包)→ War 包 → Tomcat 部署 → Nginx 反向代理 → 浏览器访问;
一、架构说明
| 角色 | IP | 部署内容 |
|---|---|---|
| 数据库服务器 | 192.168.170.22 | MariaDB |
| 应用服务器 1 | 192.168.170.21 | ZrLog(Maven 构建) + Tomcat + 阿里云镜像优化 |
| 应用服务器 2 | 192.168.170.24 | ZrLog(Maven 构建) + Tomcat + 阿里云镜像优化 |
| Nginx Master1 | 192.168.170.20 | Nginx + Keepalived + 邮件通知 + 阿里云镜像优化 |
| Nginx Master2 | 192.168.170.23 | Nginx + Keepalived + 邮件通知 + 阿里云镜像优化 |
| VIP1 | 192.168.170.100 | Keepalived 虚拟 IP |
| VIP2 | 192.168.223.101 | Keepalived 虚拟 IP |
二、基础环境配置(所有机器)
2.1 配置阿里云 YUM 源(替换本地光盘源)
]# mount /dev/sr0 /mnt mount: /mnt: WARNING: source write-protected, mounted read-only. ]# cat /etc/yum.repos.d/ redhat.repo x.repo ]# cat /etc/yum.repos.d/x.repo [base01] name=base baseurl=/mnt/BaseOS enable=1 gpgcheck=0 [base02] name=app baseurl=/mnt/AppStream enable=1 gpgcheck=0 # 清理并更新YUM缓存 dnf clean all dnf makecache fast 关闭防火墙 关闭selinux2.2 安装基础依赖(所有机器)
dnf install -y wget vim tree net-tools三、部署 MariaDB(192.168.170.22)
# 安装MariaDB(阿里云源) dnf install -y mariadb-server # 启动并设置开机自启 systemctl start mariadb systemctl enable mariadb # 初始化数据库并配置ZrLog权限 mysql -u root -e " CREATE DATABASE IF NOT EXISTS zrlog DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER IF NOT EXISTS 'zrlog'@'%' IDENTIFIED BY 'zrlog123456'; GRANT ALL PRIVILEGES ON zrlog.* TO 'zrlog'@'%'; FLUSH PRIVILEGES; " # 开放数据库端口(可选) firewall-cmd --add-port=3306/tcp --permanent firewall-cmd --reload四、部署 ZrLog 应用服务器(192.168.170.21 和 192.168.170.24)
4.1 安装 JDK + Maven(配置阿里云镜像)
# 安装JDK 11 # 1. 上传 jdk-11.tar.gz 到 /root 目录,执行解压 cd /root tar -zxf jdk-11_linux-x64_bin.tar.gz mv jdk-11 jdk11 # 2. 配置全局环境变量(永久生效) cat > /etc/profile.d/jdk.sh << 'EOF' export JAVA_HOME=/root/jdk11 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib EOF # 3. 生效并验证 source /etc/profile.d/jdk.sh java -version # 输出JDK版本即成功 # 1. 下载 Maven 3.9.6(适配JDK 11)---直接手动上传我发的软件包 cd /root wget https://archive.apache.org/dist/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz # 2. 解压并重命名 root@zrlog ~]# tar -zxf apache-maven-3.9.14-bin.tar.gz [root@zrlog ~]# mv apache-maven-3.9.14 maven # 3. 配置全局环境变量 cat > /etc/profile.d/maven.sh << 'EOF' export MAVEN_HOME=/root/maven export PATH=$MAVEN_HOME/bin:$PATH EOF source /etc/profile.d/maven.sh mvn -version # 输出Maven版本即成功 [root@zrlog package]# vim /root/maven/conf/settings.xml ..... <mirror> <id>tencentmaven</id> <mirrorOf>central</mirrorOf> <url>https://maven.aliyun.com/repository/public/</url> </mirror> ....4.2 下载 ZrLog 源码并通过 Maven 构建
cd /root # 解压到指定目录,避免文件混乱 unzip -q zrlog-3.3.0-1811fd7-release.zip -d zrlog-src cd zrlog-src # 进入pom.xml所在目录(根据你的压缩包结构) [root@dev ~]# find /root/zrlog-src/ -name pom.xml /root/zrlog-src/META-INF/maven/com.hibegin/package/pom.xml # 配置阿里云镜像(解决依赖下载慢/失败) mv /root/zrlog-src/META-INF/maven/com.hibegin/package/pom.xml /root/zrlog-src/META-INF/maven/com.hibegin/package/pom.xml.bak # 写入全新的独立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@dev ~]# cd /root/zrlog-src/META-INF/maven/com.hibegin/package/ # 执行Maven打包(-DskipTests跳过测试,加快构建速度) mvn clean package -DskipTests4.1 复制 War 包并清理旧数据
[root@zrlog-node2 ~]# tar -xaf apache-tomcat-10.1.52.tar.gz [root@zrlog-node2 ~]# mv apache-tomcat-10.1.52 tomcat10 # 复制War包到Tomcat webapps目录,重命名为ROOT.war(直接访问根路径) [root@zrlog-node2 ~]# cd /root/zrlog-src/META-INF/maven/com.hibegin/package/ [root@zrlog-node2 package]# cp target/zrlog.war /root/tomcat10/webapps/ROOT.war # 清理Tomcat旧解压文件(避免冲突) rm -rf /root/tomcat10/webapps/ROOT4.2 启动 Tomcat 并验证
# 启动Tomcat /root/tomcat10/bin/startup.sh # 查看启动日志(确认War包解压、服务无报错) tail -f /root/tomcat10/logs/catalina.out✅ 启动成功标识:
日志中出现Server startup in XXX ms,且无ERROR级日志。
在浏览器输出:
http://192.168.170.21:8080
http://192.168.170.24:8080
五、部署 Nginx + Keepalived(192.168.170.20 和 192.168.170.23)
5.1 安装 Nginx 和 Keepalived(阿里云源)
dnf install -y nginx keepalived5.2 配置 Nginx 负载均衡
cat > /etc/nginx/conf.d/zrlog.conf << 'EOF' upstream zrlog_backend { server 192.168.170.21:8080; server 192.168.170.24:8080; } server { listen 80; server_name _; location / { proxy_pass http://zrlog_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 反向代理优化 proxy_connect_timeout 5; proxy_send_timeout 10; proxy_read_timeout 10; proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 4 32k; } } EOF # 启动Nginx并设置开机自启 systemctl start nginx systemctl enable nginx nginx -t5.3 创建 Shell 邮件发送脚本
cat > /usr/local/bin/send_mail.sh << 'EOFSH' #!/bin/bash SUBJECT="$1" MESSAGE="$2" FROM="3426888919@qq.com" #换成你自己的 TO="3426888919@qq.com" #换成你自己的 SMTP="smtp.qq.com" PORT="465" USER="3426888919@qq.com" #换成你自己的 PASS="sqdqfjjccahshiah" ##换成你自己的 curl -s --url smtps://$SMTP:$PORT \ --user "$USER:$PASS" \ --mail-from $FROM \ --mail-rcpt $TO \ --upload-file - << EOF From: <$FROM> To: <$TO> Subject: $SUBJECT $MESSAGE EOF EOFSH chmod +x /usr/local/bin/send_mail.sh5.4 创建 Keepalived 通知脚本
cat > /usr/local/bin/keepalived_mail.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_mail.sh5.5 配置 Keepalived(双主模式)
192.168.170.100(VI_1):当前服务器作为MASTER(主节点)持有这个 VIP;
192.168.170.101(VI_2):当前服务器作为BACKUP(备节点),仅当持有该 VIP 的主节点故障时才接管;
配合
notify脚本,在节点角色切换(主 / 备 / 故障)时执行自定义操作(比如切换 Nginx 配置、发送告警)。
192.168.170.20 配置:
cat > /etc/keepalived/keepalived.conf << 'EOF' global_defs { router_id LVS_20 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.170.100 } # 状态切换通知脚本:节点角色变化时执行指定脚本,并传递参数(master/backup/fault) # notify_master:节点成为主节点时执行 # notify_backup:节点成为备节点时执行 # notify_fault:节点故障时执行 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 { state BACKUP interface eth0 virtual_router_id 52 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 2222 } virtual_ipaddress { 192.168.170.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" } EOF192.168.170.23 配置:
cat > /etc/keepalived/keepalived.conf << 'EOF' global_defs { router_id LVS_23 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.170.100 } 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 { state MASTER interface eth0 virtual_router_id 52 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 2222 } virtual_ipaddress { 192.168.170.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" } EOF5.6 启动 Keepalived
systemctl start keepalived systemctl enable keepalived六、验证
在浏览器上查看
检查VIP是否生效(在负载均衡器上)
七、故障验证清单及操作步骤
1.Keepalived 单实例故障验证
VIP 漂移验证(Keepalived 主节点故障,仅停掉 Master2 的 Keepalived,保留 HAProxy )
目标
模拟 Nginx Master2(192.168.170.23)故障,验证 VIP2(192.168.170.100)漂移至 Nginx Master1(192.168.170.20);
模拟 Nginx Master2(192.168.170.23)故障
停止 192.168.170.23的 Keepalived 服务:
systemctl stop keepalived验证 VIP2 漂移
在 192.168.170.20 执行,确认 VIP2 已接管:
查看Keepalived状态日志
检查邮件通知:确认收到「Keepalived VIP 漂移提醒」邮件
2. Nginx 反向代理故障验证
目标
模拟单台 Nginx 节点故障,验证另一台 Nginx 仍能通过 VIP 提供反向代理服务;模拟 Nginx 配置错误,验证快速定位与恢复。
操作步骤
步骤 1:模拟 Nginx Master1(192.168.170.20)Nginx 服务停止
停止 192.168.223.20 的 Nginx:
[root@LB-node4 ~]# ssh root@192.168.170.20 "systemctl stop nginx"注意:
Keepalived 默认只监控自己的进程,不监控 Nginx。你停了 Nginx → Keepalived 进程还在正常跑,优先级没变,虚拟路由认为节点正常→不会释放 VIP,也不会漂移,所以,测试Nginx时,需要同时停掉Keepalived。
测试 VIP1 访问(此时 VIP1 已漂移至 23,Nginx 23 正常):
[root@LB-node5 etc]# curl -I http://192.168.170.100 # 应返回200/302测试直接访问 20 的 80 端口(应失败):
[root@LB-node5 etc]# curl -I http://192.168.170.20 # 应返回连接拒绝步骤 2:模拟 Nginx 配置错误
在 192.168.223.20 修改 Nginx 配置(故意改错):
[root@LB-node4 ~]# ssh root@192.168.170.20 "sed -i 's/upstream zrlog_backend {/upstre am zrlog_backend_error {/' /etc/nginx/conf.d/zrlog.conf"重启 Nginx(应失败):
[root@LB-node4 ~]# ssh root@192.168.170.20 "systemctl restart nginx" Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details. [root@LB-node4 ~]# ssh root@192.168.170.20 "systemctl status nginx" # 查看失败状态 × nginx.service - The nginx HTTP and reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled) Active: failed (Result: exit-code) since Wed 2026-04-22 10:54:10 CST; 15s ago Duration: 12min 10.554s Process: 18183 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS) Process: 18184 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE) CPU: 24ms 4月 22 10:54:09 LB-node4 systemd[1]: Starting The nginx HTTP and reverse proxy server... 4月 22 10:54:10 LB-node4 nginx[18184]: nginx: [emerg] host not found in upstream "zrlog_backend" in /etc/nginx/conf.d/zrlog.conf:11 4月 22 10:54:10 LB-node4 nginx[18184]: nginx: configuration file /etc/nginx/nginx.conf test failed 4月 22 10:54:10 LB-node4 systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE 4月 22 10:54:10 LB-node4 systemd[1]: nginx.service: Failed with result 'exit-code'. 4月 22 10:54:10 LB-node4 systemd[1]: Failed to start The nginx HTTP and reverse proxy server.验证配置检查:
[root@LB-node4 ~]# nginx -t # 应提示配置错误 nginx: [emerg] host not found in upstream "zrlog_backend" in /etc/nginx/conf.d/zrlog.conf:11 nginx: configuration file /etc/nginx/nginx.conf test failed恢复配置并验证:
[root@LB-node4 ~]# ssh root@192.168.170.20 "sed -i 's/upstream zrlog_backend_error {/ upstream zrlog_backend {/' /etc/nginx/conf.d/zrlog.conf" [root@LB-node4 ~]# ssh root@192.168.170.20 "nginx -t && systemctl restart nginx" nginx: [warn] conflicting server name "_" on 0.0.0.0:80, ignored nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful3. 应用服务器(ZrLog+Tomcat)故障验证
目标
模拟单台应用服务器故障,验证 Nginx 负载均衡自动切换至另一台应用服务器;模拟 Tomcat 启动失败,验证快速定位。
操作步骤
步骤 1:监控负载均衡状态
先访问 VIP1 多次,确认 Nginx 轮询分发请求至 21 和 24:
[root@LB-node4 ~]# for i in {1..5}; do curl -s http://192.168.170.100 | grep "Server IP"; done [root@LB-node4 ~]# tail -f /var/log/nginx/access.log 192.168.170.1 - - [08/Apr/2026:21:01:55 +0800] "GET /assets/css/markdown.css?t=896451687 HTTP/1.1" 200 4231 "http://192.168.170.100/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0" "-" 192.168.170.1 - - [08/Apr/2026:21:01:55 +0800] "GET /include/templates/default/css/bootstrap.min.css?t=652403316 HTTP/1.1" 200 232975 "http://192.168.170.100/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0" "-" 192.168.170.1 - - [08/Apr/2026:21:01:55 +0800] "GET /assets/css/hljs/dark.css?t=1006640559 HTTP/1.1" 200 2255 "http://192.168.170.100/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0" "-" 192.168.170.1 - - [08/Apr/2026:21:01:55 +0800] "GET /favicon.ico?t=593706770 HTTP/1.1" 200 9007 "http://192.168.170.100/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0" "-" 192.168.170.1 - - [08/Apr/2026:22:29:38 +0800] "GET / HTTP/1.1" 200 4621 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0" "-" 192.168.170.100 - - [22/Apr/2026:10:59:42 +0800] "GET / HTTP/1.1" 200 4621 "-" "curl/7.76.1" "-" 192.168.170.100 - - [22/Apr/2026:10:59:43 +0800] "GET / HTTP/1.1" 200 4622 "-" "curl/7.76.1" "-" 192.168.170.100 - - [22/Apr/2026:10:59:43 +0800] "GET / HTTP/1.1" 200 4621 "-" "curl/7.76.1" "-" 192.168.170.100 - - [22/Apr/2026:10:59:43 +0800] "GET / HTTP/1.1" 200 4622 "-" "curl/7.76.1" "-" 192.168.170.100 - - [22/Apr/2026:10:59:43 +0800] "GET / HTTP/1.1" 200 4621 "-" "curl/7.76.1" "-"步骤 2:模拟应用服务器 1(192.168.170.21)Tomcat 停止
停止 21 的 Tomcat:
[root@web-node2 package]# /root/tomcat10/bin/shutdown.sh Using CATALINA_BASE: /root/tomcat10 Using CATALINA_HOME: /root/tomcat10 Using CATALINA_TMPDIR: /root/tomcat10/temp Using JRE_HOME: /root/jdk11 Using CLASSPATH: /root/tomcat10/bin/bootstrap.jar:/root/tomcat10/bin/tomcat-juli.jar Using CATALINA_OPTS:测试 VIP1 访问(应全部转发至 24,无 502 错误):
[root@LB-node4 ~]# for i in {1..5}; do curl -I http://192.168.170.100; > done # 均返回200/302 HTTP/1.1 200 Server: nginx/1.20.1 Date: Wed, 22 Apr 2026 03:01:33 GMT Content-Type: text/html;charset=utf-8 Content-Length: 4621 Connection: keep-alive X-ZrLog: 3.3.0 HTTP/1.1 200 Server: nginx/1.20.1 Date: Wed, 22 Apr 2026 03:01:33 GMT Content-Type: text/html;charset=utf-8 Content-Length: 4621 Connection: keep-alive X-ZrLog: 3.3.0 HTTP/1.1 200 Server: nginx/1.20.1 Date: Wed, 22 Apr 2026 03:01:33 GMT Content-Type: text/html;charset=utf-8 Content-Length: 4621 Connection: keep-alive X-ZrLog: 3.3.0 HTTP/1.1 200 Server: nginx/1.20.1 Date: Wed, 22 Apr 2026 03:01:33 GMT Content-Type: text/html;charset=utf-8 Content-Length: 4621 Connection: keep-alive X-ZrLog: 3.3.0 HTTP/1.1 200 Server: nginx/1.20.1 Date: Wed, 22 Apr 2026 03:01:33 GMT Content-Type: text/html;charset=utf-8 Content-Length: 4621 Connection: keep-alive X-ZrLog: 3.3.0测试直接访问 21 的 8080 端口(应失败):
[root@LB-node4 ~]# curl -I http://192.168.170.21:8080 # 连接拒绝/超时步骤 3:模拟 Tomcat 启动失败(配置错误)
在 21 的 Tomcat 配置中故意改错(如端口冲突):
[root@web-node2 package]# ssh root@192.168.170.21 "sed -i 's/8080/8081/' /root/tomcat10/conf/server.xml"启动 Tomcat 并查看日志:
[root@web-node2 package]#ssh root@192.168.170.21 "/root/tomcat10/bin/startup.sh" [root@web-node2 package]#ssh root@192.168.170.21 "tail -f /root/tomcat10/logs/catalina.out" # 查看启动错误 Failed to initialize end point associated with ProtocolHandler ["http-nio-8081"] java.net.BindException: Address already in use恢复配置并验证 Tomcat 启动:
[root@web-node2 package]# ssh root@192.168.170.21 "sed -i 's/8081/8080/' /root/tomcat10/conf/server.xml" [root@web-node2 package]# ssh root@192.168.170.21 "/root/tomcat10/bin/shutdown.sh && /root/tomcat10/bin/startup.sh" [root@web-node2 package]# curl -I http://192.168.170.21:8080 # 恢复正常4. 数据库服务器(MariaDB)故障验证
目标
模拟数据库服务停止,验证 ZrLog 应用的错误表现;模拟数据库权限错误,验证配置有效性。
操作步骤
步骤 1:模拟 MariaDB 服务停止
停止 192.168.170.22 的 MariaDB:
[root@mysql-node1 ~]# systemctl stop mariadb测试 ZrLog 访问(应返回数据库连接错误):
curl http://192.168.170.100 # 页面显示数据库连接失败 # 查看应用服务器日志 ssh root@192.168.170.21 "tail -f /root/tomcat10/logs/catalina.out" # 显示Can't connect to MySQL server步骤 2:恢复 MariaDB 并验证
重启 MariaDB:
[root@mysql-node1 ~]# systemctl start mariadb测试 ZrLog 访问恢复:
[root@web-node2 ~]# curl -I http://192.168.170.100 #返回正常状态码 HTTP/1.1 200 Server: nginx/1.20.1 Date: Wed, 22 Apr 2026 03:37:23 GMT Content-Type: text/html;charset=utf-8 Content-Length: 4621 Connection: keep-alive X-ZrLog: 3.3.0步骤 3:模拟数据库权限错误(可选)
修改数据库用户权限:
[root@mysql-node1 ~]# mysql -u root -e "mysql -u root -e " REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'zrlog'@'%'; FLUSH PRIVILEGES;"测试 ZrLog 访问(应返回权限不足错误):
[root@mysql-node1 ~]# curl http://192.168.170.100 <html> <head><title>504 Gateway Time-out</title></head> <body> <center><h1>504 Gateway Time-out</h1></center> <hr><center>nginx/1.20.1</center> </body> </html>恢复权限:
[root@mysql-node1 ~]# mysql -u root -e " GRANT ALL PRIVILEGES ON zrlog.* TO 'zrlog'@'%'; FLUSH PRIVILEGES;"5. Maven 构建故障验证(应用服务器)
目标
模拟 Maven 依赖下载失败、源码缺失,验证构建容错与恢复。
操作步骤
步骤 1:模拟 Maven 镜像失效(阿里云镜像不可用)
修改 Maven settings.xml,注释阿里云镜像:
[root@web-node2 ~]# ssh root@192.168.170.21 "sed -i '/<mirror>/{N;N;N;N;s/^/#/}' /root /maven/conf/settings.xml" Warning: Permanently added '192.168.170.21' (ED25519) to the list of known hosts.执行 Maven 构建(应失败):
[root@web-node2 ~]# ssh root@192.168.170.21 "cd /root/zrlog-src/META-INF/maven/com.hib egin/package/ && mvn clean package -DskipTests" [ERROR] Error executing Maven. [ERROR] 1 problem was encountered while building the effective settings [FATAL] Non-parseable settings /root/maven/conf/settings.xml: expected START_TAG or END_TAG not TEXT (position: TEXT seen ...</mirror>\n -->\n# <m... @160:8) @ /root/maven/conf/settings.xml, line 160, column 8查看构建日志(提示依赖下载失败):
[root@web-node2 ~]# ssh root@192.168.170.21 "tail -f /root/zrlog/build.log" tail: 无法打开'/root/zrlog/build.log' 读取数据: 没有那个文件或目录 tail: 没有剩余文件步骤 2:恢复 Maven 镜像并验证构建
取消注释阿里云镜像:
[root@web-node2 ~]# ssh root@192.168.170.21 "sed -i '/#<mirror>/,/#<\/mirror>/{s/^#//}' /root/maven/conf/settings.xml"重新构建(应成功):
[root@web-node2 ~]# ssh root@192.168.170.21 "cd /root/zrlog-src/META-INF/maven/com.hib egin/package/ && mvn clean package -DskipTests"验证 War 包生成:
[root@web-node2 ~]# ssh root@192.168.170.21 "ls -l /root/zrlog-src/META-INF/maven/com. hibegin/package/target/zrlog.war" -rw-r--r-- 1 root root 17577002 4月 8 19:12 /root/zrlog-src/META-INF/maven/com.hibegin/package/target/zrlog.war -rw-r--r-- 1 root root 17577013 4月 22 12:02 /root/zrlog-src/META-INF/maven/com.hibegin/package/target/zrlog.war八、故障恢复验证标准
| 故障类型 | 恢复操作 | 验证标准 |
|---|---|---|
| Keepalived VIP 漂移 | 重启故障节点 Keepalived | VIP 漂移回原主节点,访问 VIP 返回 200 |
| Nginx 服务停止 | 重启 Nginx | Nginx 日志无错误,反向代理访问正常 |
| Tomcat 停止 / 配置错误 | 恢复配置并重启 Tomcat | Tomcat 日志显示启动成功,8080 端口访问正常 |
| MariaDB 停止 / 权限错误 | 重启 MariaDB / 恢复权限 | ZrLog 页面正常加载,数据库连接无错误 |
| Maven 构建失败 | 恢复镜像配置并重新构建 | 生成正常 War 包,Tomcat 部署后访问正常 |
九、注意事项
每次故障验证前,记录当前所有服务状态,避免多故障叠加;
验证完成后务必恢复所有服务至初始状态,避免影响后续验证;
邮件通知可能存在延迟(取决于 SMTP 服务器),需等待 1-2 分钟确认;
所有操作建议在测试环境执行,禁止在生产环境直接模拟故障。
十、访问
主访问地址: http://192.168.170.100
备用访问地址: http://192.168.170.101
数据库配置(构建时已自动注入)
主机: 192.168.170.22
端口: 3306
用户: zrlog
密码: zrlog123456
十一、端口说明
| 主机 | 端口 | 用途 |
|---|---|---|
| 192.168.170.20/23 | 80 | Nginx 反向代理 |
| 192.168.170.21/24 | 8080 | Tomcat(Maven 构建 ZrLog) |
| 192.168.170.22 | 3306 | MariaDB |
| 192.168.170.100/101 | 80 | Keepalived VIP(反向代理入口) |
| 所有机器 | 443(可选) | HTTPS(如需配置可基于阿里云证书优化) |
核心优化点说明
镜像替换: 全部替换为阿里云 YUM/Maven 镜像,解决国内网络构建慢、下载失败问题;
无 War 包部署: 基于 ZrLog 源码通过 Maven 构建,避免 War 包版本不一致、定制化困难问题;
反向代理优化: 增加 Nginx 反向代理缓存、超时、健康检查配置,提升访问稳定性;
配置自动化: 构建时自动注入数据库配置,减少人工修改步骤。