Files
dht/dht-search
2026-08-06 23:02:18 +08:00
..
2026-08-06 23:02:18 +08:00
2026-08-06 23:02:18 +08:00
2026-08-06 23:02:18 +08:00

dht-search

dht-search 是集 DHT Metadata 采集 RocksDB 持久化 Tantivy 搜索索引和 HTTP API 于一体的应用

构建准备

RocksDB 包含 C++ 代码并在构建时使用 bindgen 因此需要 libclang

Windows 可以把 libclang 安装到工作区本地目录

python -m pip install --target .tools\libclang libclang
$env:LIBCLANG_PATH = "$PWD\.tools\libclang\clang\native"
cargo build -p dht-search --release

.tools 只用于本地构建不会部署到运行设备

配置

复制根目录的配置模板

Copy-Item dht-search.example.toml dht-search.toml

相对 data_dir 以配置文件所在目录为基准解析

也可以通过命令行覆盖数据目录和本次运行时长

cargo run -p dht-search -- --data-dir D:\data\dht-search --run-duration-secs 3600

不设置 run-duration-secs 时服务持续运行直到收到 Ctrl+C SIGINT 或 SIGTERM

网络保护配置

主动 DHT 查询共享 max_outbound_queries_per_second 总预算,因此 find_node get_peerssample_infohashes 的总发送速率不会各自叠加后失控

配置项 保守默认值 作用
max_outbound_queries_per_second 10 三类主动 DHT UDP 查询的合计每秒速率
outbound_query_burst 2 空闲后允许立即消费的 UDP 查询数
find_node_queries_per_second 6 find_node 自身速率上限
find_node_max_in_flight 12 同时等待响应的 find_node 数量
new_destinations_per_minute 60 每分钟首次探测的新 UDP 目标数量
peer_lookups_per_second 1 每秒启动的 infohash Peer 查找数量
peer_lookup_max_active 4 同时运行的 Peer 查找数量
sample_queries_per_second 1 BEP-51 采样查询速率
metadata_workers 8 同时处理的 Metadata 任务数量
metadata_connects_per_second 2 每秒真正开始的 Peer TCP 连接数量

Metadata 下载和可用性握手共用 metadata_connects_per_second 预算不会各自叠加

按需可用性验证

搜索结果和详情访问只会把已过冷却期的种子异步加入持久化验证队列 HTTP 响应不会等待 DHT 或 Peer 网络

配置项 默认值 作用
verification.enabled true 是否启用按需可用性验证
verification.queue_capacity 10000 持久化验证队列容量
verification.max_active 2 同时验证的种子数量
verification.max_peer_attempts 3 每个种子最多握手的 Peer 数量
verification.lease_secs 60 异常退出后验证任务重新可领取的租约时间
verification.poll_interval_millis 250 持久化队列轮询间隔

详情访问使用高优先级 搜索结果使用普通优先级 队列满时高优先级可以替换最旧普通任务

可用性分为 unknown activepossibly_stale 一次或多次验证失败只表示当前可能没有可连接 Peer 不会删除种子

新抓取记录会把成功下载 Metadata 的来源 Peer 视为一次有效验证 旧记录按需复查时会同时使用新 DHT 结果和已保存的成功来源 Peer

热度是近期 DHT 发现强度最近出现时间和可连接 Peer 数的综合活跃度分数 不代表全球下载量

桌面网络不要在不了解路由器 NAT 和代理容量时大幅提高这些值

采样去重和 Peer 查找

BEP-51 返回的 infohash 会先进入有界批量准入队列并由 RocksDB 精确判断

已有 infohash 只更新最后发现时间和发现次数不会再次执行 Peer Lookup

未知 infohash 首先只向返回样本的 DHT 节点查询一次 get_peers 只有单点查询没有返回 Peer 时才降级为有限迭代查找

/stats 中的 sampled_hashes_filtered peer_lookup_preferred_succeededpeer_lookup_fallbacks 用于观察提前去重和单点优先效果

Linux 资源限制

生产环境仍可能同时使用较多 TCP socket

Linux 生产运行必须把文件描述符上限提高到至少 65536

prlimit --nofile=65536:65536 -- \
  /opt/dht-search/dht-search --config /opt/dht-search/dht-search.toml

systemd 服务需要设置

[Service]
LimitNOFILE=65536

文件描述符上限过低时 DHT 连接会挤占 Tantivy 和 RocksDB 打开文件所需的描述符并导致服务安全停止

API

默认只监听 127.0.0.1:8080

GET /health
GET /ready
GET /stats
GET /search?q=ubuntu&offset=0&limit=20
GET /search?q=&min_size=1048576&max_size=10737418240&extension=mkv
GET /torrents/{infohash}

limit 被限制在 1 到 100 之间且 offset 最大为 10000

搜索和大小扩展名过滤由 Tantivy 索引执行不会把全部记录加载到内存过滤

搜索响应包含 heatavailability 摘要 详情响应包含完整验证时间 Peer 数和连续失败次数

数据恢复

RocksDB 是权威数据源而 Tantivy 是可重建索引

当 Tantivy 目录不存在时应用会把全部 RocksDB 记录重新标记为待索引并自动完成全量重建

RocksDB v1 会在启动时通过可恢复迁移升级到 v2 旧 Tantivy schema 会先备份再从 RocksDB 重建 重建提交完成后清理备份

正常退出会先停止 DHT 再排空持久化队列提交剩余索引最后关闭 HTTP 服务