如何使用libp2p构建IPFS搜寻器

2020-06-20 15:36:37

当您拥有一个由几个实体拥有的去中心化系统,而您仅在网络的一小部分中运营时,如何监控其总体状态并确保系统正常运行

0620-1-0.png


  我已经在我的出版物中提到了我的财务仪表板副项目,对我来说,学习新事物的最有效方法是将自己投入到“宠物项目”中,这激励着我,使我不要半途而废。我强迫自己使用我想学习的新技术来开发该项目,因此在此过程中,我最终得到了一个全新的附带项目和一大堆新技能。财务仪表板是学习GraphQL和ReactJS的借口(说实话,从那时起,我就越来越积极地使用ReactJS,因此它得到了回报)。今天,我将分享我的“借口”,以提高我在libp2p和Go中的并发编程方面的技能(使用goroutine,waitgroup,locks和通常的方法):libp2p中内置的IPFS搜寻器。

  设置上下文

  到目前为止,我一直对p2p,分布式技术及其对互联网和整个社会的影响(而不是对未来的影响)着迷,这已经不是什么秘密了。有一天,当我意识到以下几点时,我在考虑部署p2p网络以协调生产数据中心联合会中的所有设备将如何工作:高度监控数据中心基础架构以检测与基线操作之间的任何最小偏差系统的。在传统的(集中式)基础架构中,分析是“简单的”,您可以拥有一个中央监控系统来收集基础架构中的每个指标,因为您是该指标的所有者和管理者。但是,当您拥有一个由几个实体拥有的去中心化系统,而您仅在网络的一小部分中运营时,如何监控其总体状态并确保系统正常运行?您仅保留网络的本地视图,并且想要了解整个网络的状态。在分布式,非结构化和自组织网络中进行监视和分析非常困难,尤其是在没有集中式基础结构来协调所有内容的情况下。因此,以加深并发和libp2p的借口(并由某些外部情况触发),我决定从小规模开始研究此问题。

0620-1-1.jpeg

  计数节点

  我选择从小但有野心开始。我想在一个真实的网络中探索这个问题,因此在我的本地计算机上建立一个8节点的网络来进行实验可能会很容易。因此,我决定要尝试从最大的p2p网络之一IPFS收集一些指标。具体来说,我将尝试监视网络中活动节点的总数以及其每日用户流失(一天中剩余节点数的比率)。

  对该问题进行的首次搜索显示了一些试图映射IPFS网络的学术论文的结果,以及libp2p网络爬虫的现有实现。因此其他人以前已经解决了这个问题。现在轮到我看看是否能够按照他们的步骤进行。

  有了足够的前言,我在笔记本上放了一张空白页,开始涂鸦自己的工具的潜在设计,最后为爬虫使用了以下架构:

  爬虫将通过三个不同的过程来遵循:爬虫过程(负责随机遍历DHT以搜索连接的节点-稍后对此进行详细介绍);生动的过程(负责检查是否已经看到节点还在运行);和报告过程(输出分析的当前状态,没有幻想)。

  为了爬网,我选择了一种非常非结构化的方案,即路由DHT的随机游走。抓取者会选择一个随机的节点ID,它会问网络“嘿,伙计们!给我一个与这个人最近的x个节点的列表”。然后,搜寻器将尝试与这些节点建立临时连接,以查看它们是否正常运行,以及是否将它们添加到网络中的活动节点列表中。通过这种方式,我们“随机遍历”网络以搜索活动节点。我可能使用了更加结构化的搜索,而不是随机选择一个新的节点ID,而是从k个桶中取出了所有对等节点,看看它们是否还处于活动状态,请求从k个桶到这些节点的对等节点列表,等等。递归地我的第一个实现遵循此方案。它可能最终变得更准确,但感觉比随机方法要慢。

  随机游走搜索了网络中的活动节点,但是我需要一种方法来检查这些节点是否仍处于活动状态或是否已离开网络。这是活跃过程的目的。此过程非常简单,而搜寻器搜索并更新活动节点列表时,此过程将循环遍历活动节点列表,并尝试与它们进行短暂连接,以查看它们是否仍处于活动状态。

  最后,报告过程仅采用存储的指标并定期显示它们。最初,我从可见节点收集的唯一度量标准是:上次看到节点的时间,以及是否在NAT之后。最后一个指标对于检查节点是否仍处于活动状态非常重要,因为即使临时连接失败,也可能是因为他在NAT之后,而不是因为他不在。因此,这就是为什么我们需要事先知道该节点位于NAT之后才能知道如何识别离开节点的原因。

0620-1-2.png

  看看代码!

  如果您只是好奇地看到该工具正在工作,则可以克隆该存储库,编译代码并运行它以查看魔术的发生:

  $ git clone https://github.com/adlrocha/go-libp2p-crawler

  $ go build

  $ ./go-libp2p-crawler -crawler=-liveliness=-verbose

  使用-crawler和-liveliness标志,可以分别选择专用于搜索新节点并检查节点是否仍处于活动状态的goroutine数量。

  对于那些想进一步了解我如何实现此工具的人,让我逐步介绍它的实现:

  系统在启动时要做的第一件事就是为每个要启动的搜寻器进程启动一个新的libp2p节点。这些节点然后连接到IPFS引导节点。引导节点后,它会开始搜索新节点。

  节点只能运行搜寻器进程,也可以根据为执行选择的搜寻器数量和活动性而同时运行搜寻器和活动性进程(请记住,设计搜寻器节点是为了使它们不能仅执行活动性检查,因此您的活泼工人永远不会比履带工人多。这是一种设计选择,可以轻松进行修改)。

  为了存储有关看到的节点,网络中的活动节点等的数据。我选择使用LevelDB。该系统在同一个数据存储中编写了多个goroutine,因此使用LevelDB是避免数据争用的非常简单的方法。经过一些初步的测试之后,我还选择使用锁来显式删除任何潜在的数据争用。

  报告过程仅显示有关今天看到和离开的节点数量,网络中活动节点的数量(至少是我们的观点)以及每日用户流失的信息。我还存储有关何时最后一次看到该节点以及该节点是否位于NAT之后的信息,因此我还可以计算NAT后面的节点比率,或对节点保持连接的平均时间的粗略估计。我还考虑过探索其他指标,例如与网络其余部分的平均RTT,在可见节点中的可用传输以及有关网络的其他有趣指标,但我目前选择了简单指标(爬网很困难足以值得努力)。


0620-1-3.png

  该工具的示例执行


  长时间执行该工具后,我开始体验离开网络的总节点数在达到约500个时如何重新启动。这个错误真的让我感到困惑,我对计数器和所有goroutines分别进行了几次隔离测试,直到选择不使用LevelDB的替代实现(您可以在repo的分支feature / noLevelDB中找到)为止。通过这种替代实施,问题得以解决,您知道发生了什么事?我用来存储数据的结构以及在活泼过程中我不得不使用迭代器遍历整个数据的事实使同步陷入混乱。我在考虑其他节点并在不应该的情况下重新启动计数器。我选择使用LevelDB的另一个原因是要保留看到的节点列表,但是由于该错误,并且考虑到我可以使用其他不太复杂的方案来保留数据,因此我没有花更多的时间来尝试修复该问题。这个帖子的错误(尽管有时间我肯定会做的)。

  包起来!

  老实说,我一生都在玩这个项目。我在本新闻通讯中已经说过几次了,但是让我再做一次,希望我可以把它做为我的全职工作!如果您测试该工具,我很想知道您的反馈意见。根据您的反馈,扩大项目并积极维护它可能是有意义的。同时,在更深入地研究libp2p之后,我想出了更多的想法去探索,并且我已经开始了一个新的项目以学习新知识。下一个结合了WASM,libp2p和Rust。请继续关注以查看结果(取决于接下来几周的可用性,我可能会在一个月左右的时间内发布结果)。再见!


最新推荐