要完成有用的工作,P2P 应用程序中的对等点必须能够彼此发现对方和与对方交互。软件开发人员 Todd Sundsted 在本文中继续研究 P2P 计算,并描述了几种完成这一任务(称为发现(discovery))的方法,以及每种方法的优势和弱点。
对等应用程序是一种大规模但又是细粒度的应用程序。每个对等点都可以进入或退出 — 每个对等点都关注于自己的任务。在他们短暂的活动期间,尝试完成布置给它们的任务。这些任务中的大多数都要涉及与其它对等点交互。
治理体系结构(对等点在这种体系结构下运作)必须为构成完整 P2P 应用程序的对等点提供许多必要的服务。在我们的 P2P 计算“旅程”中,已经讲述了通信和安全性服务(请参阅参考资料);现在是时候来研究对等点发现服务了。
对等点发现服务使 P2P 应用程序中的对等点能够彼此定位以便相互之间可以交互。实现对等点发现服务有多种方法。我们先从告诉对等点彼此之间的存在这种最简单的方法开始:显式点到点配置。
显式点到点配置
显式点到点配置与其说是一种真正的发现机制,还不如说是一种用来避免实现发现的机制。每个存在的对等点都知道“居住”在其 P2P 世界中的其它对等点。
术语点到点(point-to-point)意味着,在 P2P 应用程序中的每个对等点都知道需要不断与之交互的每个对等点,并与之相连。这种连线不必将每个对等点都连起来 — 将每个对等点和其他各个对等点彼此相连,是不太可能的 — 但是,不这样做(无论是有意与否)将会使某些对等点产生网络盲点。
我为本系列文章所构建的简单的 P2P 应用程序(请参阅参考资料)使用显式点到点配置。每个对等点必须预先配置其它所有对等点的地址。假如您已经下载并使用了那些代码,则您无疑已经经历了忍受这一需求所带来的挫折 — 配置既单调乏味又轻易出错,更不用提一般的麻烦了。
一般而言,分布式应用程序中节点的显式点到点配置不能很好地扩展到具有较多节点的大型网络。那就是为什么分布式计算应用程序和技术总是(也有一些显著的例外)包含命名和定位功能。这也解释了为什么域名系统(DNS) — 一种分布式命名系统,最终取代了用于机器命名的主机文件(hosts file)机制。维护主机文件是单调乏味、轻易出错的,并且一般来说,很难在大型网络环境下运转。
但是,显式点到点配置并非一无是处。点到点寻址缺乏灵活性的特性也带来了一定程度的安全性。通过对网络中的每个对等点预先设置它所知道并且将要与之交互的对等点列表,使得网络在外部攻击面前表现得很稳固。
动态发现模型
与显式点到点配置方法的静态特性截然相反,目录服务和网络模型具有动态特性。这些模型通常能更好地符合 P2P 应用程序,它们倾向于该领域中动态的一边。
在下面几节中,我们将研究三种不同的机制,对等点通过这些机制动态地定位其它对等点和了解它自身所属的环境。
目录服务模型
在目录服务模型中,一台或多台有非凡用途的服务器为对等点提供目录服务。为了使可扩展性最大化,对应用程序进行了结构化设计,以便少量的目录就可以为数量众多的对等点服务。对等点向目录服务注册关于自身的信息(其名称、地址、资源和元数据),并通过根据目录服务器中信息的查询,使用目录服务来定位其它对等点。
图 1 说明了一个使用目录来向对等点提供位置和命名服务的 P2P 体系结构。目录本身可以是对等点(尽管是很庞大的对等点),或者可以只担当目录而不作它用。
图 1,目录服务模型
目录有两种类型。这两种类型因为其目录集中式治理的程度不同而有略微的差别。
P2P 领域中目录模型的最佳示例是 Napster 和与 Napster 几乎一模一样的 OpenNap。在 Napster 模型中,采用集中式治理目录。虽然,采用集中式治理的目录遭到“本质上是‘非 P2P’”的指责,并且事实上促使了 Napster 被弃用,但它确实提供了一个重要的优势:集中式治理使它轻易确保服务器硬件和配置能足以达到服务质量目标。
假如我们先暂时将 P2P 放一放,可以发现 DNS 是分散式目录的一个优秀示例。与因特网本身相似,DNS 设计为甚至在部分网络受到严重破坏的情况下仍能工作。DNS 目录采用层次化结构,根目录代表顶级域(譬如“com”),它将子域查询服务(如“etcee.com”这样的域)的任务委派到下一层次的 DNS 服务器。
在任意一种情况下,只有目录位置必须配置到每个对等点中,这对于点到点模型有重要优势。为加入到 P2P,对等点将自己注册到集中目录服务器。回忆上面的图。当对等点 A 希望与一个它不知道位置的对等点交互时,对等点 A 向目录服务器发送请求。然后,目录服务器向 A 返回那个对等点的位置。
网络模型
图 2 说明了另一种 P2P 应用程序。它由许多对等点组成,这些对等点在功能上很类似。没有专门的目录服务器。对等点必须使用它们所在的网络来定位其它对等点。
图 2,网络模型
正如名称所暗示的,网络模型 P2P 应用程序由一些(通常是动态的)对等点组成。没有一个对等点知道整个网络的结构或者组成网络的每个对等点的身份。相反,对等点只知道直接与它们通信的对等点 — 它们通过代理参与到大型网络中。
对等点必须合作完成任务。在许多环境中这种合作包括支持分布式查询、分布式消息传递,甚至包括认证和授权行为。因为涉及通信量的多少,象文件传输这样需要大流量的网络操作通常在对等点间直接发生 — 而不是通过对等点的网络。
思考上面图 2 中的网络。当对等点 A 希望知道网络中另一个对等点的位置时,它就发出一个查询请求并传递给邻居。这些邻居尝试满足这个请求。假如这些邻居不能完全满足这个请求,就将请求传递给它们的邻居,以此类推。
要加入网络,一个对等点要找到愿意接受它为邻居的另一个对等点。但是,当对等点本身还不是网络的一部分时,它如何找到网络中的另一个对等点呢?
一个可能的解决方案是向这个对等点提供一个对等点列表,让其检查。对等点设法联系列表上的对等点直到一个或多个对等点接受它为邻居。这个解决方案听起来很象点到点模型,是不是?正如最初 Gnutella 用户所证实的那样,这个解决方案只是一定程度上有效。因为 P2P 网络(尤其是 Gnutella)动态性很强,任何静态列表都不太可能长期有效。
进一步研究 Gnutella 这种环境中的解决方案是很有趣的。Gnutella 实现首先将这样开始:当其它对等点通过网络传播发送请求时,Gnutella 捕捉并持久地存储这些对等点的位置。当这些客户机关闭后又重新启动时,它试图连接每个先前标识的对等点直到找到一个或多个仍在运行。
这种方法,虽然自动化程度很高,但是脆弱而且低效。后来,通过添加对从中心缓存下载活动对等点的列表的支持(请参阅参考资料以获得示例),改进了这种模式下的客户机。
这种模型的一个有趣的方面是,在支持对等点发现的过程中,组成网络的对等点担任了非常活跃的角色。正如我们即将看到的,活动对等点的参与并不是必要条件。
多播(multicast)模型
除了网络中的节点不必协助发现以外,多播模型和网络模型很相似。这种模型利用网络自身提供的特性来定位和确认对等点和资源。这种技术的实现(Sun Microsystems 的 PRoject Jxta 是一个极佳的示例;有关 Jxta的更多信息,请参阅参考资料)使用 ip 多播来实现查询。
不象单播(unicast) IP 数据报 — 一台主机,最多只能向一台主机发送数据报,多播 IP 数据报可以同时发往多台主机。更重要的是,发送方不必知道有多少接收方存在或者究竟有没有接收方存在。发送主机只是封装消息并将它发布到网络上。所有调整到适当频道(非凡 IP 地址和端口号的组合)的客户机将接收到该消息的一个副本。
使用 IP 多播技术的发现通过让对等点用多播定期公布自己的存在来工作。该消息包含对等点的 TCP/IP 主机名和端口号。对此消息感爱好的对等点检测这个消息后,抽取出主机名和端口号,并使用这个信息与新对等点建立正常的 TCP/IP 连接。
这就是多播是如何在单个子网上工作的。众多子网(组成整个网络)间的路由多播通信是完全不同的,并且是一个非常复杂的课题。这也是基于 IP 多播的发现的主要局限。没有路由器的支持,基于 IP 多播的发现被局限在同一子网上的对等点之间。不幸的是,因特网对多播并不友好。通常,因特网(或大型内部网)上的发现由跨网络边界的非凡对等点将消息复制到另一个网络中来实现。
结束语
P2P 应用程序的对等点发现是一个有趣的话题。下个月,我们将研究使用 IP 多播来查找活动对等点的对等点发现的实现。这个简单 P2P 应用程序代码的附加部分将消除一个最大的问题 — 对等点的点到点配置。