17 KiB
DHT 元数据搜索服务计划
本文档记录项目当前规划实施顺序和完成状态
它是随需求实现结果性能数据和部署条件持续调整的活文档
维护规则
- 已经通过验收的任务使用
[x]标记 - 正在规划但尚未完成的任务使用
[ ]标记 - 需求变化时允许新增删除拆分合并或调整阶段顺序
- 调整计划时同步修改任务说明依赖关系和验收标准
- 不因代码已经存在就标记完成必须满足对应验收标准
- 发现原方案不合适时记录新决策并更新后续阶段
- 每次完成一个可交付功能时同步更新本文档
当前技术方向
src/crawler负责可复用的 DHT 协议节点发现 Peer 查找和 Metadata 下载src/search负责持久化去重索引搜索接口配置和运行生命周期src/web负责最终用户搜索诊断和配置管理界面- RocksDB 保存权威数据去重信息和任务状态
- Tantivy 保存可以从 RocksDB 重建的搜索索引
- Axum 提供搜索详情统计和健康检查接口
- 用户配置使用强类型 DTO 表达 TOML 只是当前持久化适配器
- SQLite 保存有明确保留上限且可安全删除的运行诊断历史
- 所有长期任务通过有界队列和背压控制资源占用
如果实际运行证明 RocksDB 的构建部署或资源成本不合适可以重新评估 redb SQLite 或其他存储方案
阶段零 项目基础
目标
建立清晰的 workspace 边界开发规则和可持续验证的基础库
任务
- 将 crawler search 和 web 源码统一收纳到根目录
src - 使用当前 Git 配置统一作者仓库许可证和 edition 元数据
- 编写
AGENTS.md记录架构边界和开发约定 - 将最终应用与可复用 DHT 基础库分离
- 删除被内容组索引替代的旧状态和无效兼容代码
- 收紧仅供测试或存储内部使用的接口和依赖
- 实现 BEP-51
sample_infohashes主动发现 - 实现主动 Peer 查找和 Metadata 获取
- 验证远程公网设备能够持续获取 Metadata
- 确认 Xray 全局代理会影响 Metadata TCP 连接并完成旁路验证
- 保持基础库测试通过
验收标准
cargo check --workspace --all-targets通过dht-crawler单元测试通过opencodes参考项目不参与 workspace 构建
阶段一 本地持久化基础
目标
建立跨重启保留的权威数据源并完成精确去重和内容聚合基础
任务
- 定义二十字节
InfoHash类型和十六进制转换 - 定义
TorrentRecordTorrentFile和内容组索引状态 - 校验名称文件列表文件总大小和 infohash
- 使用 BLAKE3 计算规范化内容指纹
- 规范化 Unicode 路径分隔符大小写和文件顺序
- 保留真实子目录避免内容指纹碰撞
- 定义 RocksDB 二进制键空间
- 实现数据库格式检查
- 实现 infohash 精确查询和存在性判断
- 实现新记录 WriteBatch 原子写入
- 实现重复 infohash 的
last_seenseen_count和 Peer 更新 - 实现相同内容不同 infohash 的聚合映射
- 实现待索引记录查询和索引完成标记
- 配置 Bloom Filter LZ4 压缩和有限 block cache
- 准备 Windows 本地 RocksDB 构建所需的 libclang
- 将本地构建工具目录排除出 Git
验收标准
- 数据库关闭并重新打开后记录仍可读取
- 重复写入不会创建第二条 torrent 记录
- 重复写入会正确增加发现次数
- 相同内容的不同 infohash 可以独立保存并聚合查询
- Metadata 主体内容映射和待索引标记原子写入
- RocksDB 功能测试通过
dht-searchClippy-D warnings通过
阶段二 采集持久化闭环
目标
让 DHT 获取的真实 Metadata 自动进入有界持久化管线并支持安全停止和重新启动
任务
- 定义应用配置结构和默认配置文件
- 支持通过配置指定固定数据目录
- 支持配置 DHT 端口并发队列容量和 Metadata 限制
- 初始化 RocksDB repository 并处理启动错误
- 将
TorrentInfocallback 转换为TorrentRecord - 建立有界持久化队列并实现背压
- 使用专用阻塞任务执行 RocksDB 操作避免阻塞 Tokio worker
- 在 Metadata 下载前查询持久化 infohash 状态减少重复下载
- 在 BEP-51 Peer Lookup 前批量查询 RocksDB 并更新已有 infohash 发现状态
- 将已存在记录更新为再次发现而不是重复创建
- 增加接收写入重复拒绝失败和队列深度指标
- 实现
Ctrl+CSIGINT和SIGTERM优雅退出 - 退出时停止接收新任务并排空或持久化剩余任务
- 支持重新启动后继续使用原数据库
- 将 example 运行方式替换为正式
dht-search二进制 - 支持通过运行时长参数进行间歇运行
验收标准
- 本地运行可以持续向 RocksDB 写入真实 Metadata
- 停止并重启后旧 infohash 不会作为新记录重复写入
- 队列达到容量时内存不继续无界增长
- 正常退出后已接受的任务不会静默丢失
- 远程设备运行一小时没有持续内存增长
- 记录采集速度重复率数据库增长和写入延迟
阶段三 Tantivy 搜索索引
目标
让持久化 Metadata 支持快速全文搜索过滤排序和索引恢复
任务
- 定义 Tantivy schema 和索引版本
- 索引名称文件路径扩展名 infohash 和内容指纹
- 将大小文件数时间和发现次数定义为 fast fields
- 设计中英文数字和文件名子串 tokenizer
- 实现待索引任务批量消费
- 实现按数量和时间间隔批量 commit
- commit 成功后原子更新 RocksDB 索引状态
- 实现关键词短语和精确 infohash 查询
- 实现大小时间扩展名文件数热度和可用性过滤
- 实现大小范围和扩展名过滤
- 实现相关性时间热度大小和发现次数排序
- 建立带时间衰减的 DHT 活跃度分数和用户可读等级
- 实现分页并限制最大翻页成本
- 实现相同
content_key结果精确折叠和变体分页 - 实现从 RocksDB 全量重建 Tantivy 索引
- 支持索引结构不兼容时直接重建
验收标准
- 新写入记录在目标延迟内可搜索
- 搜索索引删除后可以从 RocksDB 完整重建
- 索引过程中异常退出不会永久丢失文档
- 百万级测试数据常用查询延迟达到
BENCHMARKS.md约定目标
阶段四 HTTP 搜索服务
目标
提供稳定可验证并且资源受限的搜索和详情接口
任务
- 使用 Axum 建立 HTTP 服务
- 实现
/health和/ready接口 - 实现
/stats运行状态接口 - 实现
/search搜索过滤和分页接口 - 实现
/torrents/{infohash}详情接口 - 实现
/contents/{content_key}内容变体接口 - 使用 Bun Vue TypeScript Vite Tailwind CSS 和 shadcn-vue 建立 Web 基础环境
- 实现简单现代并适配移动端的单页搜索界面
- 接入搜索排序分页详情内容变体和磁力链接复制
- 实现名称别名和文件路径的有限状态自动机正则搜索
- 在普通搜索中自动识别通配符并保留独立正则开关
- 实现种子详情文件列表后端分页并限制浏览器单页节点数量
- 保留种子详情顶部结构并使用 reka-ui 数字分页重构文件条目
- 支持用户选择并持久化文件列表每页数量
- 统一搜索结果数字分页并支持用户选择每页数量
- 将采集索引持久化和验证运行状态集中到系统诊断页并仅在页面打开时每秒刷新
- 实现浏览器持久化明暗主题
- 为加载空结果接口错误和失败重试提供明确界面状态
- 将生产静态资源交给 Axum 提供并支持单页回退
- 提供 Windows 一键启动后端和 Web 开发服务的脚本
- 修复一键启动脚本只停止父进程导致 Vite 子进程残留的问题
- 定义统一错误响应
- 限制查询长度分页大小和最大 offset
- 增加请求延迟错误率和并发指标
- 增加搜索详情字段和按需验证入队 API 端到端测试
- 增加搜索过滤折叠精确哈希和变体接口测试
验收标准
- API 能搜索真实采集数据
- 非法参数返回稳定的客户端错误
- 搜索查询在独立阻塞任务执行不会阻塞异步 worker
- 健康检查能区分进程存活和服务可用
阶段五 质量过滤和重复内容控制
目标
减少垃圾数据和重复展示同时避免不可恢复的误删
任务
-
将种子可用性定义为最近通过 DHT 找到并完成 BitTorrent 握手
-
区分 Metadata 结构有效和 swarm 当前可用性
-
实现未验证活跃和可能失效三态模型
-
实现详情高优先级和搜索普通优先级的仅按需验证
-
使用持久化有界验证队列租约恢复去重和失败退避
-
Metadata 与验证握手共享 TCP 建连总预算
-
开发阶段清理测试数据库并以当前数据结构重新采集
-
搜索和详情接口返回热度与可用性数据
-
/stats返回验证队列发现握手成功失败和拒绝指标 -
统计真实数据的 infohash 重复率和内容重复率
-
在统一
config.toml中定义文件名和文件路径隐藏规则 -
支持精确前缀后缀包含通配符和正则匹配并限制规则复杂度
-
保留 RocksDB 原始文件列表并为详情统计搜索和内容聚合生成有效内容视图
-
使用规则指纹在配置变化时重算内容组并从 RocksDB 重建 Tantivy
-
默认隐藏 BitComet padding 文件以及
.pad和.____padding_file填充目录 -
全部文件被隐藏的 Metadata 只保留原始记录且不进入公开索引
-
根据真实垃圾数据决定是否增加种子名称扩展名和大小准入规则
-
增加按规则 ID 分类的隐藏文件命中指标
-
定义可配置的 Metadata 最大大小文件数名称路径长度和目录层级限制
-
识别空名称控制字符异常路径大小溢出总大小不一致和文件数量攻击
-
设计可解释的名称标准化规则
-
为模糊相似结果生成聚合候选但不自动删除
-
支持黑名单规则版本和命中原因
-
使用带规则指纹的 RocksDB 轻量拒绝记录阻止相同异常 infohash 重复下载
-
保留按原因分类的过滤指标但避免保存名称和大文件列表
-
增加误判测试和边界数据集
验收标准
-
搜索和详情响应不等待 DHT 或 Peer 网络验证
-
进程重启后已接受的验证任务能够通过租约恢复
-
一次验证失败不会删除记录或标记为绝对失效
-
数据清空后能够建立新的内容组搜索文档
-
精确重复不会重复下载和重复展示
-
内容重复可以折叠并保留全部 infohash
-
过滤规则可以配置更新和回滚且不会删除原始 Metadata
-
模糊去重不会直接造成数据丢失
阶段六 性能资源和长期运行
目标
以真实数据验证持续运行时的吞吐延迟磁盘放大和资源上限
任务
- 增加
find_nodePeer Lookup 新目标和 Metadata 建连的显式配置 - 为主动
find_nodeget_peers和sample_infohashes增加共享 UDP 查询总预算 - 为 Metadata TCP 建连增加独立每秒速率限制
- 使用保守网络预算定位早期本机断网问题
- 根据本机首次验证将主动 UDP 从
40/s下调至10/s并将 Metadata 建连从5/s下调至2/s完成故障隔离 - 对照 Bitmagnet 默认并发建立受全局预算和有界队列保护的激进配置
- 根据两轮一分钟资源测试将 Bitmagnet 等效激进配置设为应用和运行模板默认值
- 修复 Windows 临时索引文件占用导致整个服务退出的问题
- 验证极保守配置运行三分钟不影响同机代理网络并安全退出
- 将 BEP-51 采样准入压力反向传递到采样查询调度
- 实现样本来源节点单点
get_peers优先和失败后有限递归降级 - 将 BEP-51 最大在途请求和采样失败后的迭代回退暴露为应用配置
- 使用 Bitmagnet 等效并发完成一分钟资源测试并确认主网卡无丢包无错误且持久化无积压
- 将新发现但尚未验证的节点按地址稳定分流到有界 BEP-51 通道并避免与
find_node重复探测 - 增加直接采样候选队列请求响应重复过滤丢弃和 Metadata 成功来源转化指标
- 使用相同网络预算对旧快照采样和新节点直接采样完成十分钟对比
- 确认直接采样在相近 UDP 流量下 Metadata 成功数提高约百分之六点六且单条成功 UDP 成本降低约百分之六点六
- 完成首轮三分钟对比并验证 Peer Lookup UDP 从
278降至254且网络稳定 - 通过多轮或更长时间运行评估随机 DHT 样本下的 Metadata 成功率
- 统计按需验证的 Peer 发现率握手成功率和平均验证耗时
- 完成首轮真实按需验证并确认旧记录两次握手均成功更新为活跃
- 验证新 Metadata 记录直接继承成功来源 Peer 的活跃状态
- 验证启用按需可用性功能后保守预算运行三分钟并安全停止
- 根据真实验证数据校准热度权重等级边界和失败退避时间
- 根据公网设备长期实测设计超时率自动降速
- 建立可重复的采集存储索引和查询规模基准工具
- 完成一万十万和一百万条 release 基线并记录查询 P50 P95 P99
- 记录每条元数据和每个索引文档的平均磁盘占用
- 记录百万级基准进程峰值内存和索引总吞吐
- 记录 RocksDB block cache memtable 和 compaction 指标
- 记录 Tantivy IndexWriter 内存和 commit 延迟
- 根据实测调整批量大小队列容量和并发
- 增加带排空阶段恢复滞回和探测失败保护的磁盘只读降级策略
- 增加在线 RocksDB 检查点保留上限只读校验和带旧库保留的离线恢复
- 增加可配置的终端日志滚动文件日志和保留文件上限
- 验证间歇运行和正常退出恢复
- 完成本机约七小时真实持续运行并确认采集索引和搜索服务可用
- 验证二十四小时和七天连续运行
- 根据规模决定是否继续使用 RocksDB
验收标准
- 内存使用在目标上限内稳定
- 队列和缓存不会随运行时间无限增长
- 磁盘不足时能够拒绝新任务排空持久化队列并保留搜索能力
- 备份可以在独立目录恢复并从 RocksDB 重建索引搜索
- 连续运行期间没有数据格式损坏和不可恢复任务
阶段七 部署和运维
目标
让应用可以在公网 Linux 设备上重复构建部署监控停止和恢复
任务
- 固化 Linux 目标构建方式和 RocksDB 构建依赖
- 生成 release 二进制并使用 SHA-256 校验部署
- 定义配置数据日志和索引目录布局
- 编写 systemd service
- 编写 systemd timer 支持间歇运行
- 使用专用低权限 UID 运行验证
- 固化 Xray 环境下的最小范围网络旁路
- 验证高并发运行需要
LimitNOFILE=65536 - 实现启动前数据目录权限检查
- 实现优雅升级和回滚流程
- 编写备份恢复和故障排查文档
验收标准
- 新设备可以按文档完成部署
- 服务重启不会丢失已提交数据
- Xray 旁路只影响爬虫进程
- 更新失败时可以恢复上一版本二进制和数据
当前下一步
- 按职责拆分应用编排索引 worker 运行监控搜索查询构建和 Tantivy 文档映射
- 按领域边界拆分 infohash Metadata 校验内容聚合和种子活跃状态
- 将 DHT 响应限流器从服务器编排中提取为独立组合组件
- 将规模基准拆分为参数数据集工作负载采样报告和编排模块
- 明确单元组件集成端到端和性能测试层级并增加公开 API 集成测试
- 实现可回滚的无效文件过滤并重建有效内容聚合和搜索索引
- 将 crawler search 和 web 统一迁移到根目录
src并修复构建脚本文档路径 - 使用领域 Metadata DTO 切断领域层对 DHT 传输 DTO 的直接依赖
- 将配置拆分为可序列化 DTO TOML 读取适配器和运行时解析结果
- 使用独立 SQLite 建立有界运行诊断历史存储
- 采集进程 RocksDB Tantivy DHT 队列和磁盘资源快照
- 提供当前诊断快照和原始或分钟历史查询接口
- 将 HTTP 请求并发客户端错误服务端错误和延迟分布写入诊断历史
- 增加配置查询完整校验原子保存并发修订和统一重启提示
- 增加 Web 诊断页和配置管理页
- 使用页签拆分配置分类并隐藏底层配置存储位置
- 将主配置和内容过滤规则合并为唯一
config.toml - 将用户可编辑配置的持久化适配器从 TOML 迁移到 SQLite
完成二十四小时持续运行并继续观察私有内存 Metadata 成功率候选队列深度和每条成功 Metadata 的网络成本
RocksDB Tantivy HTTP 和进程资源指标已经接入诊断历史 后续根据长期实测继续调优
下一轮结构优化优先拆分 crawler 中的运行统计调度器和抓取引擎以及 search 中的 RocksDB 适配器 不为拆分而新增 crate