Files
senmesh-zc/backend/docs/生产部署说明.md

8.5 KiB
Raw Blame History

s-file 生产部署 / 上线说明

适用版本:2026-09-14(含用户启停/注销、机构账号查询、手机号查记录、机构上传配置、禁用踢下线黑名单) 构建产物:target/s-file.jar(Spring Boot 可执行 fat jar,需 JDK 8)


0. 上线前必须处理(阻断项)

0.1 替换 spire.pdf 占位 jar ⚠️

本机构开发机的 ~/.m2/repository/e-iceblue/spire.pdf/3.7.4/ 中目前安装的是编译级 stub(空实现)jar——它能保证编译打包通过,但 PDF 盖章功能(PdfUtils.pdfStampPerPage)运行时必然失败。

上线前必须:

  1. 从公司私服获取真实的 spire.pdf-3.7.4.jar(阿里云与 e-iceblue 官方仓库均无此版本);
  2. 覆盖 ~/.m2/repository/e-iceblue/spire.pdf/3.7.4/spire.pdf-3.7.4.jar(pom 同步覆盖);
  3. 重新 mvn clean package -DskipTests;
  4. 验证:解包 jar 中 com/spire/pdf/PdfDocument.class 应为真实实现(stub 版仅 300~500 字节)。

若该业务暂时不用 PDF 盖章,可带 stub 上线,但需明确告知团队。

0.2 提供生产配置文件

仓库内不含任何运行配置(application.yml 是外置的)。启动时通过 spring.config.additional-location 挂载。生产模板如下(按实际环境修改):

server:
  port: 8080

spring:
  application:
    name: s-file
  datasource:
    # 生产为达梦 DM8;驱动 com.dameng.jdbc.driver(pom 已含依赖)
    url: jdbc:dm://<DB_HOST>:5236/S_FILE
    driver-class-name: com.dameng.jdbc.driver
    username: <DB_USER>
    password: <DB_PASSWORD>
    druid:
      initial-size: 5
      min-idle: 5
      max-active: 20
      validation-query: SELECT 1
  redis:                      # 必须可用:登录缓存 + 禁用/注销踢下线黑名单依赖 Redis
    host: <REDIS_HOST>
    port: 6379
    timeout: 5000
  rabbitmq:
    host: <MQ_HOST>
    port: 5672
    username: <MQ_USER>
    password: <MQ_PASSWORD>
  servlet:
    multipart:
      max-file-size: 500MB    # 按网盘需求调整
      max-request-size: 500MB
  main:
    allow-bean-definition-overriding: true

mybatis-plus:
  mapper-locations: classpath*:com/senmesh/**/mapper/*.xml   # 必须有,否则自定义 XML 的接口全部报 Invalid bound statement

system:
  code: 1

# 发号器雪花 workerId:键格式 code.snowflake.workid.<本机IP>
# 单机部署:直接写死本机 IP 的键;多机部署:每台机器一个键、值必须不同且 0~31
"[code.snowflake.workid.192.168.1.10]": 1

security:
  jwt:
    enable: true
    secret: <上线前必须换成 64 字节以上随机串,勿用文档示例>
    expiration: 86400        # token 有效期(秒)
    header: Authorization
  ignoring: /error,/favicon.ico,/v2/api-docs,/swagger-resources/**
  login-page: /login
  superior-only: false       # true=仅平台机构用户可登录系统;按部署侧实际选择
  use-local: true
  allow-if-all-abstain-decisions: true
  oauth2:
    enable: false
  anonymous: ""              # 匿名白名单按需追加(逗号分隔,如 /file/upload)

user:
  default:
    password: <新用户初始密码>

file:
  upload-dir: /data/upload          # 容器/主机上需存在且可写
  storage:
    type: local                     # 阿里云 OSS 则改 ali 并补齐 oss 配置
  transfer:
    location: "1"                   # 内网侧 "1",外网侧 "2" —— 两侧必须相反!
    send-dir: /data/transfer/send
    receive-dir: /data/transfer/receive
    unpack-risk-check: false

dify:
  risk:
    rule:
      api-key: <真实key或占位>
    scan:
      api-key: <真实key或占位>       # 必填(可为占位),否则启动失败

rabbitmq:
  custom:
    topic-exchange-name: s-file-topic
    delayed-exchange-name: s-file-delayed
    broadcast-id: s-file-broadcast

swagger:
  enable: false                      # 生产必须 false

0.3 数据库变更

  • 已有生产库:执行 db/upgrade-20260914-upload-config.sql(达梦执行「1. MySQL / 达梦 DM8」一节,建 x_upload_config 表)。其余本次功能无表结构变更。
  • 全新库:先执行 db/init-table.sql(达梦按 MySQL 兼容模式)+ db/init-data.sql(平台、平台机构、admin 账号、文件种类字典)。
  • 执行后验证:select count(*) from x_upload_config; 无报错即建表成功(0 行为正常,未配置的机构走默认策略)。

0.4 目录与权限

mkdir -p /data/upload /data/transfer/send /data/transfer/receive
chown -R <运行用户> /data

外网侧与内网侧通过 file.transfer.location 区分,send-dir/receive-dir 指向各自的摆渡目录(网闸/摆渡盘)。


1. 启动方式

1.1 裸机 / 虚拟机(JDK 8)

# 需 JDK 1.8(java -version 确认)
java -Xms1g -Xmx2g \
  -Dspring.config.additional-location=file:/opt/sfile/config/application.yml \
  -jar /opt/sfile/s-file.jar \
  > /opt/sfile/logs/stdout.log 2>&1 &

多节点时按节点 IP 配置不同的 code.snowflake.workid.<ip>(可用启动参数 -DCODE_SNOWFLAKE_WORKID_<IP大写>=<n> 环境变量方式,_ 映射 .)。

1.2 Docker

# 构建(context 内需 s-file.jar 与 Dockerfile,Dockerfile 在 src/main/resources/)
cp target/s-file.jar <build-context>/ && docker build -t s-file:<版本> <build-context>

docker run -d --name sfile-app --restart unless-stopped -p 8080:8080 \
  -v /opt/sfile/config/application.yml:/config/application.yml:ro \
  -v /data/upload:/data/upload \
  -v /data/transfer/send:/data/transfer/send \
  -v /data/transfer/receive:/data/transfer/receive \
  -e SPRING_CONFIG_ADDITIONAL_LOCATION=file:/config/application.yml \
  -e CODE_SNOWFLAKE_WORKID_<容器IP大写下划线>=1 \
  s-file:<版本>

注意:基础镜像 freshworks/oraclejdk8 为 amd64,arm64 主机需 --platform linux/amd64;workerId 键里的 IP 用容器固定 IP(自定义网络 --ip),容器重建 IP 不变。


2. 前端发布

cd senmesh-zc-legacy
bun install
bun run build          # 产出 dist/(.env.production 已带 VITE_APP_TITLE 引号修复,规避 Bun env 解析 bug)
  • dist/ 交由 nginx 托管;
  • nginx 需将 /api 反代到后端并去掉 /api 前缀(与 vite dev 代理行为一致):
location /api/ {
    proxy_pass http://<后端IP>:8080/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    client_max_body_size 500m;      # 与后端 multipart 上限匹配
}
  • .env.production 当前值:VITE_API_URL=(空,走同域 /api)、VITE_INIT_PASSWORD(前端判断初始密码强制改密用)——如有调整需重新 build。

3. 本次版本功能与数据依赖清单(验收用)

功能 依赖 验收方法
用户启用/禁用/注销(管理员) DB uc_user.enabled/status;Redis(禁用踢下线黑名单) 禁用后该用户已登录 token 立即失效(302/401),重新登录被拒
机构管理员启停本机构用户 无额外依赖 机构管理员可启停本机构用户;跨机构返回「只能操作本机构的用户」
机构账号查询(超管) 新增只读查询 管理后台-机构账号页正常出列表与筛选
按手机号查上传/发送/接收记录 无额外依赖 输入手机号出记录;发送/接收方向由部署侧 file.transfer.location 决定
机构上传配置 新表 x_upload_config 管理后台-上传配置保存后,该机构网盘上传立即按策略拦截
禁用踢下线 Redis key user:disabled:{userId} redis-cli keys 'user:disabled:*' 可见禁用标记

4. 上线步骤建议

  1. 生产库执行 0.3 升级 SQL(执行前备份);
  2. 替换真实 spire.pdf jar 并重新打包(0.1),核对 jar 时间戳;
  3. 准备 application.yml(0.2 模板),核对 JWT secret 已更换、dify api-key 已填、swagger.enable=false;
  4. 创建 /data 目录,确定内外网 location;
  5. 部署后端(1.1 或 1.2),观察启动日志出现 Started SFileApplication;
  6. 构建并发布前端(2),nginx reload;
  7. 验收第 3 节清单(至少:admin 登录、上传一个非白名单文件被拒、禁用一个测试用户并确认其会话失效、记录查询出数据);
  8. 观察日志无 ERROR,Redis 中 user:disabled:* 与登录缓存键正常。

5. 回滚

  • 后端:保留上一版 jar/镜像,停新启旧即可(本次无破坏性 DDL/DML,x_upload_config 留存不影响旧版本运行);
  • 前端:nginx 指回上一版 dist 目录;
  • 数据库:无需回滚(仅新增表)。