个数不代表工作量:几十 KB 与几百 MB 的包差三个数量级,10 个小包 1 秒就跑完 (限制毫无必要),10 个大包能跑十几分钟(还会把下一轮挤掉)。改为时间预算后 单轮能处理多少就处理多少,超预算结束本轮、剩余留给下一轮,个数上限 500 兜底。 按 5.3 改造后的单包耗时估算,4 秒预算约可处理数十个小包,吞吐提升一个数量级。 同时解决三个会让预算被白耗的问题: - 校验不通过原来只有一种处理(静默跳过、永不改名),但它有两重含义:光闸还在搬 (下一轮就好)与包本身坏了(永远不会好)。用 mtime 是否静止超过 stale-after-seconds 区分,坏包改名 .error 停止重试,否则 5 秒轮询会为它无限白跑 - 解包异常同样按静止阈值判定,短暂基础设施抖动仍保留重试 - .finish 文件名不合规原来只 log.warn 后保留文件,每轮重复解析并刷日志,改为标 .error .finish 只做一次状态更新,改为优先处理且不受个数限制,让发送端尽早看到「已完成」。 每轮结束输出结构化日志(完成标记/成功/坏包/未就绪/耗时/预算/剩余/已搁置), 剩余超过 50 告警,作为容量规划依据。 按方案 5.3 注意事项补 max-unpack-size-mb(默认 512):解包把整个 entry 读进堆, upload 再拷一份、MD5 再一份,峰值约 2-3 倍文件大小,-Xmx3g 下单文件过大会 OOM, 超限直接标 .error 而不是尝试解包。 verifyFileMD5 打不开 zip 时原来记 ERROR 带堆栈,但「光闸还在搬」本来就是这个状态, 5 秒轮询下会为每个在途文件刷 60 条 ERROR,降为 debug;真正的坏包由改名 .error 时记 ERROR。 未实施方案里的认领改名与并发解包:两侧都是单实例部署,Spring 的 cron 任务要等上一轮 跑完才排下一轮(已实测触发间隔精确 5.00 秒),不存在同实例重叠;认领机制只会引入 kill -9 后遗留 .processing 这类新故障模式,换不到吞吐。若将来改多实例共享同一摆渡目录, 再补认领与 Redisson 互斥。
111 lines
3.6 KiB
YAML
111 lines
3.6 KiB
YAML
# =============================================================================
|
||
# s-file 客户侧静态默认配置(两台机器共用同一份,现场一般不用改)
|
||
#
|
||
# 随角色/环境变化的取值一律由 docker-compose 的环境变量注入,本文件不放:
|
||
# 数据库/Redis/MQ 地址与口令、JWT 密钥、用户初始密码、传输方向与摆渡目录、
|
||
# MeshSafe 开关与凭证、MQ 交换机命名 —— 全部在 .env 里填
|
||
# 这样交付物里不存在任何写死的口令或密钥
|
||
# =============================================================================
|
||
|
||
server:
|
||
port: 8080
|
||
|
||
spring:
|
||
application:
|
||
name: s-file
|
||
datasource:
|
||
driver-class-name: org.postgresql.Driver
|
||
type: com.alibaba.druid.pool.DruidDataSource
|
||
druid:
|
||
initial-size: 5
|
||
min-idle: 5
|
||
max-active: 50
|
||
validation-query: SELECT 1
|
||
test-while-idle: true
|
||
# 摆渡解包/送检会在多任务里并发取连接,压太低会出现等待
|
||
max-wait: 10000
|
||
redis:
|
||
timeout: 5000
|
||
lettuce:
|
||
pool:
|
||
max-active: 16
|
||
max-idle: 8
|
||
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
|
||
|
||
# 平台编码,需与 sql/02-init-data.sql 里 uc_platform.platform_code 一致
|
||
system:
|
||
code: 1
|
||
|
||
security:
|
||
jwt:
|
||
enable: true
|
||
# secret 由环境变量 SECURITY_JWT_SECRET 注入,勿在此填写
|
||
expiration: 86400000
|
||
header: Authorization
|
||
ignoring: /error,/favicon.ico
|
||
login-page: /login
|
||
superior-only: false
|
||
# 单机自闭环部署:权限走本地库,不接外部用户中心
|
||
use-local: true
|
||
allow-if-all-abstain-decisions: true
|
||
oauth2:
|
||
enable: false
|
||
not-logs: ""
|
||
anonymous: ""
|
||
|
||
# 新用户初始密码由环境变量 USER_DEFAULT_PASSWORD 注入
|
||
user:
|
||
default:
|
||
password: ${USER_DEFAULT_PASSWORD:}
|
||
|
||
file:
|
||
upload-dir: /data/upload
|
||
storage:
|
||
type: local
|
||
transfer:
|
||
# location / send-dir / receive-dir / monitor.cron 均由环境变量注入
|
||
# 解包时是否再做一次内容风险识别(依赖下面的 dify,未部署 dify 时保持 false)
|
||
unpack-risk-check: false
|
||
monitor:
|
||
# 单轮处理时间预算(秒)。超预算即结束本轮,剩余留给下一轮。
|
||
# 与监听周期配套:周期 5 秒则预算留 4 秒,保证两轮不互相挤压。
|
||
# 目录持续积压(日志「目录剩余待处理」超过 50)时调大此值
|
||
round-budget-seconds: 4
|
||
# 单轮兜底个数上限,防止极端场景单轮过长
|
||
round-max-files: 500
|
||
# 包内单个文件大小上限(MB)。解包时整个文件读进堆,峰值约 2-3 倍文件大小,
|
||
# 超限直接标 .error 而不是解包到 OOM。按 APP_JAVA_OPTS 的 -Xmx 调整:-Xmx3g 对应 512
|
||
max-unpack-size-mb: 512
|
||
# 校验不通过或解包异常,且文件静止超过该秒数即判定为坏包,标 .error 停止重试。
|
||
# 用于区分「光闸还在搬」与「搬完了但是坏包」,必须大于光闸搬运单个包的最长时间
|
||
stale-after-seconds: 300
|
||
|
||
# 内容风险识别(Dify)。未部署 Dify 时留空并保持 file.transfer.unpack-risk-check=false
|
||
dify:
|
||
risk:
|
||
rule:
|
||
api-key: ""
|
||
scan:
|
||
api-key: ""
|
||
|
||
# MeshSafe 全段由环境变量注入(MESHSAFE_*),未部署时 MESHSAFE_ENABLED=false 即可,
|
||
# 前端会自动隐藏「安全检测」列,跨网摆渡不受影响
|
||
meshsafe:
|
||
review-sync-to-meshsafe: true
|
||
|
||
# 接口文档在生产关闭
|
||
swagger:
|
||
enable: false
|
||
|
||
logging:
|
||
level:
|
||
com.senmesh: info
|