新的 JXTA 版本在实用性方面作了改变,更适合于现实世界网络拓扑 html
简介: JXTA 2 是开放源代码 P2P 网络的第二个主要版本,它利用流行的、基于 Java 的参考实现做为构建基础。在设计方面进行了重要的修改,以得到更高的性能、海量伸缩性和可维护的 P2P 网络。本文创建在 Sing Li 于两年前发表的 JXTA 系列文章 Makng P2P interoperable的基础上,为您介绍了这个平台上最新的重要改变。 java
自 JXTA 1.0 推出之后,开放源代码点对点(P2P)和分布式计算团体对它给予了热情欢迎( developerWorks 上有关 JXTA 的早期讨论,请参阅 参考资料)。在日益增加的独立开放源代码项目下聚集了众多的 JXTA 团体,这些项目的目的就是为了验证由 JXTA 平台开发小组所作出的声明:即 JXTA 能够并应该成为将来互操做的 P2P 网络应用程序的首选构建标准。 算法
从积累的经验中学习 shell
在最近的两年中,JXTA 平台设计小组一直在帮助 JXTA 开发团体更好地理解基本设计概念,以及在使用 JXTA 平台 API 提供的功能时的最佳实践。应用程序开发团体的反馈和经验为小组提供了宝贵的意见和建议。这些反馈来源于现实生活中的部署工做,包括对平台最初设计的局限性、API 库的笨拙或者矛盾之处的观察,以及使 JXTA 更适合于构建现实世界 P2P 应用程序的特定要求。若是不先推出一个可工做的参考实现,那么就不可能收集这些宝贵的积累经验。所以第一个版本的 JXTA 很好地达到了它的目的。 数据库
根据这些反馈意见,JXTA 平台小组将主要精力放到了 JXTA 2 的设计和实现中的一组主要目标上。表 1 显示了最主要的设计目标,以及 JXTA 2 实现如何知足这些设计目标的简要说明(对于 JXTA 1 和 JXTA 2 之间的区别给予了强调)。 编程
表 1. JXTA2 的设计目标和实现 缓存
目标 | JXTA 2 实现 |
在当今大多数典型的网络配置上的海量伸缩性 |
|
提升性能 |
|
改进的开发人员友好性 | 对 API 作了大量从新设计和改进,使得 API 更容易理解并具备更多的一致性。主要的 API 改变包括:
|
改进可靠性 | 对节点的自适应行为进行了更改,从而改进了整个网络的可靠性(由于汇集和中继对网络可靠性来讲是最关键的服务,因此大多数更改是围绕它们进行的):
|
提升可管理性 | 支持对节点的详细远程监视。在 JXTA 2 中内建了普遍的测试和计量能力。这是基准测试的关键,也是使网络调整和性能 / 伸缩性改进成为可能的关键。还提供了一个 GUI 监视实用程序。它标志着使 JXTA 节点更具可管理性和更容易管理这一长期计划的开始。 |
兼容移动 | 为 Java 2 mobile edition (JXME)的 JXTA 实现提供了代理能力。 |
一个 网络地址转换设备(NAT)使多台计算机和终端能够经过一个网络地址链接到 Internet (经过转换输出包上的网络地址并对输入包上的地址从新进行转换)。家庭用户或者远程工做的业务用户普遍使用这些设备,它们常被称为 高速 Internet 路由器或者 Internet 共享设备。 服务器
在本文中,咱们将详细考察在 JXTA 2 中使海量伸缩性成为可能的关键改变。咱们还将完成一些使用新的平台配置 API 的实际编码,为 JXTA shell 建立一个寂静启动装置(能够在本身的 JXTA 应用程序中重用的装置)。最后,咱们将探讨几个新的 shell 命令,并看一下在 JXTA 2 网络中是如何索引和定位资源的。 网络
回页首 数据结构
迈向海量伸缩性
现实世界的网络拓扑随着时间而不断发展。它的演变经常受到外部基础设施和经济因素的影响,这些一般是软件系统设计者没法直接控制的。JXTA 1 采起了单纯的和至关理论化的方式使用底层物理网络拓扑。相反,JXTA 2 采起了更多编程式的方式设计覆盖网络,它在今天最多见的网络拓扑上能够有更高的性能和伸缩性。
JXTA 2 推出了 汇集超级节点网络的概念:动态而自适应地将 P2P 网络成员划分为边缘节点(edge peer)和汇集节点(rendezvous peer)。传播只发生在更稳定的(且成员数更少的)汇集节点中。这种限制极大地加强了伸缩性,并下降了网络范围内消息风暴或者泛洪的可能性。
让咱们更深刻地看一下这种新重叠网络(overlay network)的实现。
边缘节点与汇集超级节点的对比
在 JXTA 2 中,边缘节点本质上是易变的,有可能频繁地加入和退出。JXTA 2 网络中大多数节点都会是边缘节点。一个边缘节点不转发查询请求,它可能维护、也可能不维护本身的本地公告缓存。大多数边缘节点将维护一个本地缓存,并须要使用 JXMEJxtaProxy的服务(有关 JXME 的更多内容请参阅 参考资料)。
虽然一些边缘节点与汇集网络直接链接,可是许多边缘节点是经过做为中继的中间节点或者 JxtaProxy链接到汇集网络的。 要参与 P2P 网络,一个边缘节点只需知道如何到达单个汇集节点。一般,一个边缘节点维护一个已知汇集节点的列表(称为 种子汇集节点),并参与新汇集节点的动态发现,这使得该节点能够故障切换到备用汇集节点,并加强整个网络的可靠性。
汇集节点通常变化较少而且更稳定(即当它们链接到网络上后,它们就停留在那里并保持链接)。能够想到,任什么时候候在 JXTA 网络中边缘节点的数量要比汇集节点多得多。汇集节点在本质上是直接链接节点,这意味着它们不该该须要中继或者 JxtaProxy,以链接到网络中另外一个汇集节点。每个汇集节点都是汇集超级节点网络中的成员(在特定的 JXTA 组环境中)。汇集节点把没法根据本身的索引缓存进行解析的查询转发给其余汇集节点,它们参与维护网络中全部可访问资源的一个松散一致的 分布式散列表(DHT)。每个汇集节点维护一个网络中全部已知汇集节点的动态视图,并能够在网络拓扑改变时链接或者故障切换到另外一个汇集节点。
每一个 JXTA 节点均可以假定为边缘节点或者汇集节点。事实上,一个边缘节点若是不能在一个延长的时间(extended period of time)内链接到任何汇集节点,那么它能够自适应地变为一个汇集节点。网络中全部汇集节点也能够发出查询,意味着边缘节点功能其实是汇集节点功能的一个彻底子集。通常来讲,在 JXTA 2 网络中应用的是自适应式和编程式的对称方法,它受底层物理网络拓扑以及定制的用户配置影响。
共享资源分布式索引
JXTA 2 网络的操做依赖于其解析分布式查询的能力(有关这一律念的更多内容,请参阅侧栏“ P2P 网络的实质”)。在 JXTA 2 中,汇集超级节点网络造成了松散一致的 DHT,从而解析分布式查询。
JXTA 2 使用了一种称为 共享资源分布式索引(shared resource distributed index SRDI) 的分布式算法,以建立并维护网络中资源的一个整体索引。在 JXTA 中,资源是用公告形式的元数据(实质上就是 XML 文档)来描述的。经过一组特定的属性,用 SRDI 在网络范围索引这些公告。维护的分布式索引相似于一个散列表,其索引的属性做为散列键,而散列值映射回包含实际公告的源节点。于是能够在汇集网络上任何地方根据这些属性进行查询。这样,经过定位具备所需公告的节点,SRDI 就能够答复在网络中的公告查询。例如,一个节点可能向具备数千个节点的网络发送叫作 “ LotteryService的管道”的查询。SRDI 能够快速地对这种查询进行解析,并使保存有“ LotteryService管道”公告的节点给出回复。
在 SRDI 中,再也不须要远程发布任何公告。发布的只是储存在节点上的公告的索引。这个索引信息经过单个链接的汇集节点“推出”到 DHT(汇集超级网络)。
松散一致的 DHT
JXTA 2 网络的做用是一个持续可用的、网络范围内的、动态的、分布式的数据结构:这是一个虚拟的散列表,包含了整个 JXTA 组中全部已发布公告的索引。一个边缘节点能够在任什么时候候经过提供一组属性(表中的散列键)来查询散列表。该查询是由网络(其实是汇集超级节点网络)经过将该散列键混编为所需的值(即包含所请求公告的节点)来进行解析的,如图 1 所示:
在图 1 中,边缘节点 1 (EP1) 建立了一个管道,并在本地储存其公告。经过 SRDI 更新这个索引,DHT 如今就知道了这个公告。以后,边缘节点 2 (EP2) 对 EP1 的管道进行查询。汇集超级节点网络解析这个查询,并通知 EP1 对该公告的请求。结果,EP1 会将所请求的公告做为响应发送给 EP2。
要建立这个 DHT,每一个节点在本地缓存公告,全部本地存储的公告都已索引。索引推送到汇集节点(在任什么时候侯,JXTA 2 边缘节点只链接到一个汇集节点)。汇集超级节点网络维护包含混合索引的 DHT。查询老是发送到汇集节点,如图 2 所示:
图 2 中显示的步骤以下:
至止,咱们已经描述了由 JXTA 2 汇集网络维护的 DHT,它好像老是以一种完美的一致性方式维护的。这在目前是不可能的,由于在 P2P 网络中,经过相互协做来实现 DHT 的一组汇集节点可能会出现加入和退出现象(尽管不像边缘节点那样频繁)。当汇集节点离开时,它所维护的一组索引就会在必定时间内没法使用(直到可靠的节点再次发布它)。基于一种自适应性的方式,JXTA 2 能够维护一个松散一致的 DHT,它能够处理 P2P 网络中节点的易变特性。
JXTA 2 采起的方式保证了 DHT 在忽然分离的网络(即因为链接节点的消失而产生的节点孤岛)以及新合并的网络(即出现了将之前分离的节点孤岛链接起来的链接节点)中也能够继续工做。JXTA 2 的方法包括了一个 汇集节点查看(rendezvous peerview,RPV) 和一个插入式汇集节点遍历器(rendezvous walker)。
RPV 和 RPV 遍历器
RPV 是由超级节点网络中每个汇集节点维护的。RPV 是该节点的已知汇集节点列表,按各个汇集节点的唯一节点 ID 排序。在 DHT 算法中使用的散列函数在每个节点上都是相同的,它用于肯定一个(本地不能解析的)查询请求应该转发到哪个汇集节点。
全部变得不可达的汇集节点都会从节点的 RPV 中删除。超级节点网络中每个汇集节点都按期向其 RPV 中随机选择的汇集节点发送其已知汇集节点的随机子集。这样作是为了保证 RPV 最终覆盖整个网络,并适应底层物理网络所发生的任何分离或者合并。注意,在任何给定时间,由网络中不一样汇集节点所维护的 RPV 可能彼此不一样。
为了维护 DHT,基于一个固定的散列函数,SRDI 会将收到的索引信息存储到所选择的汇集节点上。为了应付松散一致的特色,这个索引信息冗余地复制到 RPV 中相邻的其余汇集节点上(回顾一下,RPV 是一个已知汇集节点的有序列表,按全局唯一节点 ID 排序)。这能够保证即便目标汇集节点出现崩溃,仍然颇有可能在查询时对这一索引信息进行成功地混编。
在解析查询时,散列函数是针对汇集节点本身的 RPV 执行的。由于可能有多个现有的汇集节点断开链接,或者多个新的汇集节点加入超级节点网络,因此若是散列没有当即解析这个查询,就引入一个 RPV 遍历器,并将查询转发给有限数量的其余汇集节点。这种限定范围遍历器所使用的算法被设计为“插入式的”,也能够根据特定的网络方案进行定制。图 3 解释了索引信息的冗余储存。
在这个图中,散列函数将收到的索引信息映射到 R5。从边缘节点收到这个索引信息的汇集节点 R1 将索引信息发送给 R5,并复制给 R4 和 R6,以增长索引信息的可用性。假设 R3 收到了匹配这条存储索引的查询,那么执行的散列会将查询发送给 R3 的 RPV 中的 R5。不过,若是此时 R5 不存在,那么 RPV 将会收缩,并将原来 R5 驻留的空间关闭。这意味着之前的 R6 将成为新的 R5。
若是 R6 没有所需的索引信息,那么网络的拓扑可能有了重大的改变。在这种状况下,RPV 遍历算法就要发挥做用了。遍历器将在 RPV 列表中上下遍历以查找该信息。
咱们将在下面实际配置和使用一个汇集超级节点网络。在这以前,咱们须要看一看 JXTA 2 中的一些 API 和 shell 的改进。
配置器 API 的主要改进
API 的一个主要改进之处是在对自动配置的支持方面。如今终于可使用平台 API 经过编程建立 PlatformConfig 文件(节点公告),并启动 JXTA 平台。这意味着之前使人眼花缭乱的众多用户配置参数彻底能够隐匿无论。
有多个 API 用于进行自动配置,能够根据您的特定须要选用。大多数与配置相关的 API 在 net.jxta.util.config 包中。net.jxta.util.config.Configurator类是普通的包装器类,用于简化 JXTA 2 配置编程,在许多状况下它已经足够了。在内部,net.jxta.util.config.Configurator 类使用同一包中的更低级的类来完成其工做。
在即将发布的 JXTA 2.2 中(在写做本文时还没有发布),这些配置 API 将统一到一个外部的 net.jxta.ext.config包中。特定角色(如边缘节点、汇集节点、中继)的节点配置文件将进一步方便了经过编程来进行配置。
配置的核心目标是建立一个描述要启动的节点的节点公告。这个节点公告在默认状况下保存在与 PlatformConfig 文件相同的 .jxta 目录中。
为寂静启动对 JXTA 配置进行编程
为了进行咱们的试验,咱们须要启动总共六个 JXTA 节点,其中五个是汇集节点,一个是边缘节点。为了方便您复制这个网络,咱们将在一台计算机上运行全部这六个节点。在之前,这须要花费很大的力气来描述全部须要在 JXTA GUI 中手工输入的配置参数 ―― 这种描述轻易就能够达到本文的整个长度。
为了绕过这种复杂性,咱们将建立一个名为 com.ibm.devworks.jxta2.shell.ShellStarter的 starter 类。这个类将:
步骤 1 和 2 只有在没有找到现有节点公告的状况下才执行。
清单 1 显示 com.ibm.devworks.jxta2.shell.ShellStarter类的部分代码。参阅 参考资料一节,能够下载完整的代码。
public class ShellStarter { private static final String TLS_PRINCIPAL_PROP = "net.jxta.tls.principal"; private static final String TLS_PASSWORD_PROP = "net.jxta.tls.password"; private static final String ADDR_SEP = ":"; private static final String PORT_PRE = "97"; ... public ShellStarter() { } public static void main(String[] args) throws Exception { ... String tpFname = PlatformConfigurator.getPlatformConfigFileName(); File tpFile = new File(PlatformConfigurator.getPlatformConfigFileName()); // only perform config if not already configured if (!tpFile.exists()) { tcpAddress = args[1]; rdvNode = args[3]; int rdvNodeNum = Integer.parseInt(rdvNode); myPort = Integer.parseInt(PORT_PRE + args[2] + PORT_POST); Vector rdvList = new Vector(); if (rdvNodeNum < 10) rdvList.add(TCP_PRE + tcpAddress + ADDR_SEP + PORT_PRE + rdvNode + PORT_POST); pa = PlatformConfigurator.createTcpEdge( args[0], // peername "A dwPeer - " + args[0], // description tcpAddress, // ip myPort, // ports rdvList , // rdvs USER_NAME, USER_PASS ); // disable multicast // pass in to preserve settings TcpConfigurator tc = new TcpConfigurator(pa); tc.setMulticastState(false); // enable incoming connection tc.setServer(tcpAddress); tc.setServerEnabled(true); tc.save(pa); // save to pa only, not file // configure the rendezvous if (isRdv) { // pass in to preserve rdv settings created by PlatformConfig RdvConfigurator rdv = new RdvConfigurator(pa); rdv.setIsRendezVous(true); rdv.save(pa); } PlatformConfigurator.save(pa); } // if config exists System.setProperty(TLS_PRINCIPAL_PROP, USER_NAME); System.setProperty(TLS_PASSWORD_PROP, USER_PASS); Boot.main(args); } } |
在清单 1 中,突出显示的代码展现了如何使用 net.jxta.util.config.PlatformConfigurator 类来准备一个节点公告,该节点公告将用于寂静启动 shell 的一个实例,而无需调用 GUI 配置器。咱们首先用若干命令行参数调用帮助器方法PlatformConfigurator.createTcpEdge()建立一个边缘节点。不过,边缘节点在默认状况下启用多播(multicast),所以咱们要在单机环境中禁用它。咱们用 net.jxta.util.config.TcpConfigurator类关闭多播状态。咱们还使用同一个 TcpConfigurator启用进入的 TCP 链接。最后,咱们检查命令行是否指定了这是一个汇集节点。若是是的话,咱们就使用net.jxta.util.config.RdvConfigurator实例将节点设置为汇集节点。还要注意 net.jxta.tls.principal 和net.jxta.tls.password系统属性的设置,以绕过登陆提示。
ShellStarter的命令行使用如下的参数:
ShellStarter <peer name> <local IP or hostname> <port index> <rdv port index> [edge | rdv] |
咱们建立的全部边缘节点和汇集节点都运行在同一台主机上,可是它们使用不一样的 TCP 端口。参数 <port index>代表节点将运行在 97?1 端口,其中“?”是索引。这使咱们能够在 970一、97十一、9721 等端口上配置多达 10 个节点和汇集节点。例如,要在 9711 端口上用节点名 rdv一、IP 地址 192.168.23.17 建立一个汇集节点,咱们使用下面的命令行:
ShellStarter rdv1 192.168.23.17 1 99 rdv |
注意使用端口索引 99 以代表这个汇集节点没有其余已知的种子汇集节点。
要在 9701 端口上建立名为 peer一、具备同一 IP 的边缘节点,并以上面的汇集节点为种子,使用如下的命令行:
ShellStarter peer1 192.168.23.17 0 1 edge |
对于 rendezvous, 在 test 目录中有五个启动目录 —— 分别为 rdv1 到 rdv5。还有一个称为 peer1 的节点启动目录。每个目录包含一个 runshell.bat 文件,它有针对 ShellStarter的相应参数。您将须要编辑这些文件以修改 IP 地址。图 4 显示了这个网络的配置。
在 JXTA 2 shell 发布中,有几个新命令。其中对开发者最有用的是 kdb命令。能够在平台运行的时候,用这个命令打开和关闭不一样 JXTA 组件的调试日志。
kdb命令是菜单驱动的,可用于设置 16 个组件中任何一个的日志优先级(结果是生成的调试信息量差异很大)。
新的 route命令可用于显示或者操做 JXTA 路由表信息。
JXTA 2 shell 中另外一个有用的命令是新的 rdv命令,它特别有助于理解汇集超级节点网络是如何操做的。这个命令有许多选项,在咱们的试验过程当中对其中一些选项进行了探索。
要启动这个系统,首先从一到五按顺序启动全部汇集节点。必定要等每个汇集节点彻底启动后再启动下一个,而后再启动 peer1。
观察 RPV 和遍历器的活动
使用 rdv命令(参见侧栏“ JXTA 2 中的新 shell 命令”),能够看到由任何一个汇集节点维护的 RPV。
rdv -rpv |
做为例子,下面的代码片断显示了 rdv1 给出的结果:
rdv5 rdv4 rdv3 rdv2 |
RPV 顺序反映了节点的 JXTA 节点 ID 顺序。咱们如今能够观察 RPV walker 的活动了。 rdv命令有一个运行字符串索引服务的选项(只用于测试和诊断)。要启动这个服务,在全部六个节点上运行下面的命令:
rdv -start |
如今,在其中一个汇集节点上建立一个字符串。在咱们的例子中,咱们在 rdv4 上建立“treasure”:
JXTA> rdv -add treasure |
您能够用下面的 list 选项来确认 rdv4 如今包含这个字符串:
JXTA> rdv -list treasure |
如今,让咱们看一下 RPV 遍历器的活动。在 peer1上搜索如下的字符串:
JXTA>rdv -search treasure Sending test message rdv has sent search query for treasure JXTA>rdv received from : jxta://uuid-59616261646162614A78746150325 03369170C5E92004D0DB2E48AAA571741C803 found: treasure |
马上就在 rdv4上找到了 treasure 字符串。能够在 rdv4上键入 whoami 验证这个节点 ID 确实就是 rdv4。
看一下 rdv4shell 窗口,您将看到回复确实是直接从 rdv4发出的:
Replying search query= treasure send reply sent |
在其余的汇集节点上,您会看到转发这个查询的证据:
Forwarding search query= treasure |
下面是所发生的过程:当查询“treasure”时,就调用汇集节点遍历器,“遍历”汇集超级节点网络。做为一台汇集节点客户机,这个请求被传递给惟一链接的汇集节点 ―― rdv1。从 rdv1 开始的“遍历”引发了对查询的传播。每个没有“treasure”字符串的汇集节点都经过遍历器转发这个请求给其余已知的汇集节点(转发次数不超过任意设置的生存时间 / 跳数限制值 10,并受循环检测控制),直到这个请求到达 rdv4。收到这个查询后,rdv4 直接回复给 peer1。
观察 SRDI 的活动
使用 rdvshell 命令,能够容易地试验 RPV 和汇集节点的遍历机制。要实际看到 SRDI 的活动,咱们能够设置 SRDI 消息日志机制的LOG级别为 DEBUG,并引发一些 SRDI 活动(即一个节点上建立一个公告)。
为了不来自诊断字符串索引服务的伪消息,首先要关闭这个服务。关闭从 rdv1 到 rdv5 以及 peer1 的服务:
rdv -stop |
而后在每个节点上,用 kdb命令将 SRDI 消息的 LOG级别设置为 DEBUG:
JXTA>kdb KDB Main Menu 1 Change LOG configuration q Quit MAIN> 1 LOG Menu 1 Global 2 EndpointRouter 3 Endpoint 4 HTTP 5 TCP 6 TLS 7 Rendezvous 8 Discovery 9 Resolver 10 Pipe 11 Relay 12 Messengers 13 Messages 14 Quota Listener 15 SRDI 16 CM q Quit LOG> 15 Level [w,i,f,d,e,q or ?])> d LOG Menu 1 Global 2 EndpointRouter 3 Endpoint 4 HTTP 5 TCP 6 TLS 7 Rendezvous 8 Discovery 9 Resolver 10 Pipe 11 Relay 12 Messengers 13 Messages 14 Quota Listener 15 SRDI 16 CM q Quit LOG> |
如今,咱们将在 peer1 上建立一个公告,它会致使 SRDI 索引信息被推送到 rdv1,并随后复制到 DHT 中。建立公告的最容易方式是建立一个新的 peergroup(其实是一个 peergoup 公告):
newpgrp -n supergroup |
若是再看 rdv1 输出的消息,您将会看到相似于下面的 SRDI 消息:
<DEBUG 14:36:07,078 Srdi:521> Pushing deltas in group NetPeerGroup <DEBUG 14:36:07,078 Srdi:494> waiting 30000ms before sending deltas in group NetPeerGroup |
当散列和冗余索引复制发生时,其余汇集节点可能也会收到由 rdv1 发送的其余 SRDI 消息。
结束语
P2P 网络对当今计算的影响是深远的,而且已经有大量的计算用户受到其影响。不要期望在彻底隔离的条件下设计一个可行的 P2P 应用程序建立环境。对用户反馈、连续需求分析、从新考虑设计和设计迭代的考虑,是建立一个可以使用的设计环境的重要因素。JXTA 听从了这种理念。在第二代版本中,JXTA 根据其早期使用者群体的现实需求进行了改进和调整。
经过编程式地将重叠网络分为经过核心 汇集节点互连的边缘节点,在今天常见的网络拓扑上部署 JXTA 2 更容易了。同时缓解了在“平面的”体系结构中常见的消息广播风暴和洪流的问题。
JXTA 2 的核心 汇集节点网络实现了松散一致的 DHT。在 P2P 网络上可用的全部资源均可在这个 DHT 的帮助下索引并动态获取。由 DHT 维护的索引是 SRDI。与初版相比,再也不在网络中传播公告了,相反,在须要时只传播索引信息。这种方法显著地改进了可用网络带宽的使用,而代价只是在查询解析时计算量稍有增长。
另外一个正在完善的领域是 JXTA 平台 API。全功能节点配置 API 如今可使用了,它容许开发人员建立寂静启动的应用程序,而无需启动 JXTA 的默认(一般是使人困惑的)节点配置器。咱们在建立寂静 shell 启动脚本进行试验时使用了这个 API。使用新的 shell 命令 rdv,咱们能够观察汇集超级节点网络的活动。经过使用新的 kdbshell 命令设置 DEBUG 日志级别,还能够观察 SRDI 消息传递和操做。
建立可伸缩的、高性能的而且(最重要的) 可以使用的P2P 网络须要不懈地追求。JXTA 2 是在正确的方向上迈出的重要一步。
参考资料
原文地址:http://www.ibm.com/developerworks/cn/java/j-jxta2/index.html#2