分布式部署
分布式部署用于提升应用层的容量和可用性。所有应用节点必须使用同一套数据库、Redis、文件存储和版本配置;仅增加 Java 节点而继续使用各节点本地附件目录,会导致文件随机丢失或无法访问。
推荐架构
用户
│
▼
负载均衡 / WAF / Nginx
├── 静态前端 dist/public、dist/admin
└── /admin-api、/captcha
├── App 1:48080
├── App 2:48080
└── App N:48080
│
├── 共享 MySQL
├── 共享 Redis
└── 对象存储或共享文件系统
数据库、Redis 和对象存储本身的高可用由对应产品或云服务负责。部署前先确认故障切换方式、连接地址和备份恢复流程。
部署前检查
- 所有应用节点运行相同版本的 JAR、配置和 License。
- 数据库结构已完成当前版本升级,且所有节点连接同一个写入端点。
- Redis 地址在所有节点可达,不使用节点本机
127.0.0.1。 - 文件存储对所有节点可见,域名可被最终用户访问。
- 应用节点的
48080只允许负载均衡器和运维网络访问。 - 节点时间同步,时区和 JVM 参数保持一致。
1. 部署应用节点
每个节点都可以参考RHEL 8 系部署创建 systemd 服务,但连接配置需要改为共享服务地址:
server:
port: 48080
spring:
datasource:
dynamic:
datasource:
master:
name: survey
url: jdbc:mysql://mysql.internal:3306/survey?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
username: surveyking
password: 请替换为数据库密码
redis:
host: redis.internal
port: 6379
database: 0
password: 请替换为 Redis 密码
敏感配置应通过受控配置文件、环境变量或密钥管理系统分发,不要写入镜像和代码仓库。
逐个节点验证:
systemctl status surveyking --no-pager
ss -lntp | grep 48080
journalctl -u surveyking -n 100 --no-pager
2. 配置 Nginx 负载均衡
在标准 Nginx 配置的基础上增加 upstream,并将两个后端代理地址替换为 surveyking_backend。静态前端仍由 Nginx 直接提供。
upstream surveyking_backend {
least_conn;
server 192.168.10.11:48080 max_fails=3 fail_timeout=30s;
server 192.168.10.12:48080 max_fails=3 fail_timeout=30s;
keepalive 32;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
/admin-api 和 /captcha 的代理配置:
location ^~ /admin-api {
proxy_pass http://surveyking_backend;
proxy_buffering off;
proxy_cache off;
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_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 10s;
proxy_read_timeout 1800s;
proxy_send_timeout 1800s;
proxy_next_upstream error timeout http_502 http_503 http_504;
}
location ^~ /captcha {
proxy_pass http://surveyking_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_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 10s;
proxy_read_timeout 1800s;
}
开源 Nginx 的 max_fails 和 fail_timeout 是被动故障判断,不是主动健康检查。需要主动探测时,应由上游负载均衡器、服务发现平台或监控系统完成。
不要使用 set_real_ip_from 0.0.0.0/0。只有存在受控的上游代理时,才把该代理的固定网段加入 set_real_ip_from。
检查配置:
sudo nginx -t
sudo systemctl reload nginx
3. 配置共享文件存储
进入 基础设置 → 文件管理 → 文件配置,选择所有节点都能访问的存储。

推荐顺序:
- S3、OSS、COS 等兼容的对象存储。
- 企业内部 MinIO 或其他 S3 兼容服务。
- 已有的共享文件系统,例如经过高可用设计的 NFS。
不建议使用 FTP 或定时 rsync 在多个写入节点之间同步附件。它们无法保证并发写入一致性,故障切换时容易产生缺失或覆盖。
使用 NFS 时,每个节点必须挂载到同一绝对路径,并在启动 SurveyKing 前确认挂载成功。不要使用 no_root_squash 扩大权限;应用以专用用户读写共享目录即可。
4. 数据库与 Redis
MySQL
- 应用只连接数据库服务提供的写入端点。
- 不在应用配置中列出多个数据库节点自行轮询。
- 切换主库后,连接地址和账号权限应保持稳定。
- 数据库备份必须在独立环境完成恢复演练。
Redis
- 所有应用节点连接同一个 Redis 服务或统一高可用端点。
- 不将 Redis 暴露到公网。
- 使用 Sentinel、Cluster 或云 Redis 时,先确认当前交付版本支持对应连接方式。
- 不同生产环境使用独立 Redis 数据库或实例,避免键冲突。
5. 验证集群
- 逐个启动应用节点,确认每个节点都能登录、查询数据库和读写 Redis。
- 通过负载均衡地址创建项目并提交答卷。
- 连续请求接口,确认请求可以到达不同节点。
- 上传文件后逐个停止应用节点,确认文件仍可预览和下载。
- 停止一个应用节点,确认新请求能够转移到其他节点。
- 检查定时任务、消息通知和统计任务没有重复异常。
滚动升级
- 先备份数据库、附件、配置和当前安装包。
- 确认数据库变更是否向前兼容;不兼容时安排维护窗口。
- 从负载均衡中摘除一个节点。
- 替换 JAR、重启并完成健康验证。
- 将节点重新加入负载均衡,再处理下一个节点。
- 最后替换前端文件,并确认
index.html未被缓存。
常见问题
登录状态随机失效
检查所有节点是否连接同一个 Redis、系统时间是否同步,以及代理是否完整转发 Cookie 和协议头。共享 Redis 正常时通常不需要 ip_hash。
文件有时能打开、有时 404
应用节点仍在使用各自本地目录。迁移到对象存储或所有节点共同挂载的共享文件系统。
停止一个节点后请求仍长时间失败
检查负载均衡器的故障判断、连接超时和节点摘除流程。Nginx 被动检查只会在实际请求失败后暂时跳过故障节点。