本方案用于评估在品牌商用 NAS 下载器中,用
libtorrent替代qBittorrent-nox,构建自研 BT / PT / Magnet 下载服务的可行性、架构、模块、接口、落地计划与风险。
如果公司最优先考虑商用 License 可控、品牌长期技术资产、下载服务可深度定制,推荐采用:
text自研 Download Orchestrator + 自研 bt-engine 服务 + libtorrent
其中:
libtorrent 只作为底层 BitTorrent 协议库;bt-engine 负责进程生命周期、任务状态机、持久化、PT 安全、Tracker 管理、文件选择、做种策略、诊断日志;download-orchestrator 保持统一任务模型,对 Web / App / NAS 本地 UI 暴露稳定 API;aria2 或自研 http-engine / libcurl 负责,不建议强行用 BT 服务覆盖。| 维度 | 结论 |
|---|---|
| 商用 License | 优于 qBittorrent 路线 |
| 首版开发成本 | 明显高于 qBittorrent 路线 |
| 长期可控性 | 最优 |
| PT 安全策略 | 可做到最强约束 |
| 资源占用 | 可控,但取决于实现质量 |
| 适合 615 快速上线 | 不建议作为唯一首发路径 |
| 适合 730 / V2 平台化 | 推荐 |
一句话结论:
libtorrent + 自研 BT 服务是长期最优路线,但不是最快路线。615 若必须快速上线,仍可先用 qBittorrent-nox;若法务不接受 GPL 或品牌必须完全掌控下载内核,则应启动本方案。
支持 NAS 下载器中的 BT / PT / Magnet 核心能力:
.torrent;magnet:?;libtorrent 是 C++ BitTorrent 实现,官方定位是 feature complete,强调效率、可扩展性,并支持嵌入式设备与桌面环境。
官方能力覆盖包括:
对 NAS 商用产品而言,libtorrent 的关键优势是:
textWeb / App / NAS Local UI │ ▼ Download BFF / API Gateway │ ▼ Download Orchestrator(Go,统一任务编排层) ├─ Task Service ├─ Protocol Router ├─ PT Safety Guard ├─ Conflict Resolver ├─ Notification Service ├─ Path Permission Service ├─ Event Bus / WebSocket Push └─ Engine Adapter │ ├─ BT Adapter │ │ │ ▼ │ bt-engine(C++,自研 BT 服务) │ ├─ API Server:gRPC / REST │ ├─ Libtorrent Session Manager │ ├─ Torrent Task Manager │ ├─ Magnet Metadata Manager │ ├─ Tracker Manager │ ├─ File Priority Manager │ ├─ Seeding Policy Manager │ ├─ Resume Data Manager │ ├─ Alert Event Loop │ ├─ Metrics / Diagnostics │ └─ Storage Adapter │ │ │ ▼ │ libtorrent │ ├─ HTTP Adapter → aria2 / http-engine └─ Share Adapter → 品牌分享转存 / 下载降级 Persistent Store ├─ SQLite:统一任务库 ├─ bt-engine metadata:resume data / session state / torrent metadata └─ operation logs / diagnostic snapshots
不建议将 libtorrent 直接嵌入 Go Orchestrator。推荐单独做一个 C++ bt-engine daemon。
原因:
libtorrent 做 ABI / 依赖管理;建议提供 gRPC 为主、REST 为辅:
| API | 说明 |
|---|---|
| AddTorrent | 添加 .torrent 文件 |
| AddMagnet | 添加 Magnet 链接 |
| GetTask | 获取任务详情 |
| ListTasks | 获取任务列表 |
| PauseTask | 暂停 |
| ResumeTask | 恢复 |
| RemoveTask | 删除任务,可选删除文件 |
| SetFilePriorities | 设置文件选择/优先级 |
| GetFiles | 获取文件树与进度 |
| GetTrackers | 获取 Tracker 列表与状态 |
| AddTracker | 添加 Tracker |
| ReplaceTrackers | 替换 Tracker |
| Reannounce | 重新汇报 Tracker |
| GetPeers | 获取 Peer 列表 |
| SetSpeedLimit | 设置限速 |
| SetSeedPolicy | 设置做种规则 |
| ForceRecheck | 强制校验 |
| MoveStorage | 移动存储目录 |
| SubscribeEvents | 订阅事件流 |
| ExportDiagnostics | 导出诊断包 |
负责创建和管理 lt::session。
settings_pack;yamlbt_session:
listen_port_range: [45000, 45999]
enable_dht: true
enable_pex: true
enable_lsd: false
enable_upnp: true
enable_natpmp: true
max_active_downloads: 20
max_active_seeds: 20
max_connections: 500
max_uploads: 80
download_rate_limit: 0
upload_rate_limit: 0
disk_cache_size_mb: 64
alert_level: standard
低配机型建议:
yamlbt_session:
max_active_downloads: 5
max_active_seeds: 10
max_connections: 120
max_uploads: 30
disk_cache_size_mb: 16
负责维护自研任务模型与 libtorrent::torrent_handle 的映射。
| 字段 | 说明 |
|---|---|
| task_id | 自研任务 ID,稳定对外 |
| info_hash_v1 | BT v1 infohash |
| info_hash_v2 | BT v2 infohash |
| lt_handle_id | libtorrent handle 映射,仅内部使用 |
| source_kind | torrent_file / magnet |
| save_path | 目标路径 |
| status | 自研统一状态 |
| resume_data_path | fast resume 数据路径 |
| torrent_metadata_path | .torrent 或 magnet 元数据路径 |
| policy_snapshot | PT / 做种 / 限速策略快照 |
| 统一状态 | libtorrent 参考状态 / 事件 | 说明 |
|---|---|---|
| waiting | queued / auto-managed waiting | 等待队列 |
| metadata_fetching | magnet metadata not ready | Magnet 元数据获取中 |
| checking | checking_files | 校验中 |
| downloading | downloading | 下载中 |
| seeding | seeding / finished | 做种中 |
| paused | paused flag | 暂停 |
| completed | download complete and seed disabled/finished | 完成 |
| failed | torrent_status::error / torrent_error_alert | 失败 |
| moving | move_storage in progress | 移动目录 |
| removed | remove_torrent completed | 已删除 |
注意:前端不应直接暴露 libtorrent 的复杂状态,应由 bt-engine 输出产品化状态和可读错误。
Magnet 任务分为两个阶段:
status=metadata_fetching;.torrent metadata;| 阶段 | 超时 | 处理 |
|---|---|---|
| Magnet 初始连接 | 60 秒 | 提示网络/资源热度不足 |
| Metadata 获取 | 10 分钟 | 任务保持等待,可手动重试 |
| 无 Peer | 15 分钟 | 提示无可用 Peer |
libtorrent 支持文件级优先级设置,适合实现“选择部分文件下载”。
负责 Tracker 列表、状态、编辑、reannounce、scrape。
这是自研路线相比 qB 路线的关键优势,应作为独立模块实现。
.torrent 中 info.private=1;| 策略 | private torrent | public torrent |
|---|---|---|
| DHT | 禁用 | 可配置 |
| PEX | 禁用 | 可配置 |
| LSD | 禁用 | 可配置 |
| 公共 Tracker 注入 | 禁止 | 可配置 |
| 自动上传 | 遵循 PT 做种策略 | 遵循全局策略 |
| Peer 来源审计 | 开启 | 可选 |
| 策略快照 | 必须保存 | 建议保存 |
每个任务创建时保存:
json{
"private": true,
"dht": false,
"pex": false,
"lsd": false,
"allow_public_tracker": false,
"seed_ratio_limit": 2.0,
"seed_time_limit_min": 4320,
"created_at": "2026-04-28T14:42:44+08:00"
}
BT 下载恢复是自研服务成败关键。libtorrent 支持 fast resume,但需要上层正确保存和恢复。
textbt-engine 启动 │ ├─ 读取 session state ├─ 读取任务表 ├─ 按任务加载 resume data ├─ 校验 save_path 是否存在 ├─ 校验 torrent metadata 是否存在 ├─ async_add_torrent ├─ 建立 task_id -> torrent_handle 映射 └─ 对账:DB 状态、文件状态、libtorrent 状态
| 异常 | 处理 |
|---|---|
| resume data 缺失 | 重新校验文件 |
| 目标目录不存在 | 任务进入 failed/path_missing |
| 文件被用户删除 | 任务进入 checking 或 failed |
| metadata 缺失 | Magnet 重新获取,torrent 文件任务失败 |
| infohash 冲突 | 走重复任务处理 |
建议仍由 Orchestrator 维护统一任务主库,bt-engine 维护 BT 专属运行数据。
| 字段 | 类型 | 说明 |
|---|---|---|
| task_id | TEXT PK | 统一任务 ID |
| engine_type | TEXT | bt / http / share |
| source_kind | TEXT | torrent_file / magnet |
| source_uri | TEXT | 原始来源,敏感信息脱敏 |
| normalized_source | TEXT | 标准化来源 |
| duplicate_key | TEXT | infohash 或 magnet hash |
| name | TEXT | 任务名称 |
| save_path | TEXT | 保存目录 |
| status | TEXT | 统一状态 |
| progress | INTEGER | 0-10000 |
| total_size | INTEGER | 总大小 |
| downloaded_size | INTEGER | 已下载 |
| uploaded_size | INTEGER | 已上传 |
| download_speed | INTEGER | 下载速度 |
| upload_speed | INTEGER | 上传速度 |
| error_code | TEXT | 标准错误码 |
| error_message | TEXT | 可读错误 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
| completed_at | DATETIME | 完成时间 |
| 字段 | 类型 | 说明 |
|---|---|---|
| task_id | TEXT PK | 任务 ID |
| info_hash_v1 | TEXT | v1 infohash |
| info_hash_v2 | TEXT | v2 infohash |
| private | BOOLEAN | 是否 private torrent |
| metadata_ready | BOOLEAN | 元数据是否已获取 |
| torrent_metadata_path | TEXT | metadata 文件路径 |
| resume_data_path | TEXT | fast resume 路径 |
| seed_ratio_limit | REAL | 分享率限制 |
| seed_time_limit | INTEGER | 做种时长限制 |
| dht_enabled | BOOLEAN | DHT 实际策略 |
| pex_enabled | BOOLEAN | PEX 实际策略 |
| lsd_enabled | BOOLEAN | LSD 实际策略 |
| policy_snapshot | TEXT | JSON 策略快照 |
| 字段 | 类型 | 说明 |
|---|---|---|
| task_id | TEXT | 任务 ID |
| file_index | INTEGER | 文件序号 |
| path | TEXT | 文件路径 |
| size | INTEGER | 文件大小 |
| priority | INTEGER | 下载优先级 |
| progress | INTEGER | 文件进度 |
| completed_size | INTEGER | 已完成大小 |
| 字段 | 类型 | 说明 |
|---|---|---|
| task_id | TEXT | 任务 ID |
| tracker_url | TEXT | Tracker URL |
| tier | INTEGER | tier |
| status | TEXT | working / error / updating |
| last_announce | DATETIME | 最近汇报 |
| next_announce | DATETIME | 下次汇报 |
| message | TEXT | 错误或状态消息 |
jsonPOST /bt/tasks:torrent
{
"task_id": "dl_xxx",
"torrent_file_path": "/data/tmp/upload/xxx.torrent",
"save_path": "/data/downloads",
"file_priorities": [1, 0, 1],
"pt_policy": {
"force_private_mode": true,
"allow_public_tracker": false
}
}
返回:
json{
"task_id": "dl_xxx",
"info_hash_v1": "...",
"name": "Ubuntu ISO",
"private": false,
"status": "waiting"
}
jsonPOST /bt/tasks:magnet
{
"task_id": "dl_xxx",
"magnet_uri": "magnet:?xt=urn:btih:...",
"save_path": "/data/downloads"
}
返回:
json{
"task_id": "dl_xxx",
"status": "metadata_fetching",
"metadata_ready": false
}
jsonGET /bt/events?task_id=dl_xxx
事件:
json{
"event_id": "evt_xxx",
"task_id": "dl_xxx",
"type": "task.status_changed",
"status": "downloading",
"progress": 1520,
"download_speed": 1048576,
"upload_speed": 204800,
"occurred_at": "2026-04-28T14:42:44+08:00"
}
libtorrent 通过 alert 机制向客户端程序报告状态、错误和事件。bt-engine 应将 alert 转换为产品事件。
| 类别 | 示例 |
|---|---|
| task | added / removed / paused / resumed / finished / failed |
| metadata | metadata_received / metadata_timeout |
| file | file_priority_changed / file_error |
| tracker | announce_ok / announce_error / tracker_list_changed |
| peer | peer_connected / peer_disconnected,可采样 |
| storage | disk_full / permission_denied / move_completed |
| session | listen_failed / portmap_error / dht_state_changed |
| metrics | session_stats / speed_update |
| 错误码 | 说明 | 用户提示 |
|---|---|---|
| BT_INVALID_TORRENT | torrent 文件无效 | 种子文件损坏或格式不支持 |
| BT_DUPLICATE_TASK | 重复任务 | 该资源已在下载列表中 |
| BT_METADATA_TIMEOUT | Magnet 元数据超时 | 暂未找到可用节点,可稍后重试 |
| BT_NO_PEERS | 无可用 Peer | 当前资源热度较低或网络受限 |
| BT_TRACKER_ERROR | Tracker 错误 | Tracker 无响应或返回错误 |
| BT_PT_POLICY_BLOCKED | PT 策略拦截 | PT 安全模式禁止该操作 |
| BT_PATH_DENIED | 路径无权限 | 当前账号无权写入目标目录 |
| BT_DISK_FULL | 磁盘空间不足 | 请释放空间或更换保存目录 |
| BT_FILE_MISSING | 文件缺失 | 文件可能被移动或删除 |
| BT_ENGINE_CRASHED | 引擎异常退出 | 下载服务已重启,请检查诊断日志 |
../ 路径穿越;| 模块 | 技术 |
|---|---|
| bt-engine | C++20 / C++17 |
| BT 协议库 | libtorrent 2.x |
| RPC | gRPC + Protobuf,辅以 REST |
| 本地存储 | SQLite / 文件型 resume data |
| 构建 | CMake + Conan / vcpkg / Yocto recipe |
| 日志 | spdlog / 自研结构化日志 |
| 指标 | Prometheus text endpoint 或本地 metrics API |
| 上层编排 | Go |
NAS 常见架构:
textnas-downloader/ ├─ bin/ │ ├─ download-orchestrator │ └─ bt-engine ├─ lib/ │ ├─ libtorrent.so │ ├─ libboost_*.so │ └─ libssl.so / libcrypto.so,如采用随包依赖 ├─ config/ │ ├─ downloader.yaml │ └─ bt-engine.yaml ├─ data/ │ ├─ db.sqlite │ ├─ torrents/ │ ├─ resume/ │ └─ session/ └─ licenses/ ├─ libtorrent.LICENSE ├─ boost.LICENSE ├─ openssl.LICENSE └─ third_party_notices.md
| 项目 | 默认值 | 说明 |
|---|---|---|
| 活跃下载 | 20 | 与 PRD 对齐 |
| 历史任务 | 200 | 与 PRD 对齐 |
| 最大连接数 | 500 | 中高配机型 |
| 低配最大连接数 | 120 | 低配机型 |
| 磁盘缓存 | 64MB | 中高配 |
| 低配磁盘缓存 | 16MB | 低配 |
| 状态推送频率 | 1s | 前端体验与资源平衡 |
| resume 保存间隔 | 30s | 防止异常断电损失 |
如果 615 先采用 qB,V2 再切换到自研 bt-engine,可按以下方式迁移:
| 数据 | 迁移方式 |
|---|---|
| torrent 文件 | 从 qB profile 或 Orchestrator 备份目录导入 |
| save_path | 复用统一任务表 |
| infohash | 复用 duplicate_key |
| 文件选择 | 从 qB API 导出后映射为 file priorities |
| 做种规则 | 映射到 bt-engine seed policy |
| 已下载文件 | 通过 libtorrent 校验或 resume data 恢复 |
text暂停 qB 任务 │ 导出任务元数据 │ 停止 qB 引擎 │ bt-engine 导入 torrent + save_path + policy │ 加载或重新生成 resume data │ 必要时 force recheck │ 恢复任务状态
注意:跨客户端 resume data 不一定兼容,应准备重新校验文件的兜底路径。
目标:完成基本可用 BT / Magnet 下载内核。
范围:
目标:达到产品可测版本。
范围:
目标:达到商用发布质量。
范围:
| 风险 | 描述 | 应对 |
|---|---|---|
| 开发周期长 | 自研服务需要补齐 qB 已有产品能力 | 分 MVP / Beta / GA,先实现核心链路 |
| C++ 稳定性风险 | 崩溃、内存、线程问题 | 独立进程、崩溃拉起、ASAN/TSAN、长稳测试 |
| libtorrent API 学习成本 | 需要理解 session、alert、resume、settings | 建立内部封装层,不让业务直接调用 libtorrent |
| PT 兼容性风险 | PT 站点对客户端行为敏感 | 早期引入 PT 用户与站点测试用例 |
| 恢复逻辑复杂 | resume data、文件状态、DB 状态需对账 | 启动 reconcile 作为核心模块 |
| 资源占用失控 | 多任务、多 Peer 对低配 NAS 压力大 | 机型 profile、连接数限制、缓存限制 |
| 诊断能力不足 | 自研初期不如 qB 可解释 | 事件体系、诊断包、错误码先行 |
| HTTP 下载仍需补齐 | libtorrent 不替代直链下载 | HTTP/HTTPS 保持 aria2 或 libcurl 路线 |
| 维度 | qBittorrent-nox | libtorrent + 自研 BT 服务 |
|---|---|---|
| 首版速度 | 快 | 慢 |
| License 风险 | GPL 高合规成本 | BSD 商业友好 |
| UI 可控性 | 中 | 高 |
| 状态模型可控 | 中 | 高 |
| PT 安全强约束 | 中高,需要外层兜底 | 高,可内建策略 |
| Tracker 诊断 | 成熟 | 需自研 |
| 文件选择 | 成熟 | 需封装 |
| 重启恢复 | 成熟 | 需重点实现 |
| 低配优化 | 中 | 可深度优化 |
| 长期品牌资产 | 中 | 高 |
| 研发风险 | 低中 | 高 |
仍建议:
textqBittorrent-nox + Orchestrator
同时把 Orchestrator 的任务模型、API、状态机设计成与底层引擎解耦,为后续替换 bt-engine 留出空间。
建议直接启动:
textlibtorrent + 自研 bt-engine
但需要接受至少 3~5 个月的工程化打磨周期。
推荐路线:
text615:qB 快速落地 / 或 bt-engine MVP 730:bt-engine Beta V2:bt-engine 替代 qB,成为品牌原生下载内核
最终目标:
让品牌 NAS 下载器的核心资产从“调用第三方下载器”升级为“自有下载服务平台”。
本文作者:oyph
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!