前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >探索 libp2p:基本知识

探索 libp2p:基本知识

作者头像
tyrchen
发布2021-06-17 15:33:47
4.1K0
发布2021-06-17 15:33:47
举报
文章被收录于专栏:程序人生

自 napster 20 年前以来,p2p 的应用一直层出不穷,一开始主要集中在音视频的文件共享领域。早期的 bitTorrent,电驴,后来的pplive,迅雷,快播等,都是走内容分享的路子。在这里,p2p 主要充当的是点对点下载资源块的角色,至于播放体验的优化,是另一回事。在分光了一段时间后,互联网进入到高带宽 + 海量 CDN 时代,这类的 p2p 软件渐渐式微,越来越小众。原因很简单 —— 通过高速网络和遍布全球各地的 CDN 节点,流媒体音视频的播放体验已经非常优秀,普通用户又何必退而求其次使用体验一般,片源不稳定的 p2p 软件呢(除了特殊需求)?

p2p 的另一个战场是即时通讯。QQ / MSN / Skype 等虽然不能算作完全的 p2p 软件,但大量使用了 p2p 技术来提升通讯的效率,以及避免不必要的带宽消耗。比如 Alice 和 Bob 通过后台确认过对方的在线状态后,两者之间完全可以建立点对点连接,之后的通讯完全可以在两者之间完成,消息无需服务器进行一道转手。当然,这样「白嫖」用户的带宽是有代价的,用户间传输的数据很难被「监控」到(如果每个消息都要往服务器转发一份,那 p2p 也没有多大意义了),于是相关的服务也无法根据这些数据去做各种各样的深度学习和分析,进而更好地提升用(zhuan4)户(qian2)体(neng2)验(li4)。所以随着互联网厂商越来越不差钱,对 p2p 技术的渴求也没那么强烈了。

区块链技术爆红后,p2p 又逐渐走回主流技术界的视野。早期的区块链,最核心的技术是两个部分:p2p 和共识算法。人们都觉得 p2p 是已经解决了的问题,把目光更多投在了共识算法。所以尽管必不可少,相对于层出不穷的当红炸子鸡 —— 共识算法,p2p 技术就像一个被冷落在角落里的老黄牛,只是在需要的时候,就被拉出来抽两鞭子。

到了区块链走向更广阔的领域,尤其是 IPFS 兴起后,大家才渐渐意识到,之前的项目,p2p 和共识算法绑得太紧,为每一种解决方案都设(chao1)计(xi2)一套 p2p,不符合 DRY 的伟大精神,于是在 IPFS 项目的牵头下,libp2p 被定义出来 —— 顾名思义,这是用来解决 p2p 网络层核心问题的一套库。有了 libp2p,开发者要实现一个基于 p2p 的解决方案,变得无比简单:即便是一个对 p2p 核心技术没有深入了解的人,也可以很快开发出一个 p2p 系统。可以这么说:libp2p 未来在 p2p 领域的历史地位,就像 webkit 在浏览器世界的历史地位一样。

在具体介绍 libp2p 之前,我们先看看 p2p 网络和我们熟悉的 client/server 网络的区别:

  • p2p 网络的每一个节点既是客户端,又是服务器
  • p2p 网络的每个节点,都(潜在)是数据的发起者和存储者(对比:c/s 网络中,server 拥有数据)
  • p2p 网络很不稳定,节点可能进进出出(对比:c/s 网络,服务器非常稳定,一般 SLA 都有几个9)
  • p2p 网络需要某种机制来实现节点的发现和查找(对比:c/s 网络,客户端知道服务器在哪,如何访问)
  • p2p 网络(往往)需要 NAT traversal / Hole punching 等技术来允许两个节点之间通讯。这是因为很多节点(比如说家庭网络)往往藏在运营商的 NAT 服务器之后。

(图片来源:Telecommunication systems and technology[1])

  • p2p 网络需要投入额外的精力来保证公平(反吸血)
  • p2p 网络需要更好的安全和验证机制。这是因为节点是对等的,保证数据的安全性比 c/s 网络难度更大。

libp2p 简介

libp2p 包含一系列协议的实现,这些协议共同作用,完成了:

  • p2p 网络的传输层(下图绿色):支持几乎所有的主流传输协议,甚至允许不同节点间使用不同的传输层,比如 native 节点间优先使用 QUIC,而 native 和 web 节点间使用 websocket。
  • 节点发现(黄色,注意这里 PKI 是指基于 PKI 的节点身份):一般本地网络可以使用 mDNS,大规模 p2p 网络一般使用 bootstrap 来连接初始节点,然后通过 gossip 获取更多节点信息,并通过 Kad DHT 来查找节点。
  • 节点路由(蓝色):主要使用 Kad DHT 通过多跳来路由到网络中任意一个节点
  • 内容路由(紫色):如果点对点发送消息,可以通过 Kad DHT,如果在网络中 flood,可以通过 floodsub 和 gossipsub 来对某个 topic 的内容进行广播。
  • NAT traversal(红色):包括主流的 hole punching 解决方案

(图片来源:A network framework for decentralized P2P application development [2])

对于开发者而言,相对于掌握这些协议的细节而言,更重要的掌握如何使用 libp2p 构造一个 p2p 网络,所以,我们需要掌握以下概念和它们的使用。

网络身份:Network identity

对于一个 p2p 网络,一个节点想让别人认识它并接受它的一个前提是它要有可以被识别的节点身份。这个就是 network identity。libp2p 使用公钥/私钥对来产生 network identity:私钥用于数据的签名,公钥作为 PeerId。一般来说,一个节点在初始化之后,应该产生一个配置文件,保存节点的公钥私钥,以便节点以后反复运行时能够使用相同的身份。

传输协议:Transport

前面我们提到,在 p2p 网络中,节点间传输协议的选择需要非常多样,这是因为网络中有可能运行着各种版本,甚至不同实现的节点,因而,支持一个范围广泛的传输协议供节点连接时协商,便变得非常必要。此外,p2p 网络需要额外的安全性,不仅仅是消息的加密,还有消息发送者的身份验证 —— 你可以将其类比成使能了 mutual auth 的 TLS:客户端验证服务器的证书来确保连接的是合法的服务器,而服务器同时也验证客户端的证书确保访问的是合法的客户端。

为了实现这一目的,libp2p 抽象出了 Transport 层,它负责传输协议的协商,包括使用什么样的传输协议,使用什么样的安全机制,以及如果做多路复用(stream multiplexing)。基本上,这对应了 ISO/OSI 模型的:传输层(比如用 TCP)和会话层(比如用 Noise + Yamux)。如果你使用过 websocket,那么你对一个 HTTP 连接 "upgrade" 成 websocket 并不陌生,libp2p 在这些层之间也是一层层 upgrade 的。我们看个例子:

代码语言:javascript
复制
let noise_keys = noise::Keypair::<noise::X25519Spec>::new()
  .into_authentic(&keypair)
  .unwrap();
let transport_layer = {
  let tcp = tcp::TcpConfig::new().nodelay(true);
  let dns_tcp = dns::DnsConfig::system(tcp).await?;
  let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone());
  dns_tcp.or_transport(ws_dns_tcp)
};
let transport = transport_layer
  .upgrade(Version::V1)
  .authenticate(NoiseConfig::xx(noise_keys).into_authenticated())
  .multiplex(YamuxConfig::default())
  .timeout(Duration::from_secs(20))
  .boxed();

这段代码并不难懂,非常简洁干练,没有 Rust 经验的人也能猜出来在干什么。但里面包含的信息量巨大:

  • 传输层使用 TCP 协议或者 websocket(优先 TCP 协议)。
  • 安全层使用 noise protocol,使用 XX 模式握手(双方都不知道对方的 static key)
  • Multiplex 使用 Yamux。如果你对 Yamux 不太了解,可以回想一下 HTTP/2 是如何做 multiplex 的, Yamux 的原理与之非常类似。

可以看到,短短几行代码,我们就构建了一个非常安全(noise protocol),非常高效(yamux),以及非常灵活(tcp / websocket)的传输协议。

网络行为:Network behaviour

如果说 Transport 定义了如何在网络中传输数据,那么 NetworkBehaviour 则定义了在网络中要传输什么样的数据,或者说,你的 p2p 协议本身。你只需要专注于数据本身而不必考虑最终数据是如何加密,使用什么协议发送出去。我觉得这个设计非常优雅,它清晰地像我们展示了什么是 Separation of Concerns。

libp2p 自带了一系列 Network behaviour —— 上图中大部分的协议,都通过 Network behaviour 实现,我举几个例子:

  • Ping:节点和其 peer 之间 keepalive,以及网络诊断的工具。
  • mDNS:本地节点发现协议。
  • floodsub:floodsub protocol 实现。它是 libp2p 几种 pubsub 方案之一。适用于小型网络中消息的广播。我会单开一篇讲 pubsub 的。
  • kad:Kademlia 协议的实现。

除了 libp2p 默认实现的一系列 Network behaviour 外,你也可以创建新的 Network behaviour,并且把你的协议和已有的 behaviour 组合在一起。

要实现你自己的 Network behaviour,你需要:

  • 实现 UpgradeInfo:这告诉 libp2p 你的协议的唯一标识符,比如:/ipfs/ping/1.0.0
  • 实现 InboundUpgradeOutboundUpgrade:这是协议输入输出数据的处理。
  • 实现 ProtocolsHandlerNetworkBehaviour:协议的主要处理流程。

Swarm

上文提到 Network 定义了如何发送数据,NetworkBehaviour 定义了什么时候发送什么样的数据,但我们还缺一个中间人,把 NetworkBehaviour 要发送的数据交给 Network 发送出去,并且把 Network 收到的数据交给 NetworkBehaviour 处理。这个中间人就是 Swarm

我们用一段代码看看 Swarm 是如何驱动 NetworkNetworkBehaviour 前进的:

代码语言:javascript
复制
let transport = ...; // 参见上文代码
let behaviour = Ping::new(PingConfig::new().with_keep_alive(true));
let mut swarm = Swarm::new(transport, behaviour, local_peer_id);
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
loop {
  let event = swarm.next().await?;
  println!("event: {:?}", event);
}

这里可以看到,Swarm 需要 NetworkNetworkBehaviour 才能创建。swarm 可以监听一个特殊的地址 —— 这里 /ip4/0.0.0.0/tcp/0 是一个 IPFS 定义的 multiaddr,可以很方便地表述多层协议的地址。之后,我们可以通过 swarm.next() 来驱动 Swarm 处理数据。一般而言,Swarm 获取到的数据,已经交给 NetworkBehaviour 处理了,只有未定义的数据,才会被收到上文中的流程进行进一步处理。

libp2p 可以用来做什么?

现在 libp2p 主要被用来构建狭义的区块链项目,比如 substrate,filecoin 等,我觉得有些暴殄天物。其实 libp2p 还可以有更广阔的天地,比如在社交软件,工具软件,通讯软件,甚至电子商务等领域找到自己的位置。接下来的几篇文章,我们会进一步讲解 libp2p,并使用 rust-libp2p[3] 构建一个有意思的小工具。

参考文档

[1] Telecommunication systems and technology: https://www.slideserve.com/myrrh/telecomunication-systems-and-technology-powerpoint-ppt-presentation

[2] A network framework for decentralized P2P application development: https://ipfs.io/ipfs/QmdzerM4fsnNGVf5jnogxu6QpXQa5rHDK87oHStC5xGCS4/

[3] rust-libp2p: https://crates.io/crates/libp2p

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • libp2p 简介
    • 网络身份:Network identity
      • 传输协议:Transport
        • 网络行为:Network behaviour
          • Swarm
          • libp2p 可以用来做什么?
          • 参考文档
          相关产品与服务
          区块链
          云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档