跳到主要内容

分布式部署

分布式部署用于提升应用层的容量和可用性。所有应用节点必须使用同一套数据库、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_failsfail_timeout 是被动故障判断,不是主动健康检查。需要主动探测时,应由上游负载均衡器、服务发现平台或监控系统完成。

不要信任任意客户端的转发 IP

不要使用 set_real_ip_from 0.0.0.0/0。只有存在受控的上游代理时,才把该代理的固定网段加入 set_real_ip_from

检查配置:

sudo nginx -t
sudo systemctl reload nginx

3. 配置共享文件存储

进入 基础设置 → 文件管理 → 文件配置,选择所有节点都能访问的存储。

在 SurveyKing 管理后台配置共享文件存储

推荐顺序:

  1. S3、OSS、COS 等兼容的对象存储。
  2. 企业内部 MinIO 或其他 S3 兼容服务。
  3. 已有的共享文件系统,例如经过高可用设计的 NFS。

不建议使用 FTP 或定时 rsync 在多个写入节点之间同步附件。它们无法保证并发写入一致性,故障切换时容易产生缺失或覆盖。

使用 NFS 时,每个节点必须挂载到同一绝对路径,并在启动 SurveyKing 前确认挂载成功。不要使用 no_root_squash 扩大权限;应用以专用用户读写共享目录即可。

4. 数据库与 Redis

MySQL

  • 应用只连接数据库服务提供的写入端点。
  • 不在应用配置中列出多个数据库节点自行轮询。
  • 切换主库后,连接地址和账号权限应保持稳定。
  • 数据库备份必须在独立环境完成恢复演练。

Redis

  • 所有应用节点连接同一个 Redis 服务或统一高可用端点。
  • 不将 Redis 暴露到公网。
  • 使用 Sentinel、Cluster 或云 Redis 时,先确认当前交付版本支持对应连接方式。
  • 不同生产环境使用独立 Redis 数据库或实例,避免键冲突。

5. 验证集群

  1. 逐个启动应用节点,确认每个节点都能登录、查询数据库和读写 Redis。
  2. 通过负载均衡地址创建项目并提交答卷。
  3. 连续请求接口,确认请求可以到达不同节点。
  4. 上传文件后逐个停止应用节点,确认文件仍可预览和下载。
  5. 停止一个应用节点,确认新请求能够转移到其他节点。
  6. 检查定时任务、消息通知和统计任务没有重复异常。

滚动升级

  1. 先备份数据库、附件、配置和当前安装包。
  2. 确认数据库变更是否向前兼容;不兼容时安排维护窗口。
  3. 从负载均衡中摘除一个节点。
  4. 替换 JAR、重启并完成健康验证。
  5. 将节点重新加入负载均衡,再处理下一个节点。
  6. 最后替换前端文件,并确认 index.html 未被缓存。

常见问题

登录状态随机失效

检查所有节点是否连接同一个 Redis、系统时间是否同步,以及代理是否完整转发 Cookie 和协议头。共享 Redis 正常时通常不需要 ip_hash

文件有时能打开、有时 404

应用节点仍在使用各自本地目录。迁移到对象存储或所有节点共同挂载的共享文件系统。

停止一个节点后请求仍长时间失败

检查负载均衡器的故障判断、连接超时和节点摘除流程。Nginx 被动检查只会在实际请求失败后暂时跳过故障节点。