1. 引言
在工业物联网场景中,起重机安全监控系统的稳定运行直接关系到生产安全。本文将基于一套真实的双机高可用部署方案,详细讲解后端服务(Spring Boot)与前端应用(Vue + Nginx)在 Linux 服务器上的部署、配置与维护全流程。无论你是运维工程师还是全栈开发者,都能从中获得可直接落地的实践经验。
2. 系统架构与高可用设计
本平台部署于 两台物理工控机(Node A 与 Node B) 上,采用高可用架构设计,确保监控系统和数据采集的不间断运行。
2.1 核心设计方案
- 双节点冗余部署:Node A 和 Node B 分别部署完整的前端(Nginx 静态托管)和后端(Spring Boot 服务)程序。
- 底层数据库实时同步(达梦双写) :
- 底层达梦数据库(DM8)配置了 Data Watch 双机热备 物理归档同步方案。
- 数据在主库(Primary)与备库(Standby)之间进行实时双写与增量对齐,确保数据一致性。
- 本地化数据库访问 :
- 为了保证高性能与服务高内聚,每一个节点的 Spring Boot 服务仅连接自己本机的数据库服务 (连接配置为
127.0.0.1:5236)。 - Node A 的后端仅读写 Node A 的数据库,Node B 的后端仅读写 Node B 的数据库。
- 为了保证高性能与服务高内聚,每一个节点的 Spring Boot 服务仅连接自己本机的数据库服务 (连接配置为
- 网络层 Keepalived 高可用 :
- 在两台工控机上配置 Keepalived,设置统一的 虚拟 IP(VIP:
192.160.6.9)。 - 所有外部访问流量(用户浏览器、PLC 数据写入等)全部通过 VIP 进行接入。
- 虚拟 IP 会漂移并绑定到当前的"主节点"。当主节点发生硬件故障、网络故障或 Spring Boot 服务挂掉时,虚拟 IP 会自动漂移到备用节点,实现秒级无感知切换。
- 在两台工控机上配置 Keepalived,设置统一的 虚拟 IP(VIP:
2.2 软硬件配置要求
- 硬件设备:2 台物理工控机(Node A 与 Node B)
- 操作系统:银河麒麟操作系统(Kylin OS,基于 Linux 内核)
- 数据库系统:达梦数据库 DM8(配置 Data Watch 主备同步)
- 主要运行软件 :
- JDK 1.8(后端服务运行环境)
- Nginx(前端静态托管及反向代理服务)
- Keepalived(虚拟 IP 漂移及高可用路由)
2.3 系统架构拓扑图
#mermaid-svg-yMK0xgZwBAdoyJzF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yMK0xgZwBAdoyJzF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yMK0xgZwBAdoyJzF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yMK0xgZwBAdoyJzF .error-icon{fill:#552222;}#mermaid-svg-yMK0xgZwBAdoyJzF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yMK0xgZwBAdoyJzF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yMK0xgZwBAdoyJzF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yMK0xgZwBAdoyJzF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yMK0xgZwBAdoyJzF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yMK0xgZwBAdoyJzF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yMK0xgZwBAdoyJzF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yMK0xgZwBAdoyJzF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yMK0xgZwBAdoyJzF .marker.cross{stroke:#333333;}#mermaid-svg-yMK0xgZwBAdoyJzF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yMK0xgZwBAdoyJzF p{margin:0;}#mermaid-svg-yMK0xgZwBAdoyJzF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yMK0xgZwBAdoyJzF .cluster-label text{fill:#333;}#mermaid-svg-yMK0xgZwBAdoyJzF .cluster-label span{color:#333;}#mermaid-svg-yMK0xgZwBAdoyJzF .cluster-label span p{background-color:transparent;}#mermaid-svg-yMK0xgZwBAdoyJzF .label text,#mermaid-svg-yMK0xgZwBAdoyJzF span{fill:#333;color:#333;}#mermaid-svg-yMK0xgZwBAdoyJzF .node rect,#mermaid-svg-yMK0xgZwBAdoyJzF .node circle,#mermaid-svg-yMK0xgZwBAdoyJzF .node ellipse,#mermaid-svg-yMK0xgZwBAdoyJzF .node polygon,#mermaid-svg-yMK0xgZwBAdoyJzF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yMK0xgZwBAdoyJzF .rough-node .label text,#mermaid-svg-yMK0xgZwBAdoyJzF .node .label text,#mermaid-svg-yMK0xgZwBAdoyJzF .image-shape .label,#mermaid-svg-yMK0xgZwBAdoyJzF .icon-shape .label{text-anchor:middle;}#mermaid-svg-yMK0xgZwBAdoyJzF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yMK0xgZwBAdoyJzF .rough-node .label,#mermaid-svg-yMK0xgZwBAdoyJzF .node .label,#mermaid-svg-yMK0xgZwBAdoyJzF .image-shape .label,#mermaid-svg-yMK0xgZwBAdoyJzF .icon-shape .label{text-align:center;}#mermaid-svg-yMK0xgZwBAdoyJzF .node.clickable{cursor:pointer;}#mermaid-svg-yMK0xgZwBAdoyJzF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yMK0xgZwBAdoyJzF .arrowheadPath{fill:#333333;}#mermaid-svg-yMK0xgZwBAdoyJzF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yMK0xgZwBAdoyJzF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yMK0xgZwBAdoyJzF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yMK0xgZwBAdoyJzF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yMK0xgZwBAdoyJzF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yMK0xgZwBAdoyJzF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yMK0xgZwBAdoyJzF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yMK0xgZwBAdoyJzF .cluster text{fill:#333;}#mermaid-svg-yMK0xgZwBAdoyJzF .cluster span{color:#333;}#mermaid-svg-yMK0xgZwBAdoyJzF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yMK0xgZwBAdoyJzF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yMK0xgZwBAdoyJzF rect.text{fill:none;stroke-width:0;}#mermaid-svg-yMK0xgZwBAdoyJzF .icon-shape,#mermaid-svg-yMK0xgZwBAdoyJzF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yMK0xgZwBAdoyJzF .icon-shape p,#mermaid-svg-yMK0xgZwBAdoyJzF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yMK0xgZwBAdoyJzF .icon-shape .label rect,#mermaid-svg-yMK0xgZwBAdoyJzF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yMK0xgZwBAdoyJzF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yMK0xgZwBAdoyJzF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yMK0xgZwBAdoyJzF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 工控机 Node B - 192.160.6.6 (当前备节点)
工控机 Node A - 192.160.6.7 (当前主节点)
统一访问虚拟 IP: 192.160.6.9
反向代理 /crane-monitor
连接本机库 127.0.0.1
反向代理 /crane-monitor
连接本机库 127.0.0.1
达梦 Data Watch 实时双写同步
转发流量 (主路由)
故障时漂移绑定 (备路由)
客户端 / 用户浏览器 / PLC设备
Keepalived 虚拟 IP
Nginx 业务端口 8888
Spring Boot 端口 82
本地达梦数据库 5236 - 主库
Nginx 业务端口 8888
Spring Boot 端口 82
本地达梦数据库 5236 - 备库
3. 后端部署手册 (monitor-server)
3.1 部署环境要求
- 操作系统:银河麒麟操作系统 (Kylin OS)
- JDK 版本 :JDK 8 (OpenJDK 或 Oracle JDK,安装路径如:
/home/server/soft/java) - 数据库:达梦数据库 DM8(配置为本地高可用)
- 高可用 VIP :Keepalived 虚拟 IP (
192.160.6.9)
3.2 目录规划
在部署服务器上创建后端服务目录:
- 服务器路径 :
/home/server/soft/crane/backend
目录结构:
text
/home/server/soft/crane/backend/
├── monitor-server-1.0-SNAPSHOT.jar # 后端 jar 包
└── logs/ # 日志存放目录(需手动创建或由服务自动生成)
├── stdout.log # 系统运行日志 / 标准输出日志
├── gc.log # JVM 垃圾回收日志
└── heapdump.hprof # OOM 堆内存快照文件(仅在发生内存溢出时生成)
3.3 编译、打包与文件分发
-
本地编译打包:
在开发环境或集成构建环境的项目根目录下,执行 Maven 打包命令:
bashmvn clean package -Dmaven.test.skip=true打包完成后,将在项目子模块
monitor-server/target/目录下生成可运行的二进制 Jar 包:monitor-server-1.0-SNAPSHOT.jar。 -
创建服务器部署路径:
在服务器上,使用
mkdir命令创建后端项目目录和日志目录:bashmkdir -p /home/server/soft/crane/backend/logs -
分发并上传包文件:
通过 SFTP/SCP 等工具,将打包好的
monitor-server-1.0-SNAPSHOT.jar上传到服务器的部署路径/home/server/soft/crane/backend/下。
3.4 Systemd 守护进程配置
在包文件上传完成后,需要在服务器上配置 Systemd 守护进程服务,以确保程序在后台自动运行并具备异常自愈和开机自启的能力。
3.4.1 创建并配置服务文件
在服务器 /etc/systemd/system 目录下创建服务配置文件 monitor.service:
bash
sudo vi /etc/systemd/system/monitor.service
写入以下配置内容:
ini
[Unit]
Description=Crane Monitor Backend Service
After=syslog.target network.target
[Service]
Type=simple
User=root
WorkingDirectory=/home/server/soft/crane/backend
# 注意:请确认 /home/server/soft/java/bin/java 为您服务器上实际的 java 命令绝对路径
ExecStart=/home/server/soft/java/bin/java -server -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+ParallelRefProcEnabled -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/server/soft/crane/backend/logs/heapdump.hprof -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/server/soft/crane/backend/logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -Dfile.encoding=UTF-8 -Djava.awt.headless=true -jar monitor-server-1.0-SNAPSHOT.jar
SuccessExitStatus=143
Restart=always
RestartSec=5s
[Install]
WantedBy=multi-user.target
3.4.2 启动守护进程服务
配置完成后,依次执行以下命令加载、启动服务并设置开机自动启动:
bash
# 重新加载 Systemd 配置以识别新创建的 monitor.service
systemctl daemon-reload
# 启动后端服务
systemctl start monitor.service
# 设置服务为开机自启动
systemctl enable monitor.service
3.4.3 服务管理常用命令
在后续维护中,您可以通过以下命令来管理后端服务的运行状态:
-
停止服务:
bashsystemctl stop monitor.service -
重启服务:
bashsystemctl restart monitor.service -
查看服务运行状态:
bashsystemctl status monitor.service -
禁用开机自启:
bashsystemctl disable monitor.service -
查看实时应用日志 (journalctl):
bashjournalctl -u monitor.service -f
3.4.4 服务部署验证
服务启动后,进行以下步骤验证部署是否成功:
-
运行状态检查 :执行
systemctl status monitor.service观察输出中的Active: active (running)状态。 -
服务端口监听检查 :执行以下命令,确认后端服务的
82端口是否处于监听状态:bashnetstat -ntlp | grep 82 -
应用健康度联调检查:通过 HTTP 访问 Spring Boot 提供的 Actuator 端点:
bashcurl http://127.0.0.1:82/crane-monitor/actuator/health(如果返回
{"status":"UP",...},则表示后端应用已经成功运行,且本地达梦数据库(DM8)连接完全正常。)
4. 前端部署手册 (monitor-ui)
4.1 部署环境要求
- 构建环境:Node.js (推荐 v14.x 或 v16.x) + npm/yarn
- 运行环境:Nginx (建议 1.18.0+)
- 前端静态文件部署路径 :
/home/server/soft/crane/frontend/dist
4.2 前端打包
-
安装依赖:
在本地或构建机的
monitor-ui目录下执行依赖安装:bashnpm install # 或使用 yarn yarn install -
生产构建:
执行前端打包编译命令:
bashnpm run build # 或使用 yarn yarn build编译完成后会在
monitor-ui/下生成dist/目录。 -
上传至服务器:
将
dist/目录打包(如dist.tar或dist.zip)并上传至服务器,解压到/home/server/soft/crane/frontend/dist。确保在该目录下可以直接看到index.html和assets/文件夹。
4.3 Nginx 配置
4.3.1 Nginx 全局配置说明
如果服务器尚未配置 Nginx,可以使用以下配置作为 Nginx 主配置文件 nginx.conf 的标准配置。主配置文件的常见路径为:/home/server/soft/nginx/conf/nginx.conf 或 /etc/nginx/nginx.conf。
nginx
user server;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /home/server/soft/nginx/conf/conf.d/*.conf;
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
4.3.2 项目专用配置 (crane-monitor.conf)
在 /home/server/soft/nginx/conf/conf.d/ 目录下创建项目的 Nginx 配置文件 crane-monitor.conf。内容如下:
nginx
server {
# 监听起重机监控平台指定的业务端口
listen 8888;
server_name _;
# 1. 静态资源托管配置
location / {
root /home/server/soft/crane/frontend/dist;
try_files $uri $uri/ @router;
index index.html;
}
# 支持 Vue Router HTML5 History 模式的路由重定向
location @router {
rewrite ^.*$ /index.html last;
}
# 2. 后端接口反向代理配置
location /crane-monitor {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 代理到本地运行的 Spring Boot 后端服务端口 (82)
proxy_pass http://127.0.0.1:82/crane-monitor;
# 支持 WebSocket 连接(起重机实时数据推送)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Origin "";
}
}
4.3.3 Nginx Systemd 守护进程配置
为了将 Nginx 配置为系统守护进程并实现开机自启,请在 /etc/systemd/system/ 目录下创建 nginx.service 文件:
bash
sudo vi /etc/systemd/system/nginx.service
写入以下配置内容:
ini
[Unit]
Description=The NGINX HTTP and reverse proxy server (Custom)
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
# 对应您 nginx.conf 中配置的 pid 路径
PIDFile=/run/nginx.pid
# 启动前进行配置文件语法检查
ExecStartPre=/home/server/soft/nginx/sbin/nginx -t -c /home/server/soft/nginx/conf/nginx.conf
# 启动命令
ExecStart=/home/server/soft/nginx/sbin/nginx -c /home/server/soft/nginx/conf/nginx.conf
# 重载配置命令
ExecReload=/home/server/soft/nginx/sbin/nginx -s reload -c /home/server/soft/nginx/conf/nginx.conf
# 停止命令
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
4.3.4 Nginx 服务管理与重启生效
配置好 nginx.service 后,可以使用以下 Systemd 命令管理 Nginx 服务:
-
重新加载 Systemd 配置:
bashsystemctl daemon-reload -
启动 Nginx 服务:
bashsystemctl start nginx.service -
停止 Nginx 服务:
bashsystemctl stop nginx.service -
重启 Nginx 服务:
bashsystemctl restart nginx.service -
重新加载 Nginx 配置 (平滑重载,不中断连接):
bashsystemctl reload nginx.service -
设置 Nginx 开机自启:
bashsystemctl enable nginx.service -
查看 Nginx 服务状态:
bashsystemctl status nginx.service
(注:如果尚未配置 nginx.service 守护进程,也可以通过原生命令进行配置文件检查与平滑重启:)
bash
# 验证 nginx 配置文件语法是否正确
/home/server/soft/nginx/sbin/nginx -t -c /home/server/soft/nginx/conf/nginx.conf
# 重新加载 Nginx 配置
/home/server/soft/nginx/sbin/nginx -s reload -c /home/server/soft/nginx/conf/nginx.conf
5. 部署验证与联调测试
5.1 联调步骤
- 打开浏览器,输入访问地址(若 Keepalived 已配置,则访问虚拟 IP