From 9be37fe7f81261f4409e0a400a8ada8a3b3c4097 Mon Sep 17 00:00:00 2001 From: KodouWZF <3092554823@qq.com> Date: Thu, 5 Nov 2026 01:07:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E9=83=A8=E7=BD=B2):=20=E4=BA=A4=E4=BB=98?= =?UTF-8?q?=E5=8C=85=E5=AE=B9=E5=99=A8=E5=86=85=E8=B7=AF=E5=BE=84=E4=B8=8E?= =?UTF-8?q?=E8=80=81=E7=B3=BB=E7=BB=9F=E5=AF=B9=E9=BD=90=EF=BC=8C=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E4=B8=8E=E4=B8=B4=E6=97=B6=E7=9B=AE=E5=BD=95=E8=90=BD?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=9B=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 库里 xs_file_record.file_path 存的是 file.upload-dir 拼出来的绝对路径,老系统是 /var/s-file/upload,新包之前写 /data/upload 会让接老库的历史文件全部读不到(只能迁库), 现在容器内逐字一致,宿主机侧仍由 .env 的 SFILE_DATA_ROOT 决定。 顺带把两处老配置没真正落地的补上: - logging.file.name 沿用 /usr/local/logs/s-file.log。之前 /app/logs 挂载是空的——yml 没设 文件日志,输出只进 docker 的 json-file 且不封顶;同时给 app 的 json 日志加 20m×5 上限 - java.io.tmpdir 用 -D 指到 upload 挂载内。老项目把这行写在 application.properties 里 并不会改 JVM 系统属性,等于没生效;现在 500MB 上传缓冲落在数据盘而不是容器 overlay 层 摆渡目录保持容器内 /data/transfer/*:光闸需要能单独挂它,嵌进 upload 树会把整个文件库 暴露给光闸,而传输包是过路文件、路径不入库。宿主机侧照旧可与老机器同路径(GATE_*)。 内外网两套 compose/config/install.sh 仍字节一致。 --- deployment/iw/README.md | 1 + deployment/iw/VERSION.txt | 1 + deployment/iw/config/application.yml | 15 ++++++++++++++- deployment/iw/docker-compose.yml | 20 +++++++++++++++++--- deployment/iw/scripts/install.sh | 3 ++- deployment/ow/README.md | 1 + deployment/ow/VERSION.txt | 1 + deployment/ow/config/application.yml | 15 ++++++++++++++- deployment/ow/docker-compose.yml | 20 +++++++++++++++++--- deployment/ow/scripts/install.sh | 3 ++- deployment/部署说明.md | 17 ++++++++++++++--- 11 files changed, 84 insertions(+), 13 deletions(-) diff --git a/deployment/iw/README.md b/deployment/iw/README.md index 1017b73..0bfd36e 100644 --- a/deployment/iw/README.md +++ b/deployment/iw/README.md @@ -33,6 +33,7 @@ vi .env ├── docker-compose.yml 5 个服务(web/app/pg/redis/mq),现场不改 ├── .env 本机全部可变项:角色/端口/口令/目录/MeshSafe ← 只改这个 ├── config/application.yml 后端静态默认配置,不放任何口令(口令走 .env 注入) +│ ⚠ 别改 file.upload-dir:库里存的是它拼出来的绝对路径前缀 ├── nginx/web.conf 前端站点 + /api 反代,改端口/上传上限时看这里 ├── web/ 前端静态包(内网包),挂进 nginx 当站点根 ├── sql/01-init-table.sql 全量建表 02-init-data.sql 初始数据(admin、机构、平台编码) diff --git a/deployment/iw/VERSION.txt b/deployment/iw/VERSION.txt index 9a732da..87f1052 100644 --- a/deployment/iw/VERSION.txt +++ b/deployment/iw/VERSION.txt @@ -1,4 +1,5 @@ s-file 部署包 1.0.1(内网机 iw) +包配置修订: git v1.0.2 —— 容器内路径/日志/tmpdir 与老系统对齐;镜像与 jar 未变,images/*.tar 不用重出 构建平台: linux/amd64 导出时间: 2026-11-04 21:45:19 后端 jar: d39b3b0(+ 未提交改动则与本仓库当前源码一致) diff --git a/deployment/iw/config/application.yml b/deployment/iw/config/application.yml index b40682b..f4d23b6 100644 --- a/deployment/iw/config/application.yml +++ b/deployment/iw/config/application.yml @@ -67,7 +67,9 @@ user: password: ${USER_DEFAULT_PASSWORD:} file: - upload-dir: /data/upload + # 这个前缀必须与老系统一致:库里 xs_file_record.file_path 存的是拼接好的绝对路径, + # 换前缀 = 历史文件全部读不到(要迁数据)。compose 里 app 的挂载点必须与这里逐字相同 + upload-dir: /var/s-file/upload storage: type: local transfer: @@ -105,6 +107,17 @@ meshsafe: swagger: enable: false +# 日志文件路径与格式沿用老系统(/usr/local/logs/s-file.log), +# compose 把宿主机 volumes/logs 挂到 /usr/local/logs,日志直接落数据盘、重装不丢 logging: + file: + name: /usr/local/logs/s-file.log + pattern: + console: "%d{yyyy/MM/dd-HH:mm:ss} %X{traceId:-} [%thread] %-5level %logger- %msg%n" + file: "%d{yyyy/MM/dd-HH:mm:ss} %X{traceId:-} [%thread] %-5level %logger- %msg%n" + logback: + rollingpolicy: + # 老系统没配轮转,日志单文件会一直长;这里按天切、最多留 30 天 + max-history: 30 level: com.senmesh: info diff --git a/deployment/iw/docker-compose.yml b/deployment/iw/docker-compose.yml index 8d9e9fb..43b24c8 100644 --- a/deployment/iw/docker-compose.yml +++ b/deployment/iw/docker-compose.yml @@ -53,7 +53,10 @@ services: TZ: ${TZ:-Asia/Shanghai} # 发号器 workerId 按「容器 IP」取键,取不到会回退 99 而 99 > 31 直接启动失败, # 因此这里锁死 app 的容器 IP,并把同一个键写进 JVM 参数,两处永远一致 - JAVA_OPTS: "${APP_JAVA_OPTS:--Xms1g -Xmx3g -Dfile.encoding=UTF-8} -Dcode.snowflake.workid.${APP_NODE_IP:?缺少 APP_NODE_IP}=${APP_WORK_ID:?缺少 APP_WORK_ID}" + # java.io.tmpdir 指到数据盘挂载内:Tomcat 接收大文件时先在这里落盘(multipart 上限 500MB), + # 不指就写进容器 overlay 层,把系统盘吃掉几个 G。老系统那行 java.io.tmpdir 写在 + # application.properties 里其实没生效,这里用 -D 才真正生效 + JAVA_OPTS: "${APP_JAVA_OPTS:--Xms1g -Xmx3g -Dfile.encoding=UTF-8} -Djava.io.tmpdir=/var/s-file/upload/tmpdir -Dcode.snowflake.workid.${APP_NODE_IP:?缺少 APP_NODE_IP}=${APP_WORK_ID:?缺少 APP_WORK_ID}" SPRING_CONFIG_ADDITIONAL_LOCATION: file:/config/application.yml SPRING_DATASOURCE_URL: jdbc:postgresql://pg:5432/${POSTGRES_DB:?缺少 POSTGRES_DB} @@ -77,6 +80,9 @@ services: # 内网机 1 / 外网机 2,写反了摆渡方向就反了 FILE_TRANSFER_LOCATION: "${SFILE_TRANSFER_LOCATION:?缺少 SFILE_TRANSFER_LOCATION}" + # 摆渡目录不进 upload 树(老系统是 ${file.upload-dir}/transfer/send):光闸要单独挂这两个目录, + # 嵌在 upload 里就得把整个文件库暴露给光闸。这里只是容器内路径,宿主机侧看 .env 的 GATE_*; + # 传输包是过路文件、路径不入库,所以改它不影响历史数据 FILE_TRANSFER_SEND_DIR: /data/transfer/send FILE_TRANSFER_RECEIVE_DIR: /data/transfer/receive FILE_TRANSFER_MONITOR_CRON: "${FILE_TRANSFER_MONITOR_CRON:-0/5 * * * * ?}" @@ -90,10 +96,18 @@ services: MESHSAFE_TIMEOUT_SECONDS: ${MESHSAFE_TIMEOUT_SECONDS:-120} MESHSAFE_POLL_TIMEOUT_MINUTES: ${MESHSAFE_POLL_TIMEOUT_MINUTES:-60} MESHSAFE_POLL_CRON: ${MESHSAFE_POLL_CRON:-0/10 * * * * ?} + # 容器标准输出留一份即可(应用日志已写 /usr/local/logs/s-file.log 并按天轮转), + # 不限速的话 docker 的 json-file 默认不封顶,跑半年能把系统盘吃满 + logging: + driver: json-file + options: + max-size: "20m" + max-file: "5" volumes: - ./config/application.yml:/config/application.yml:ro - - ${SFILE_DATA_ROOT}/upload:/data/upload - - ${SFILE_DATA_ROOT}/logs:/app/logs + # 容器内路径与老系统逐字一致(库里存的是绝对路径前缀,不能改),宿主机侧由 .env 决定 + - ${SFILE_DATA_ROOT}/upload:/var/s-file/upload + - ${SFILE_DATA_ROOT}/logs:/usr/local/logs # 摆渡目录:容器内固定路径,宿主机侧由光闸设备负责单向搬运 - ${GATE_SEND_DIR:?缺少 GATE_SEND_DIR}:/data/transfer/send - ${GATE_RECV_DIR:?缺少 GATE_RECV_DIR}:/data/transfer/receive diff --git a/deployment/iw/scripts/install.sh b/deployment/iw/scripts/install.sh index 54211eb..3c89467 100755 --- a/deployment/iw/scripts/install.sh +++ b/deployment/iw/scripts/install.sh @@ -129,7 +129,8 @@ GATE_SEND="$(envget GATE_SEND_DIR)" GATE_RECV="$(envget GATE_RECV_DIR)" [ -n "$DATA_ROOT" ] || die ".env 里 SFILE_DATA_ROOT 为空" -mkdir -p "$DATA_ROOT"/{upload,logs/nginx,pgdata,redis,mq} +# upload/tmpdir:JVM 的 java.io.tmpdir 指到这里(大文件上传先在此落盘),Tomcat 会在下面建 work 目录 +mkdir -p "$DATA_ROOT"/{upload,upload/tmpdir,logs/nginx,pgdata,redis,mq} mkdir -p "$GATE_SEND" "$GATE_RECV" # 数据盘挂载点没起来时直接建目录会落到根分区,先确认一下 diff --git a/deployment/ow/README.md b/deployment/ow/README.md index 19007e9..96bdc4d 100644 --- a/deployment/ow/README.md +++ b/deployment/ow/README.md @@ -33,6 +33,7 @@ vi .env ├── docker-compose.yml 5 个服务(web/app/pg/redis/mq),现场不改 ├── .env 本机全部可变项:角色/端口/口令/目录/MeshSafe ← 只改这个 ├── config/application.yml 后端静态默认配置,不放任何口令(口令走 .env 注入) +│ ⚠ 别改 file.upload-dir:库里存的是它拼出来的绝对路径前缀 ├── nginx/web.conf 前端站点 + /api 反代,改端口/上传上限时看这里 ├── web/ 前端静态包(外网包),挂进 nginx 当站点根 ├── sql/01-init-table.sql 全量建表 02-init-data.sql 初始数据(admin、机构、平台编码) diff --git a/deployment/ow/VERSION.txt b/deployment/ow/VERSION.txt index cd9338c..a9d9723 100644 --- a/deployment/ow/VERSION.txt +++ b/deployment/ow/VERSION.txt @@ -1,4 +1,5 @@ s-file 部署包 1.0.1(外网机 ow) +包配置修订: git v1.0.2 —— 容器内路径/日志/tmpdir 与老系统对齐;镜像与 jar 未变,images/*.tar 不用重出 构建平台: linux/amd64 导出时间: 2026-11-04 21:45:21 后端 jar: d39b3b0(+ 未提交改动则与本仓库当前源码一致) diff --git a/deployment/ow/config/application.yml b/deployment/ow/config/application.yml index b40682b..f4d23b6 100644 --- a/deployment/ow/config/application.yml +++ b/deployment/ow/config/application.yml @@ -67,7 +67,9 @@ user: password: ${USER_DEFAULT_PASSWORD:} file: - upload-dir: /data/upload + # 这个前缀必须与老系统一致:库里 xs_file_record.file_path 存的是拼接好的绝对路径, + # 换前缀 = 历史文件全部读不到(要迁数据)。compose 里 app 的挂载点必须与这里逐字相同 + upload-dir: /var/s-file/upload storage: type: local transfer: @@ -105,6 +107,17 @@ meshsafe: swagger: enable: false +# 日志文件路径与格式沿用老系统(/usr/local/logs/s-file.log), +# compose 把宿主机 volumes/logs 挂到 /usr/local/logs,日志直接落数据盘、重装不丢 logging: + file: + name: /usr/local/logs/s-file.log + pattern: + console: "%d{yyyy/MM/dd-HH:mm:ss} %X{traceId:-} [%thread] %-5level %logger- %msg%n" + file: "%d{yyyy/MM/dd-HH:mm:ss} %X{traceId:-} [%thread] %-5level %logger- %msg%n" + logback: + rollingpolicy: + # 老系统没配轮转,日志单文件会一直长;这里按天切、最多留 30 天 + max-history: 30 level: com.senmesh: info diff --git a/deployment/ow/docker-compose.yml b/deployment/ow/docker-compose.yml index 8d9e9fb..43b24c8 100644 --- a/deployment/ow/docker-compose.yml +++ b/deployment/ow/docker-compose.yml @@ -53,7 +53,10 @@ services: TZ: ${TZ:-Asia/Shanghai} # 发号器 workerId 按「容器 IP」取键,取不到会回退 99 而 99 > 31 直接启动失败, # 因此这里锁死 app 的容器 IP,并把同一个键写进 JVM 参数,两处永远一致 - JAVA_OPTS: "${APP_JAVA_OPTS:--Xms1g -Xmx3g -Dfile.encoding=UTF-8} -Dcode.snowflake.workid.${APP_NODE_IP:?缺少 APP_NODE_IP}=${APP_WORK_ID:?缺少 APP_WORK_ID}" + # java.io.tmpdir 指到数据盘挂载内:Tomcat 接收大文件时先在这里落盘(multipart 上限 500MB), + # 不指就写进容器 overlay 层,把系统盘吃掉几个 G。老系统那行 java.io.tmpdir 写在 + # application.properties 里其实没生效,这里用 -D 才真正生效 + JAVA_OPTS: "${APP_JAVA_OPTS:--Xms1g -Xmx3g -Dfile.encoding=UTF-8} -Djava.io.tmpdir=/var/s-file/upload/tmpdir -Dcode.snowflake.workid.${APP_NODE_IP:?缺少 APP_NODE_IP}=${APP_WORK_ID:?缺少 APP_WORK_ID}" SPRING_CONFIG_ADDITIONAL_LOCATION: file:/config/application.yml SPRING_DATASOURCE_URL: jdbc:postgresql://pg:5432/${POSTGRES_DB:?缺少 POSTGRES_DB} @@ -77,6 +80,9 @@ services: # 内网机 1 / 外网机 2,写反了摆渡方向就反了 FILE_TRANSFER_LOCATION: "${SFILE_TRANSFER_LOCATION:?缺少 SFILE_TRANSFER_LOCATION}" + # 摆渡目录不进 upload 树(老系统是 ${file.upload-dir}/transfer/send):光闸要单独挂这两个目录, + # 嵌在 upload 里就得把整个文件库暴露给光闸。这里只是容器内路径,宿主机侧看 .env 的 GATE_*; + # 传输包是过路文件、路径不入库,所以改它不影响历史数据 FILE_TRANSFER_SEND_DIR: /data/transfer/send FILE_TRANSFER_RECEIVE_DIR: /data/transfer/receive FILE_TRANSFER_MONITOR_CRON: "${FILE_TRANSFER_MONITOR_CRON:-0/5 * * * * ?}" @@ -90,10 +96,18 @@ services: MESHSAFE_TIMEOUT_SECONDS: ${MESHSAFE_TIMEOUT_SECONDS:-120} MESHSAFE_POLL_TIMEOUT_MINUTES: ${MESHSAFE_POLL_TIMEOUT_MINUTES:-60} MESHSAFE_POLL_CRON: ${MESHSAFE_POLL_CRON:-0/10 * * * * ?} + # 容器标准输出留一份即可(应用日志已写 /usr/local/logs/s-file.log 并按天轮转), + # 不限速的话 docker 的 json-file 默认不封顶,跑半年能把系统盘吃满 + logging: + driver: json-file + options: + max-size: "20m" + max-file: "5" volumes: - ./config/application.yml:/config/application.yml:ro - - ${SFILE_DATA_ROOT}/upload:/data/upload - - ${SFILE_DATA_ROOT}/logs:/app/logs + # 容器内路径与老系统逐字一致(库里存的是绝对路径前缀,不能改),宿主机侧由 .env 决定 + - ${SFILE_DATA_ROOT}/upload:/var/s-file/upload + - ${SFILE_DATA_ROOT}/logs:/usr/local/logs # 摆渡目录:容器内固定路径,宿主机侧由光闸设备负责单向搬运 - ${GATE_SEND_DIR:?缺少 GATE_SEND_DIR}:/data/transfer/send - ${GATE_RECV_DIR:?缺少 GATE_RECV_DIR}:/data/transfer/receive diff --git a/deployment/ow/scripts/install.sh b/deployment/ow/scripts/install.sh index 54211eb..3c89467 100755 --- a/deployment/ow/scripts/install.sh +++ b/deployment/ow/scripts/install.sh @@ -129,7 +129,8 @@ GATE_SEND="$(envget GATE_SEND_DIR)" GATE_RECV="$(envget GATE_RECV_DIR)" [ -n "$DATA_ROOT" ] || die ".env 里 SFILE_DATA_ROOT 为空" -mkdir -p "$DATA_ROOT"/{upload,logs/nginx,pgdata,redis,mq} +# upload/tmpdir:JVM 的 java.io.tmpdir 指到这里(大文件上传先在此落盘),Tomcat 会在下面建 work 目录 +mkdir -p "$DATA_ROOT"/{upload,upload/tmpdir,logs/nginx,pgdata,redis,mq} mkdir -p "$GATE_SEND" "$GATE_RECV" # 数据盘挂载点没起来时直接建目录会落到根分区,先确认一下 diff --git a/deployment/部署说明.md b/deployment/部署说明.md index 74d75a8..612fa0f 100644 --- a/deployment/部署说明.md +++ b/deployment/部署说明.md @@ -79,7 +79,10 @@ deployment/ | `rabbitmq` | `3.13-management-alpine` | 84M | 验证过 3.13.7 | > `sfile-app:1.0.1`(对应 git tag `v1.0.1`)相比 `1.0.0` 是传输链路性能优化那一批(监听周期 60s→5s、读写缓冲 64KB、已压缩格式不再二次压缩、`md5_code` 加索引、单轮时间预算)。对照实测:端到端 123.1s → 9.9s,组包 11.4×、解包 9.9×,包体 +3.63%;详见 `backend/docs/传输链路性能优化方案.md` §10。 -> 版本对应关系:git tag `v1.0.1` = 镜像 `sfile-app:1.0.1` = `.env` 的 `APP_IMAGE`,出包脚本按版本号一次对齐。 +> 版本对应关系:git tag 是**包版本**,镜像 tag 是 **jar 版本**,两者可以不同。 +> 当前 git tag `v1.0.2` 只是包配置修订(容器内路径与老系统对齐、日志落盘、`java.io.tmpdir` 落数据盘), +> 镜像与 jar 未变,仍是 `sfile-app:1.0.1` = `.env` 的 `APP_IMAGE`,`images/*.tar` 不用重出; +> 下次 jar 有改动时再用 `build-package.sh <新版本>` 把包版本与镜像版本一起对齐。 ### 2.2 数据挂载对照(命名/位置与之前一致) @@ -88,12 +91,20 @@ deployment/ | PostgreSQL | `/var/lib/postgresql` | `volumes/pgdata` | `/data/sfile/pgdata` | | Redis | `/data` | `volumes/redis` | `/data/sfile/redis` | | RabbitMQ | `/var/lib/rabbitmq` | `volumes/mq` | `/data/sfile/mq` | -| 上传文件本体 | `/data/upload` | `volumes/upload` | `/data/sfile/upload` | -| 后端日志 | `/app/logs` | `volumes/logs` | `/data/sfile/logs` | +| 上传文件本体 | `/var/s-file/upload`(**与老系统逐字一致**) | `volumes/upload` | `/data/sfile/upload` | +| 后端日志 | `/usr/local/logs/s-file.log`(**与老系统一致**) | `volumes/logs` | `/data/sfile/logs` | | 摆渡发出/收到 | `/data/transfer/send`、`/receive` | `volumes/gate/out`、`in` | `/data/sfile/gate/out`、`in` | 子目录名与 compose 里的写法完全沿用,只是根目录默认从 `/data/sfile` 改成包内 `./volumes`(整目录自包含、拷走就能跑)。放独立数据盘就把 `.env` 的 `SFILE_DATA_ROOT`、`GATE_SEND_DIR`、`GATE_RECV_DIR` 改成绝对路径,重跑 `install.sh` 即可,compose 不用动。 +> **容器内的这两个路径不是随便写的,别改回去。** 上传文件在库里存的是拼接好的绝对路径 +> (`FileServiceImpl` 取 `file.upload-dir` 拼 `orgId/fileCode` 写进 `xs_file_record.file_path`,下载时直接 +> `new FileInputStream` 读它),老库里的前缀是 `/var/s-file/upload`,所以容器内必须也叫这个名, +> 否则历史文件全部读不到、只能迁库。日志同理,沿用老系统的 `/usr/local/logs`,运维脚本不用改。 +> 只有摆渡目录例外:传输包是过路文件、路径不入库,且光闸要单独挂它,所以留在 `/data/transfer/*`。 +> 改 `file.upload-dir` 必须同时改 compose 里 app 的挂载点,两处逐字相同(`deploy/offline/` 那套仍是旧的 +> `/data/upload`,不要与本包混用)。 + --- ## 3. 现场要先定的 6 件事(都在 `.env`)