news 2026/4/23 13:49:21

ZrLog博客系统部署 + 高可用部署指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ZrLog博客系统部署 + 高可用部署指南

在 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.22MariaDB
应用服务器 1192.168.170.21ZrLog(Maven 构建) + Tomcat + 阿里云镜像优化
应用服务器 2192.168.170.24ZrLog(Maven 构建) + Tomcat + 阿里云镜像优化
Nginx Master1192.168.170.20Nginx + Keepalived + 邮件通知 + 阿里云镜像优化
Nginx Master2192.168.170.23Nginx + Keepalived + 邮件通知 + 阿里云镜像优化
VIP1192.168.170.100Keepalived 虚拟 IP
VIP2192.168.223.101Keepalived 虚拟 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 关闭防火墙 关闭selinux

2.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 -DskipTests

4.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/ROOT

4.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 keepalived

5.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 -t

5.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.sh

5.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.sh

5.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" } EOF

192.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" } EOF

5.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 successful

3. 应用服务器(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 漂移重启故障节点 KeepalivedVIP 漂移回原主节点,访问 VIP 返回 200
Nginx 服务停止重启 NginxNginx 日志无错误,反向代理访问正常
Tomcat 停止 / 配置错误恢复配置并重启 TomcatTomcat 日志显示启动成功,8080 端口访问正常
MariaDB 停止 / 权限错误重启 MariaDB / 恢复权限ZrLog 页面正常加载,数据库连接无错误
Maven 构建失败恢复镜像配置并重新构建生成正常 War 包,Tomcat 部署后访问正常

九、注意事项

  1. 每次故障验证前,记录当前所有服务状态,避免多故障叠加;

  2. 验证完成后务必恢复所有服务至初始状态,避免影响后续验证;

  3. 邮件通知可能存在延迟(取决于 SMTP 服务器),需等待 1-2 分钟确认;

  4. 所有操作建议在测试环境执行,禁止在生产环境直接模拟故障。

十、访问

  • 主访问地址: http://192.168.170.100

  • 备用访问地址: http://192.168.170.101

数据库配置(构建时已自动注入)

  • 主机: 192.168.170.22

  • 端口: 3306

  • 用户: zrlog

  • 密码: zrlog123456

十一、端口说明

主机端口用途
192.168.170.20/2380Nginx 反向代理
192.168.170.21/248080Tomcat(Maven 构建 ZrLog)
192.168.170.223306MariaDB
192.168.170.100/10180Keepalived VIP(反向代理入口)
所有机器443(可选)HTTPS(如需配置可基于阿里云证书优化)

核心优化点说明

  1. 镜像替换: 全部替换为阿里云 YUM/Maven 镜像,解决国内网络构建慢、下载失败问题;

  2. 无 War 包部署: 基于 ZrLog 源码通过 Maven 构建,避免 War 包版本不一致、定制化困难问题;

  3. 反向代理优化: 增加 Nginx 反向代理缓存、超时、健康检查配置,提升访问稳定性;

  4. 配置自动化: 构建时自动注入数据库配置,减少人工修改步骤。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 13:47:20

AD21 PCB设计避坑指南:模块复用中Channel Offset设置与PCB List高效操作

AD21 PCB模块复用实战&#xff1a;Channel Offset精准配置与PCB List高阶技巧 在复杂PCB设计项目中&#xff0c;模块复用功能往往能节省70%以上的重复布局时间——但当你在Altium Designer 21中尝试复用一个经过验证的模块时&#xff0c;是否遇到过明明按教程操作却始终失败的困…

作者头像 李华
网站建设 2026/4/23 13:44:45

从ST75256到ST75263:揭秘矽创GreenDriver HI-FAS技术如何重塑STN显示驱动生态

1. 从B-TYPE到HI-FAS&#xff1a;一场显示驱动技术的静默革命 第一次拿到ST75256开发板时&#xff0c;我盯着电路图愣了足足五分钟——这颗驱动IC的外围电路简单得不像传统STN方案。相比早年调试ST7529时铺满PCB的升压电容&#xff0c;现在只需要两颗0805封装的陶瓷电容就能让屏…

作者头像 李华
网站建设 2026/4/23 13:43:56

从材料到封装—晶体谐振器与振荡器的制造工艺探秘

​晶体谐振器与振荡器的卓越性能&#xff0c;源于石英晶体材料的独特物理特性与精密制造工艺的完美结合。从天然石英晶体到微米级晶片&#xff0c;从简单电极封装到集成化振荡模块&#xff0c;每一道制造工序都直接决定器件的频率精度、稳定性与可靠性。很多人只关注晶振的电气…

作者头像 李华
网站建设 2026/4/23 13:40:16

AI Agent 面试题 008:AI Agent与RPA(机器人流程自动化)有什么本质区别?

🔥 AI Agent 面试题 008:AI Agent与RPA(机器人流程自动化)有什么本质区别? 摘要:本文深入解析了「AI Agent与RPA(机器人流程自动化)有什么本质区别?」这一 AI Agent 领域的核心面试题。文章从 Agent 定义与演进 的基本概念出发,系统性地剖析了 RPA、自动化、区别 等…

作者头像 李华