06852c5d90ce435502d9f73b1fbaf5759524d7cf
个数不代表工作量:几十 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 互斥。
senmesh-zc(信创文件安全传输系统 · 合并仓库)
光闸内外网文件摆渡系统,前后端合并仓库:
| 目录 | 项目 | 说明 | 技术栈 |
|---|---|---|---|
backend/ |
s-file(原 alita-bjy-uygur) | 服务端:文件传输/网盘/机构用户管理/MeshSafe 安全检测对接 | Java 8 + Spring Boot 2.4.2 + MyBatis-Plus + PG/DM8 |
frontend/ |
senmesh-zc-legacy | Web 前端:我的文件/分享/内外网传输/管理端 | React 19 + Vite + TanStack Router/Query + shadcn/ui |
两端保留原仓库完整提交历史(子目录导入),
git log --follow可追溯。
本地启动
# 后端(需 JDK8,本地联调配置见 backend/docker-test/application-local.yml)
cd backend && mvn spring-boot:run
# 前端(dev 代理 /api -> localhost:8081)
cd frontend && bun install && bun dev
文件安全检测(MeshSafe 对接配置)
对接独立检测服务 MeshSafe(code.senmesh.com/zhaolei/MeshSate):文件上传与跨网传输接收解包后自动送检(HMAC-SHA256 签名 + 响应验签),结论回写 x_file_security 表并标记在文件上。
核心行为:
- 检测不通过的文件禁止分享与跨网传输(下载/预览不受限);文件夹内部分文件不通过时,分享/传输弹窗列出清单,用户确认后仅传输通过的内容(
onlyPassed=true) - 检测中 → 禁止分享/传输;检测失败 → 默认放行(仅标记,可重新检测)
- 管理员可人工复核改判(必填说明,留痕并回写 MeshSafe)、重新检测
- 列表"安全检测"列展示状态徽章 + 结论摘要,悬停浮窗显示全信息;检测中的文件列表每 2 秒自动轮询刷新
1. 后端配置(backend 的 application.yml)
meshsafe:
enabled: true # 总开关:false 时整体关闭——不送检/不拦截/预检返回空/前端隐藏检测列
base-url: https://meshsafe.internal # MeshSafe 服务地址
client-id: s-file # MeshSafe 分配的调用方标识
secret: "***" # MeshSafe 分配的密钥(勿泄露,建议环境变量注入)
channel: default # 业务通道标识(仅用于 MeshSafe 日志追溯)
timeout-seconds: 120 # 单次请求超时
fail-open: true # 检测服务异常时降级:true-放行(仅标记检测失败) / false-同样禁止分享传输
poll-timeout-minutes: 60 # "检测中"超过该时长仍无结论则标记检测失败(防死轮询)
review-sync-to-meshsafe: true # 人工复核是否回写 MeshSafe(失败仅告警,不影响本地生效)
poll:
cron: "0 */30 * * * ?" # 轮询未完成检测任务的定时任务(默认30秒)
| 配置项 | 说明 |
|---|---|
enabled |
总开关。关闭场景(无需 MeshSafe 的部署):后端上传/解包不送检、分享传输不拦截、/file_security/share_check 预检返回空、复核与重新检测接口报"文件安全检测未开启" |
fail-open |
安全优先的部署建议 false(检测服务异常时宁可阻断);可用性优先用 true |
| 其余 | 一般保持默认即可 |
2. 数据库
执行 backend/db/upgrade-20261101-meshsafe-file-security.sql(新增 x_file_security 检测记录表,MySQL/DM8 与 PostgreSQL 双节;全新环境直接执行 init 脚本已包含)。同一文件允许多条检测记录(复核/重检均新增),业务取最新一条。
3. MeshSafe 侧配置
- 向管理员申请调用方凭证,并将
client_id:secret加入 MeshSafe 的MESHSAFE_API_CLIENTS环境变量白名单; - MeshSafe 策略
config/policy.yaml的engine_failure_mode生产必须为fail_closed(引擎异常宁可拒绝),注意不要为了"服务没起来也能用"改成fail_open后带上生产; - 建议监控
GET /api/v1/health(重点clamav.available与签名库更新时间)。
4. 前端(无需配置)
前端通过 GET /file_security/enabled 自动感知总开关:开启时展示"安全检测"列与复核/重新检测入口,关闭时相关 UI 完全隐藏,无需前端发版。
5. 部署检查清单
- 执行数据库升级脚本(
x_file_security); - 后端配置
meshsafe:段并确认enabled: true; - MeshSafe 侧将后端凭证加入白名单,确认
/api/v1/health健康; - 重启后端,上传一个测试文件验证:列表出现"检测中"→ 数秒内变为"检测通过/不通过";
- 用测试样本验证拦截链路(分享/传输被拒、文件夹确认跳过、复核改判后放行)。
6. 相关文档与代码
- 接口文档:
backend/docs/接口文档-文件安全检测.md - 客户端实现:
backend/src/main/java/com/senmesh/sfile/client/MeshSafeClient.java(HKDF 密钥派生、请求签名、multipart 手工构造、响应验签) - 检测记录表:
x_file_security(实体FileSecurity,取最新一条生效) - 送检触发点:网盘上传(
NormalUserFileServiceImpl)、传输接收解包(TransferFileMonitorServiceImpl)、手动重检(/file_security/rescan)
Description
Languages
JavaScript
51.2%
Java
35.6%
TypeScript
6.4%
CSS
3.1%
HTML
2.8%
Other
0.9%