Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
17 KiB
涩花塘磁力助手 - 项目架构与部署说明
更新时间:2026-03-14
说明:本文档描述当前项目的整体架构、核心数据流、缓存策略、云同步设计、线上部署信息(不包含任何敏感凭据),以及当前已知问题与优化方向。
1. 项目概览
本项目由两部分组成:
-
Chrome 扩展端
负责在涩花塘论坛页面中:- 识别列表页 / 帖子页
- 批量抓取帖子与磁力链接
- 本地缓存帖子、范围快照、页快照、磁力结果
- 展示搜索结果、缓存总览、收藏夹、云同步入口
-
云端共享缓存服务
负责:- 共享线程缓存(shared thread cache)
- 共享范围缓存(shared coverage cache)
- 共享页缓存(shared page cache)
- 覆盖规划(coverage planning)
- 私有保险柜(vault)
- 账号注册 / 登录 / 鉴权
2. 目录结构
扩展端根目录
manifest.json:Chrome 扩展清单(MV3)content.js:内容脚本,挂载 UI、执行抓取、合并缓存、结果展示background.js:Service Worker,负责 IndexedDB、本地状态、云接口、跨页请求popup.html/popup.js:扩展独立云同步中心 + 快捷复制入口
服务端目录
server/package.json:服务端依赖与脚本server/src/index.js:Fastify 入口server/src/config.js:环境变量配置server/src/db.js:MySQL 连接池server/src/redis.js:Redis 连接与 JSON 缓存server/src/crypto.js:AES-GCM 加密与哈希server/src/auth.js:认证辅助逻辑server/src/routes/auth.js:注册 / 登录 / me / logoutserver/src/routes/vault.js:私有保险柜 push / pullserver/src/routes/shared-cache.js:共享缓存查找 / 写入 / coverage planningserver/sql/001_init.sql:数据库初始化表结构
3. 扩展端架构
3.1 页面层(content.js)
content.js 负责:
- 判断当前页面是:
- 列表页(forumdisplay / forum-x-y.html / normalthread tbody)
- 帖子页(thread-xxx / tid=xxx)
- 创建浮动面板 UI
- 管理:
- 关键词搜索
- 页码范围
- 速度模式
- 结果列表
- 收藏页
- 缓存页
- 云同步页入口
- 调用后台:
- 读取 / 保存本地缓存
- 读取 / 保存进度状态
- 触发云同步相关动作
3.2 后台层(background.js)
background.js 是当前项目的核心调度层,负责:
- IndexedDB 缓存存取
- 云缓存接口调用
- 共享缓存 planning 调用
- 上传抑制(hash 去重 + TTL 节流)
- 本地历史缓存回填到云端
- 私有保险柜加解密
- 云账号登录状态维护
3.3 本地存储层
当前本地存储分三类:
-
IndexedDB(结构化缓存)
threadscoveragespageCoverages
-
chrome.storage.local(扩展私有存储)
- 收藏夹
- 搜索历史
- 云同步状态
- 上传元数据去重表
- 进度状态
-
运行时内存态
- 当前抓取状态
- session backup 临时状态
4. 服务端架构
4.1 服务端职责
云服务现在不仅是“存数据”,还承担:
- 共享缓存存储
- 去重写入
- coverage planning
- Redis 缓存 planning 结果
- 账号认证
- 私有保险柜同步
4.2 路由职责
认证
POST /api/auth/registerPOST /api/auth/loginGET /api/auth/mePOST /api/auth/logout
私有保险柜
POST /api/vault/pushPOST /api/vault/pull
共享缓存
POST /api/shared-cache/threads/lookupPOST /api/shared-cache/threads/upsertPOST /api/shared-cache/coverages/lookupPOST /api/shared-cache/coverages/upsertPOST /api/shared-cache/pages/lookupPOST /api/shared-cache/pages/upsertPOST /api/shared-cache/coverages/plan
健康检查
GET /healthGET /ready
5. 本地缓存模型
5.1 threads
存储唯一帖子级信息:
forumKeythreadKeyurltitlelastSeenAtmagnetslastMagnetSyncAt
特点:
- 同一板块 + 同一帖子只保留一份
- 线程磁链缓存优先从这里命中
5.2 coverages
存储范围级快照:
forumKeystartPageendPagestrategyfrontRefreshPagesthreadKeys
特点:
- 表示某个页范围对应的帖子集合
- 用于 exact coverage / shifted coverage / 历史 coverage 碎片复用
5.3 pageCoverages
存储页级快照:
forumKeypagethreadKeys
特点:
- 用来组装连续页块
- 当前大范围命中优化的重要基础
6. 云端缓存模型
6.1 共享线程缓存 shared_thread_cache
- 唯一键:
(forum_key, thread_key) - 数据库存储加密:AES-GCM
- 用于跨用户复用帖子级磁链结果
6.2 共享范围缓存 shared_coverage_cache
- 唯一键:
(forum_key, start_page, end_page, strategy) - 用于整段范围的覆盖规划
6.3 共享页缓存 shared_page_cache
- 唯一键:
(forum_key, page) - 用于连续页块拼装
6.4 私有保险柜 vault_items
- 用户级密文存储
- 当前用于:
- 收藏夹
- 搜索历史
- UI 设置
- 进度状态
7. 抓取流程(当前实际运行路径)
7.1 点击“开始获取”后的流程
- 读取页码范围 / 关键词 / 速度配置
- 构建
searchContext - 显示:
正在规划缓存:检查本地缓存 / 云端规划 / 复用块...
- 调用
getCachedCoveragePlan(...) - 依次判断:
- exact coverage
- assembled page coverage
- 服务端 planning
- cachedBlocks
- shiftedCoverage
- 对缺口区间执行 live 抓取
- 结果与缓存合并后,再写回本地与云端
7.2 实际搜索执行路径
主要函数:
fetchFromPage(...)fetchLivePageRange(...)processCachedThreadBatch(...)applyCachedMagnetHits(...)
8. 去重与上传抑制策略
8.1 本地去重
- 线程去重:
normalizeCachedThreads() - 磁链去重:
normalizeMagnetList() - coverage 合并去重:
mergeCoverageThreads() - coverage 保存前合并:
mergeCoverageThreadLists()
8.2 云端去重
数据库唯一索引 + ON DUPLICATE KEY UPDATE
8.3 上传抑制
本地维护 upload meta:
threadscoveragespages
每类记录:
payloadHashlastUploadedAt
TTL:
- 线程:10 分钟
- 页:30 分钟
- 范围:60 分钟
作用:
- 降低重复上传
- 降低重复加密
- 降低数据库写入压力
9. 当前“智能更新”逻辑
已实现
- front refresh(从第一页开始时可刷新前段)
- shiftedCoverage 复用
- page cache block 复用
- intersecting coverage fragments 复用
- 服务端 coverage planning
- Redis 缓存 planning 结果
当前仍不够理想的点
-
thread cache 很多,但未完全反向沉淀成 page/coverage 索引
这会导致“明明有很多历史线程缓存,但大范围规划不够聪明”。 -
coverage 合并仍然偏保守
少量前页更新后,虽然已经补了历史 coverage 合并,但仍建议继续增强“旧帖保留连续性”。 -
前段刷新策略仍是经验型策略
当前已从“固定刷新前 20 页”改为“前面没有缓存覆盖才刷新”,但仍属于启发式策略。 -
启动前规划仍然是同步等待
现在已经加了状态提示,但未来可以做:- 本地快速规划优先
- 云端规划异步补充
10. 线上部署信息(不含敏感凭据)
服务器基础信息
- 公网 IP:
47.238.173.98 - 域名:
s.52oai.com - 系统:CentOS 7(当前会话已确认)
- 部署方式:Nginx + PM2 + Node.js + MySQL + Redis
- 面板:宝塔面板(BT Panel)
当前服务端组成
- Nginx:反向代理入口
- Node 服务:
magnet-cloud-cache - PM2:进程守护
- MySQL:主数据存储
- Redis:coverage planning 结果缓存
线上访问入口
https://s.52oai.com/healthhttps://s.52oai.com/ready
Redis 状态
当前已验证:
- Redis 可连接
- 可写入/读取 JSON
- coverage planning key 已落库
11. 当前安全边界
已完成的安全改造
- 云同步登录/注册 UI 已迁移到扩展独立页面
- 收藏/搜索历史已迁移到扩展私有存储
- session 进度备份已不再依赖页面
sessionStorage - shared-cache 写接口已加写入令牌鉴权
- shared-cache 已避免旧写覆盖新写
仍建议后续加强
vaultKeyBase64改为 session-only- auth/vault/shared-cache 更细粒度限流
- 服务端请求体大小再收紧
- 共享缓存写审计日志
12. 当前最值得继续优化的方向
P1 - 正确性优先
-
thread cache 反向沉淀成 page/coverage 索引
这是目前提升“大范围缓存命中率”的最高价值项。 -
coverage 合并策略继续增强
尤其是前段少量更新后,历史旧帖不应被挤出当前范围搜索。 -
规划器结果可观测化
建议增加 debug summary:- 命中 exact coverage
- 命中 page blocks 数
- 命中 intersecting coverage 数
- 实际缺口页数
P2 - 性能优先
- 本地快速规划优先,云端 planning 异步补充
- planning 结果本地短时缓存
- 回填队列分批化
12.1 当前抓取合并 / 去重 / 智能更新逻辑复盘
一、当前逻辑里已经做对的部分
-
线程级去重已经明确
- 本地通过
threadKey去重 - 云端通过
(forum_key, thread_key)唯一约束去重
- 本地通过
-
磁链级去重已经明确
- 本地通过
normalizeMagnetList()去重 - 云端共享缓存目前按线程保存,磁链集合在单线程内部去重
- 本地通过
-
coverage 规划已经从“只看精确范围”进化为多层来源
当前getCachedCoveragePlan()已经综合:- exact coverage
- assembled page coverage
- 服务端 planning
- cachedBlocks(页块)
- intersecting coverages(相交范围碎片)
- shiftedCoverage
-
上传抑制已经开始发挥作用
- thread/page/coverage 都有 upload meta
- hash + TTL 可以减少重复上云
二、当前逻辑不够理想的核心点
1. 线程缓存与页/范围索引仍然是“半脱节”
这是目前最关键的问题:
threads里可能已经积累了大量帖子与磁链- 但这些历史数据没有系统性地回灌成:
pageCoveragescoverages
结果就是:
看起来缓存很多,但真正能参与“大范围规划”的缓存块不够多。
2. 智能更新仍然偏启发式,而不是差异驱动
当前 front refresh / shiftedCoverage 还是基于:
- 从第 1 页开始时,倾向刷新前段
- 历史范围快照的最近性
但它缺少真正的:
- 基于“帖子是否变化”的差异判断
- 基于线程游标 / 内容指纹 / 页指纹 的更新模型
3. coverage 合并虽然已经补强,但仍然不够结构化
当前已经补了:
- 保存新 coverage 前,合并历史相交 coverage 的线程
但这个策略仍是:
- 按线程集合合并
- 不是按“真实页结构”或“线程页位置偏移”合并
所以在论坛前段轻微更新时,仍可能出现:
- 范围快照连续性不足
- 旧帖可见性波动
4. 服务端 planning 已加入,但仍然是“辅助规划器”
现在服务端已经能返回:
exactCoveragecachedBlocksshiftedCoverage
但扩展端仍保留了大量本地规划逻辑,导致:
- 本地规划与服务端规划并存
- 逻辑复杂度上升
- 调试成本高
三、当前最值得优先继续优化的技术方向
A. threads -> pageCoverages / coverages 反向沉淀
这是正确性和命中率的第一优先级优化。
目标:
- 当系统手里已经有大量 thread cache 时
- 能定期 / 按需将其重建为:
- page coverage block
- coverage fragment
收益:
- “缓存明明很多却命中不上”的问题会明显缓解
B. 引入“线程或页面指纹”作为智能更新依据
例如:
- 页面线程列表 hash
- 范围线程集合 hash
- 线程集合版本号
这样 front refresh 就能从“经验刷新”变成:
- 先比对指纹
- 只有前段真的变化才刷新
C. 最终把 planning 统一到服务端主导
建议目标不是“双规划器”,而是:
- 服务端负责 coverage planning
- 扩展端只负责执行计划
- 本地逻辑只保留兜底回退
这样架构会明显更稳。
P3 - 运维优先
- 共享缓存保留策略 / 归档策略
- 写入审计与异常监控
- 密钥轮换机制
13. 当前版本的整体评价
已经具备的能力
- 本地线程 / 范围 / 页缓存
- 云端共享缓存
- 私有保险柜
- 上传抑制与 TTL 节流
- coverage planning + Redis planning cache
- 扩展端 UI / 云同步中心 / 收藏 / 搜索历史
当前最核心的短板
缓存数据已经很多,但“如何把这些缓存组织成最优复用计划”仍然不够强。
也就是说,当前系统最难的不是“存缓存”,而是:
把已有缓存规划成正确、完整、连续的搜索路径
14. 文档使用建议
如果后续你继续迭代项目,建议把本文档当成:
- 新人接手说明
- 线上部署说明
- 缓存/同步逻辑总览
- 后续重构路线图
15. 敏感信息说明
本文档不记录以下信息:
- SSH 密码
- MySQL 密码
- write token
- 加密密钥
.env明文内容
这些信息应只保留在安全的部署环境与秘密管理系统中。
16. Chrome 分发与更新能力边界
结合当前平台限制和架构评估,下面是真实可行与不可行的边界。
16.1 对普通 Chrome 用户,不可直接做到的事
以下能力在普通非企业托管 Chrome 中,不现实或不受支持:
- 从网站自动把扩展装进 Chrome
- 通过主页密码后,静默安装 CRX
- 普通用户使用自托管 CRX 自动更新
也就是说:
s.52oai.com可以做“分发引导页”,但不能真正实现“输密码后自动装到 Chrome 里”。
16.2 最现实的分发方式
对于普通用户,最推荐:
- 发布到 Chrome Web Store(建议 unlisted)
s.52oai.com做密码门禁页- 门禁通过后展示:
- CWS 安装链接
- 安装说明
- 使用说明
这样可以获得:
- 官方安装路径
- Chrome 自动更新
- 最低用户支持成本
16.3 自托管更新什么时候才成立
只有在以下场景,自托管更新才是现实方案:
- 企业托管 Chrome
- 管理员通过策略安装
- 使用企业设备 / 组织统一管理浏览器
这不是普通公网用户场景。
16.4 当前项目建议的分发策略
如果未来要正式分发,推荐顺序:
- Chrome Web Store(最好 Unlisted)
s.52oai.com做密码门禁与引导页- 扩展内做“最低支持版本”检查
- 如果版本太低,则提示用户去商店更新
16.5 站点密码的真实作用
主页密码(例如 123456)只能充当:
- 引导门槛
- 简单访问控制
- 降低无关访问
但它不能视为真正安全边界。真正的权限控制仍然必须放在:
- 后端账号系统
- API 鉴权
- 服务端授权逻辑
16. Chrome 分发与更新能力边界(部署到主页的现实约束)
16.1 对普通 Chrome 用户,不能直接做到的事
对于普通、非企业托管的 Chrome 用户,当前不支持:
- 从
s.52oai.com网页直接自动安装扩展 - 从自有网站静默安装 CRX
- 对普通用户使用自托管 CRX 做自动更新
也就是说:
网站可以做“入口页 / 密码门禁页 / 引导页”,但不能真正代替 Chrome 官方安装渠道完成自动安装。
16.2 对普通用户最现实的方案
最可行方案是:
- 发布到 Chrome Web Store(建议 Unlisted)
s.52oai.com作为密码门禁页- 输入密码后展示:
- Chrome Web Store 安装链接
- 使用说明
- 更新说明
这样可以获得:
- 标准安装体验
- Chrome 自动更新
- 最低的用户支持成本
16.3 自托管自动更新什么时候可行
只有在:
- 企业托管 Chrome
- 管理员策略安装
- 受管设备/受管浏览器环境
这种情况下,自托管 CRX + update manifest 才是现实路径。
16.4 当前项目推荐的分发模式
推荐顺序:
- Chrome Web Store(Unlisted) 作为主分发渠道
s.52oai.com做密码门禁 + 安装引导页- 扩展内调用服务端
/ext/config(后续可实现)检查最低支持版本 - 如果版本过低,提示用户跳转到商店升级
16.5 密码门禁的真实作用
密码门禁只能起到:
- 隐藏安装入口
- 控制谁能看到链接
但它不能视为真正的安全边界。真正的权限控制必须放在:
- 后端账号体系
- API token / 登录态
- 服务器侧权限判断