OpenMAIC 服务端持久化的资产字节怎么备份、回收与保留?

发布时间:2026/9/12 21:01:09
OpenMAIC 服务端持久化的资产字节怎么备份、回收与保留? OpenMAIC 服务端持久化的资产字节怎么备份、回收与保留【免费下载链接】OpenMAICOpen Multi-Agent Interactive Classroom — Get an immersive, multi-agent learning experience in just one click项目地址: https://gitcode.com/GitHub_Trending/op/OpenMAIC当你把 OpenMAIC 部署成服务端持久化server-backed persistence形态后课堂里的图片、音频、视频这些资产字节不再只存在于浏览器 IndexedDB 中而是落在服务器侧默认写在 PostgreSQL 的字节列里也可以整个切到 S3。随之而来的三个运维问题是这些字节去哪里备份、被删除后由谁回收、以及被删除的字节实际上能保留多久。这篇文章基于仓库文档回答这三个问题并给出每一步的验证方式。适用前提你正在使用或准备使用server-persistenceCompose profile 部署 OpenMAIC应用容器 PostgreSQL 两个容器持久化 HTTP 服务内嵌在应用的/api/persistence没有独立的持久化服务。仅浏览器本地运行不配置DATABASE_URL的部署不存在服务端资产字节本文内容不适用。资产字节落在哪一层OpenMAIC 的资产存储分两层见 asset HTTP 契约注册表registry资产 id、归属、媒体类型、元数据、引用计数始终存放在事务性存储即 PostgreSQL中字节层byte layer可插拔。默认是 PostgreSQL 中的一列配置ASSET_S3_BUCKET后切换为 S3对象以内容哈希命名。也就是说无论字节层选哪个注册表都在同一个 Postgres 库里只有字节本体随ASSET_S3_BUCKET的取值改变位置。前提启用 server-persistence 部署按 README.md 的 “Server-backed persistence (PostgreSQL)” 一节cp .env.example .env.local printf \nDATABASE_URLpostgres://openmaic:openmaic-devpostgres:5432/openmaic\nPERSISTENCE_DEV_TOKENopenmaic-local-dev\n .env.local NEXT_PUBLIC_PERSISTENCE1 NEXT_PUBLIC_PERSISTENCE_TOKENopenmaic-local-dev docker compose --profile server-persistence up --build两点与本文直接相关的注意事项NEXT_PUBLIC_PERSISTENCE是构建期开关编译进浏览器 bundle启用了它的构建必须配上可用的运行时DATABASE_URL和PERSISTENCE_DEV_TOKEN且NEXT_PUBLIC_PERSISTENCE_TOKEN在构建时必须与服务端 token 一致否则浏览器会选中 HTTP 持久化但内嵌端点报错首页会显示 persistence-unavailable 提示并保留之前的课程列表。PERSISTENCE_DEV_TOKEN方案没有任何用户隔离能力文档明确它只适合 localhost 或可信网络的单用户部署上生产前需要替换 lib/persistence/server-auth.ts 中真实的会话校验。备份资产字节备份 Postgres 还是备份 S3 桶文档没有给出额外的资产专属备份命令因为备份目标就是字节所在的存储本身。默认形态和 S3 形态各有一个主备份对象默认PostgreSQL 字节列资产字节就是openmaic数据库的一部分。asset HTTP 契约 明确说明这种形态下“字节会流经预写日志WAL和备份因此备份与复制的体积会随存储的资产规模增长”。因此用你现有的 Postgres 备份手段逻辑备份、数据卷openmaic-postgres的卷级备份备份整个数据库资产字节与课程文档、学习者运行时数据一起被覆盖反过来资产越多这类备份的体积越大——这也是文档把“把字节层迁到对象存储”列为该形态的后续演进原因配置时要有心理预期。S3 字节层字节在桶里由 S3 侧的保留/复制策略承担Postgres 里只剩注册表。文档同时提醒这种形态多出一项家务事进程崩溃窗口会留下无人引用的对象需要自行清理或按过期策略处理由于对象以内容哈希命名重复写入同字节会幂等覆盖孤儿对象是无害的。两种形态下注册表都不可缺它持有 id 到内容哈希的映射和引用计数只备份字节而不备份库或反之都无法还原完整的资产状态。一个影响备份策略的运维细节来自 README.mdPERSISTENCE_POSTGRES_PASSWORD只在数据目录为空时初始化角色之后改它不会轮换已有卷里的密码。要轮换密码并保留数据正确做法是连接数据库执行ALTER ROLE openmaic WITH PASSWORD new-password;再更新DATABASE_URL。而文档给出的docker compose --profile server-persistence down -v中的-v会删除数据卷只可用于丢弃型本地库执行前确认你不需要保留这些数据。回收离线 collector 的行为与可调参数删除或替换某个资产只会删掉注册表条目字节本身由一个离线 collector回收。关键性质asset HTTP 契约 “Where the bytes live” 与 README.md请求路径从不删除字节写路径先锁定 blob 行再写字节读路径持共享锁读字节collector 持排他锁删除三者互不破坏每个候选 blob 在自己的事务里FOR UPDATE加锁并复查后才删所以多实例同时开 collector 也只是串行化不会竞态这个部署默认就在跑 collector不需要任何配置资产存储才会在回收后停止增长。collector 由应用进程调度实现见 lib/persistence/asset-collector-schedule.ts相关配置都在 .env.example 的 “Server-backed Persistence” 一节# 仅当 DATABASE_URL 已配置时 collector 才存在默认开启 ASSET_COLLECTION_ENABLED0 # 可选设为 0 或 false 关闭本进程的回收 ASSET_COLLECTION_INTERVAL_MS900000 # 可选一轮回收的间隔默认 90000015 分钟下限 1000ms ASSET_COLLECTION_GRACE_MS3600000 # 可选字节失去最后引用后的保留窗口默认 36000001 小时各参数的用途与边界ASSET_COLLECTION_INTERVAL_MS是调度节奏不是保留时间。README 说明默认 15 分钟“短到被删资产的字节当天就消失长到不会干扰正常请求流量”。进程内传入的不是安全整数或低于 1000ms 的值会被告警并回退默认值。进程启动后第一轮在一个间隔之后才运行冷启动不会与 PostgreSQL 就绪竞态。ASSET_COLLECTION_GRACE_MS才是真正的保留窗口见下一节。ASSET_COLLECTION_ENABLED0只在当前进程关闭回收。横向扩容的部署可以所有实例都开着有行锁保护也可以全部关掉、自己跑一个文档把“两处都不管”列为会无界增长的设计。保留grace period 到底保留了什么字节在失去最后一个引用后至少存活一个 grace period默认 1 小时之后才可能被 collector 收走。README 的原话是“grace period 就是用户删除的字节实际得到的保留窗口所以应该刻意deliberately调大它”——如果你的合规要求是“删除后 N 天内不真正消失”就把这个值设为 N而不是依赖默认 1 小时。全局去重意味着remove从来不保证字节被销毁字节跨用户共享只要有其他主体的注册表条目仍引用它它就一直保留。文档明确指出“remove本来就无法承诺字节被销毁”这是去重设计的固有结果不是可调项。一个值得知道的反向事实注册表条目指向的字节如果被回收了该 id 的读取解析为miss未命中而不是报错客户端按404 ASSET_NOT_FOUND处理。元数据同样有保留含义生成时的 provenance 文本提示词、旁白、音色等随资产持久化但当前没有任何代码路径会把它读回来。文档提醒这类调用方提供的文本“应遵循其所需的保留与隐私姿态”做数据保留策略时要把它算进去。可选S3 间接字节出口ASSET_BYTE_EGRESSredirect如果字节层在 S3可以把GET字节改为返回短时效签名 URL302或打包客户端请求的 JSON 描述符把下载流量从应用服务器挪走。README 给出启用前必须满足的两个对象存储前提桶的 CORS 允许本应用的 origin并在签名响应上暴露Content-Type签名身份持有桶的s3:ListBucket权限这样缺失的 key 返回404 NoSuchKey而不是403——客户端只有靠这个代码才能把“字节已被回收”识别为 miss。PostgreSQL 字节列不能签名配置了ASSET_BYTE_EGRESSredirect也会自动回退到直接字节。asset HTTP 契约 还规定了签名 URL 的有效期必须远低于 grace period打包处理器要求它小于 grace 的十分之一且不超过 15 分钟上限否则构建失败并明确这是一个知情选择以哈希为对象名的签名 URL 会泄露跨 id 的字节相等性同时对象存储的ETag/Last-Modified头签名无法剥离。对这类信号敏感的部署应维持直接出口。验证确认备份与回收按预期工作文档提供的判断依据回收在运行collector 每轮若回收了 blob会打印日志Asset collector reclaimed n unreferenced blob(s)文档示例格式n为实际数量仅大于 0 时打印某轮失败则打印Asset collection pass failed; retrying on the next interval进程不会退出下一轮间隔自动重试。观察这两行日志即可判断调度是否活着。被回收的字节读起来是 miss按契约注册表条目字节被收走后该 id 的读/替换返回固定的404 ASSET_NOT_FOUND与其他用户的 id、从未分配过的 id 完全不可区分。持久化配置错误可观察构建启用了NEXT_PUBLIC_PERSISTENCE但运行时 token/DATABASE_URL不匹配时首页显示 persistence-unavailable 提示并保留旧课程列表而不是显示空库——这是判断“浏览器连上了服务端持久化”与否的可见信号。S3 出口生效与否ASSET_BYTE_EGRESSredirect S3 时字节 GET 得到签名 URL或描述符字节层无法签名如 PG 列时同一请求得到直接字节两种形态客户端都能处理无需额外开关。限制字节读取是整份物化的契约不支持Range读字节会把整个资产读入内存大媒体是这条链路的真实上限remove之后字节仍在磁盘上停留至多一个 grace period 再被收集存储会在 collector 运行前持续增长——这是设计代价不是故障开发 token 方案不提供用户隔离任何能加载页面的人都可枚举学习者分区备份文件本身包含所有用户数据按生产敏感数据对待浏览器本地模式未配DATABASE_URL下所有资产在 IndexedDB服务端没有任何字节可备份本节的备份/回收讨论不适用。【免费下载链接】OpenMAICOpen Multi-Agent Interactive Classroom — Get an immersive, multi-agent learning experience in just one click项目地址: https://gitcode.com/GitHub_Trending/op/OpenMAIC创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考