共计 4284 个字符,预计需要花费 11 分钟才能阅读完成。
文 / 龙蜥社区开发者
Dragonfly2 简介
Dragonfly 作为龙蜥社区的镜像减速规范解决方案,是一款基于 P2P 的智能镜像和文件散发工具。它旨在进步大规模文件传输的效率和速率,最大限度地利用网络带宽。在利用散发、缓存散发、日志散发和镜像散发等畛域被大规模应用。
现阶段 Dragonfly 基于 Dragonfly1.x 演进而来,在放弃 Dragonfly1.x 原有外围能力的根底上,Dragonfly 在零碎架构设计、产品能力、应用场景等几大方向上进行了全面降级。
Dragonfly 架构次要分为三局部 Manager、Scheduler、Seed Peer 以及 Peer 各司其职组成 P2P 下载网络,Dfdaemon 能够作为 Seed Peer 和 Peer。具体内容能够参考架构文档,上面是各模块性能:
- Manager:保护各 P2P 集群的关联关系、动静配置管理、用户态以及权限治理等性能。也蕴含了前端控制台,不便用户进行可视化操作集群。
- Scheduler:为下载节点抉择最优下载父节点。异常情况管制 Dfdaemon 回源。
- Seed Peer:Dfdaemon 开启 Seed Peer 模式能够作为 P2P 集群中回源下载节点, 也就是整个集群中下载的根节点。
- Peer:通过 Dfdaemon 部署,基于 C/S 架构提供 dfget 命令行下载工具,以及 dfget daemon 运行守护过程,提供工作下载能力。
更多详细信息能够参考 Dragonfly 官网。
问题背景
尽管 Dragonfly 的定位是一个基于 P2P 的文件散发零碎,然而散发的文件必须是可能从网络上下载的文件,无论是 rpm 包还是容器镜像内容,最终都是有一个地址源的,用户能够通过 dfget 命令向 dfdaemon 发动下载申请,而后 Dragonfly P2P 零碎负责下载,如果数据不在其余 Peer 上,那么 Peer 或者 SeedPeer 本人会回源,间接从源下载数据,而后返回给用户。
然而有些场景咱们须要散发的数据是某个节点上生成的,不存在一个远端的源地址,这个时候 Dragonfly 就无奈散发这种数据了。所以咱们心愿 Dragonfly 可能减少对这种场景的反对,其实相当于把 Dragonfly 当作了一个分布式的基于 P2P 的缓存和任意数据散发零碎。
扩大 Dragonfly2
所以咱们构想中的 Dragonfly 缓存零碎架构是这样的:
- 每个计算节点上(比方神龙)部署一个 dfdaemon,作为一个 peer 退出 P2P 网络。
- 承受来自本节点的申请
- 为其余 peer 提供上传服务
- 每个 peer 只负责管理本人本地的 cache 数据,不负责回源,回源由业务过程负责
- 每个集群能够部署一个到多个基于 ECS 的 scheduler 节点。
- 记录文件 P2P 网络的文件信息
- 下载调度
- 多 scheduler 节点解决单点故障问题
- 每个 cache 零碎中的文件都会通过 ringhash 映射到某个 scheduler 上
- 一个或者多个 Manager 作为集群管理者。
- 负责向 scheduler 和 peer 节点发送动静配置
- 收集 metrics 等信息
接口设计
dfdaemon 接口
原来的 daemon 接口:
pkg/rpc/dfdaemon/dfdaemon.proto
// Daemon Client RPC Service
service Daemon{
// Trigger client to download file
rpc Download(DownRequest) returns(stream DownResult);
// Get piece tasks from other peers
rpc GetPieceTasks(base.PieceTaskRequest)returns(base.PiecePacket);
// Check daemon health
rpc CheckHealth(google.protobuf.Empty)returns(google.protobuf.Empty);
}
新增 4 个接口:
service Daemon {
// Check if given task exists in P2P cache system
rpc StatTask(StatTaskRequest) returns(google.protobuf.Empty);
// Import the given file into P2P cache system
rpc ImportTask(ImportTaskRequest) returns(google.protobuf.Empty);
// Export or download file from P2P cache system
rpc ExportTask(ExportTaskRequest) returns(google.protobuf.Empty);
// Delete file from P2P cache system
rpc DeleteTask(DeleteTaskRequest) returns(google.protobuf.Empty);
}
scheduler 接口
原来的 scheduler 接口:
// Scheduler System RPC Service
service Scheduler{
// RegisterPeerTask registers a peer into one task.
rpc RegisterPeerTask(PeerTaskRequest)returns(RegisterResult);
// ReportPieceResult reports piece results and receives peer packets.
// when migrating to another scheduler,
// it will send the last piece result to the new scheduler.
rpc ReportPieceResult(stream PieceResult)returns(stream PeerPacket);
// ReportPeerResult reports downloading result for the peer task.
rpc ReportPeerResult(PeerResult)returns(google.protobuf.Empty);
// LeaveTask makes the peer leaving from scheduling overlay for the task.
rpc LeaveTask(PeerTarget)returns(google.protobuf.Empty);
}
新增 2 个接口,下载复用之前的 RegisterPeerTask() 接口,删除复用之前的 LeaveTask() 接口:
// Scheduler System RPC Service
service Scheduler{
// Checks if any peer has the given task
rpc StatTask(StatTaskRequest)returns(Task);
// A peer announces that it has the announced task to other peers
rpc AnnounceTask(AnnounceTaskRequest) returns(google.protobuf.Empty);
}
接口申请时序图
StatTask
ImportTask
ExportTask
DeleteTask
代码实现
目前代码曾经合并,能够在 Dragonfly v2.0.3 版本中应用。
upstream PR:https://github.com/dragonflyo…
应用办法
除了减少新的接口之外,咱们还减少了一个叫 dfcache 的命令,用于测试,应用办法如下:
- add a file into cache system
dfcache import --cid sha256:xxxxxx --tag testtag /path/to/file
- check if a file exists in cache system
dfcache stat --cid testid --local # only check local cache
dfcache stat --cid testid # check other peers as well
- export/download a file from cache system
dfcache export --cid testid -O /path/to/output
- delete a file from cache system, both local cache and P2P network
dfcache delete -i testid -t testtag
测试及成果
测试方法
通过新增的 dfcache 命令,在一个节点上向 P2P cache 零碎中增加不同大小的文件,而后在另外一个节点上针对这个文件做查问、下载、删除等操作。例如:
# dd if=/dev/urandom of=testfile bs=1M count =1024
# dfcache stat -i testid # 查看一个不存在的文件
# dfcache import -i testid testfile
# on another node
# dfcache stat -i testid
# dfcache export -i testid testfile.export
测试成果
两台 ecs,网络走 vpc,带宽 3.45 Gbits/s (约 440MiB/s):
下载的 ecs 磁盘带宽 180MiB/s 左右:
操作 | 工夫(ms) | 备注 |
---|---|---|
stat (本地存在 cache) | 0.07 | cache 曾经在本地,不须要查问 scheduler |
stat(本地不存在,peer 存在) | 0.6 | cache 不在本地,然而 scheduler 晓得其余 peer 有 |
stat(不存在) | 1 | cache 不在 P2P cache 零碎里 |
delete | 1 | / |
import 1G file | 2542 | 大部分工夫是本地做分片计算 hash 等 |
announce | 1 | 向 scheduler 申明本地有某个 cache |
export 4k file | 3.37 | / |
export 4m file | 14 | 默认依照 4M 分片,所以 4M 以内文件都是一片 |
export 128m file | 170 | 有些稳定,150ms 到 190ms 都有 |
export 1G file | 2150 | 默认 200M 限速 |
相干浏览链接:
1、Dragonfly1.x 链接地址:
https://github.com/dragonflyo…
2、Dragonfly 架构文档:
https://d7y.io/zh/docs/concep…
3、Dragonfly 官网链接:
https://d7y.io/
4、龙蜥云原生 SIG 地址链接:
https://openanolis.cn/sig/clo…
—— 完 ——