Java 版 (精华区)
发信人: rhine (静&&凉爽&&想念你), 信区: Java
标 题: jini核心技术3
发信站: 哈工大紫丁香 (2000年07月17日11:03:08 星期一), 站内信件
第3章 Jini 模 型
主要内容:
* Jini的目标。
* Jini是什么、不是什么。
* 基本概念:发现、查找、租借、远程事件、事务。
* 可下载的代理是服务发送的关键。
我们已经看到Java可以给分布式计算带来很多好处,下面来看看Jini给Java带来了什么
。Jini的设想十分简单:所有支持Jini的设备,可以是数字相机、打印机、PDA或者蜂窝
式电话,只要插入到TCP/IP网络中,就可以自动发现并使用附近其他支持Jini的设备。
支持Jini的设备可以使用网络上任何可用的资源,就像直接连到一起或者用专门的程序
控制了设备一样。把一个新设备添加到"网络群体"中,只需要将其插接到网络中。
在本章,来看一下Jini到底是什么。首先看一下其设计的"重心"-Jini开发者主要考虑了
哪些方面,然后看一下Jini所引入的五个新概念。
3.1 Jini设计的中心
在本节,将讨论Jini设计的中心问题,也就是Jini的设计者感觉最重要的一些领域。
3.1.1 简明性
Bill Joy是Jini的策划人员之一,他曾经说:"成功的大系统起步于成功的小系统",Ji
ni系统在很大程度上也是受这种观点的启发。从本质上说,读者了解了Java,也就了解
了Jini,Jini完全基于基本的Java概念构造,尤其在一些有关分布式计算的问题上更是
如此,另外为使网络上的设备和服务更便于合作而增加了很少一些其他的内容。
有一点很关键:Jini本质上是解决服务彼此间如何连接的问题,而不是讨论这些服务是
什么,做什么或如何工作。事实上,Jini服务完全可以用Java以外的其他语言开发,唯
一的要求是在网络上存在一小段采用Java编写的代码,它可以参与到Jini中寻找其他的
Jini设备和服务的机制。
前面一直在使用"设备"和"服务"两个词语,实际上从Jini的角度看,一个设备如扫描仪
、打印机或电话也是一个服务。参照面向对象里的方法,世界上的一切,包括硬件设备
,都可以通过其表现的接口来了解,这些接口就是它们提供的服务,因此Jini使用"服务
"这个术语来指代网络中可被其他Jini参与者所使用的实体。这些实体所提供的服务实现
方法可以各不相同(仍然是面向对象的术语),可以是一个硬件设备,或是多个设备的
组合;也可以是一个纯软件实体或是多个软件的组合。
3.1.2 可靠性
我们说Jini提供了一种使网络上的服务可以彼此寻找并互相利用的基本结构,但是这句
话究竟意味着什么呢?Jini是不是就像Internet上的域名服务器(DNS)或者一个单位中
的轻量目录访问协议(LDAP),只是简单地提供名字解析服务?事实上,Jini和名字服
务器有相似之处,它也提供一种用于查找群体中其他服务的服务(不过这种服务要比传
统的名字服务功能强大得多),但是和简单的名字服务器比,Jini另外还有两个基本特
点:
* Jini支持服务以及服务使用者之间"偶遇"(serendipitous)的交互,也就是说,对J
ini的其他参与者,一个服务的出现和消失都是轻便的,一组协同服务的所有变化,都会
自动通知到相关的参与者。Jini允许那些其他服务可感知的服务不停变化,无需静态配
置或是进行管理。基于这种工作方式,Jini支持"自发连网",那些彼此邻近的服务能够
自动组成一个小群体,不需用户的直接介入。这意味着不必进行编辑配置文件、重启名
字服务器,以及配置网关等工作,就可以使用Jini服务。理论上只要将设备插到网上,
Jini就可以完成其他工作了。另外,连到Jini群体的设备或服务都带有可以被群体中其
他的参与者使用的代码。
* Jini服务的群体具有很强的"自修复"能力,这是Jini天生具有的基本属性。Jini不认
为网络是完美的,也不认为软件从不会失败,不过只要有足够的时间,Jini系统就可以
修复自己内部的故障。像通常的做法那样,Jini也支持冗余结构,以减小在关键机器出
现故障时服务不可用的可能性。
这些属性使得Jini在商业级别的分布式系统结构中与众不同,同时也保证了Jini群体可
以无需管理。Jini的自发连网能力是指可以在不需系统管理员的情况下改变网络;而可
以使用Jini群体中未知设备的能力是指在使用特定设备时不需安装驱动程序或软件(当
然要安装Jini内核软件);此外,Jini系统的自修复能力也减轻了管理负担,方便了用
户。一组协同工作的Jini服务对于网络拓扑的变化、服务丢失以及网络划分等现象也有
很大弹性,Jini服务可以应付网络失败。Jini的服务并不可能一直工作(即使电话网有
时也会报错),但是至少在系统失败时,它们可以按预定方式处理,并且可以在一定时
间内恢复。
3.1.3 可伸缩性
前面提到许多Jini服务以协同工作组的方式加入到一起,在Jini中,这些服务组被称为
群体(community)。群体中的任何服务都能感觉到其他服务,并可以相互利用 。Jini
服务集中到一起可形成群体,不过这样的群体可以有多大呢?Jini的设计者们对群体的
大小所定的目标是什么呢?这是一个重要的问题,如果Jini设计为可支持特别大的组,
比如说一个由全美国所有支持Jini的设备组成的组,那么其性能和互操作特性与仅支持
一个小组时会有很大差别。这里的关键是可伸缩性(scalablity),即如何使Jini容纳
数量不同的服务,可以特别多,也可以特别少。
Jini通过联合(federation)来解决可伸缩性问题。联合是Jini群体连接到一起组成更
大的组的能力。理想情况下,一个单独Jini群体的大小与一个工作组的大小相类似,也
就是说,一个10个到100人的组所使用的打印机、PDA、蜂窝式电话、扫描仪等设备以及
相应网络服务组成一个群体。这样定义一个工作组的原因在于,大多数情况下人们只和
那些一起工作的人协作,Jini使这样一组人更方便地组成一个群体,并把他们的资源共
享。
即使你只是本工作组小群体中的成员,也可能需要偶尔访问一下"远处"(网络意义上的
)的资源,比如需要了解市场上新的彩色激光打印机。Jini通过联合把各群体组成更大
的组织,从而支持访问其他群体中的服务。特别地,Jini查找服务,即用于跟踪一个群
体中所有服务的实体,其本身也是一个Jini服务,这样某个群体中的查找服务可以在其
他群体中注册,把自己以一种资源的方式提供给那里的用户和服务(稍后我们将看到,
实际上Jini是自引导的(bootstraps):很多核心的Jini特征就是Jini的服务,它们可以
通过正常的Jini机制被其他的服务共享和使用)。
这些群体的拓扑并不重要,在安装Jini软件时,系统自己会根据网络边界创建群体。举
例来说,如果你的工程部和市场部在不同的网络中,那么每个部门都会形成一个单独的
Jini群体。如果你希望把这些群体结成联合,只需要稍做一点管理,保证每个群体中的
查找服务彼此认识即可。
注意:Jini和管理
Jini被设计为在无需管理的情况下正常工作,不过为使系统适应特殊的环境,当然也可
以做一些手工的管理。
将企业中的群体组织成联合是这类管理的例子:Jini自己可根据网络的情况创建群体,
但它不知道企业的行政结构,因此我们必须亲自给Jini配置这些信息。
3.2 设备不可知论
这个问题在前面章节也提到了,不过它十分重要,需要重新进行说明:关于设备,Jini
是不可知的。这是什么意思呢?从根本上说,它是指Jini的设计是支持各种可参与到Ji
ni群体中的"实体",这里的"实体"可以是设备或软件,或者是二者的组合体。事实上,
这些"实体"的用户通常也说不清楚它们到底是什么。这是Jini的一大贡献,即我们可以
使用某些实体而不必知道它是硬件还是软件,其实根本就不必关心,只要了解它的接口
就行了。
对于真正连接到网络上的硬件设备,Jini可灵活支持它具有的计算能力。Jini可支持真
正的桌面计算机或服务器计算机,这些计算机能够运行多个JVM并且通过快速网络互连;
Jini也可以支持PDA和蜂窝式电话这样的Java功能十分有限的设备,这些设备一般只有嵌
入式的或个人的Java版本,类库也有限。
事实上,Jini的设计是面向那些可能根本没有计算能力的简单设备。在下一章我们将了
解到,Jini甚至可以支持带计算智能的电灯开关,前提只需要存在其他的或共享的计算
资源可代表它参与到Jini群体的协议中。
此外令人惊奇的是,Jini甚至不要求设备或者服务用Java编写程序或是理解Java程序,
Jini只需要一些可以支持Java的设备作为代理代表那些非Java的设备和服务。
3.3 Jini不是什么
我们已对Jini是什么做了些陈述,下面几条是说Jini不是什么。
3.3.1 Jini不是名字服务器
前面已谈以,Jini并不是一个简单的名字服务器。尽管Jini的一些行为,如跟踪一个群
体中的服务,看起来像是名字服务器,而且Jini使用的Jini查找工具,功能也类似于(
不完全相同)名字服务器,但Jini并不仅仅如此。它是一个用于创建分布式系统的模型
,可支持服务在一个群体中自发地出现或消失,而且在系统出错时具有自修复能力。
3.3.2 Jini不是JavaBeans
JavaBeans提供了一种方法,使得软件构件(称为Bean)可以彼此找到,可以使用其他B
eans提供的服务,相互内省等等。但JavaBeans的设计核心与Jini完全不同,Beans需要
在单地址空间中使用,Bean之间使用的通信机制是基于直接方法调用,而不是远程协议
。Beans的模型在灵活性和动态性方面都远不如Jini。当一个新的Bean出现在系统中时,
应用中已有的Bean不能立即感知到它并使用它,系统的设计者必须明确地把这个Bean链
入应用中并建立与其他Bean的连接。JavaBeans主要是用于设计时而不是运行时,在单地
址空间中使用;Jini是用于运行时,跨地址空间工作(这并不是说Jini和JavaBeans不兼
容,相反,Jini可以在很多方面优化JavaBeans,后面相关章节将讨论如何从Jini中使用
JavaBeans事件模型,以及如何将Bean附加到Jini服务中)。
3.3.3 Jini不是企业JavaBeans
类似地,Jini也不是企业JavaBean(EJB)。从表面上看,EJB具有一些Jini的特征,它
提供了网络上的服务的概念。企业Bean可以存在于不同的地址空间,并且一般也是如此
。但是EJB设计的核心是集中于企业级系统,依靠Java软件来构成企业应用的后端事务逻
辑。EJB主要用于支持简便地构造事务逻辑,优化企业网络中已有的事务、消息及数据库
服务,因此EJB被大量地用于配置企业软构件之间相对静态路径。只要系统的逻辑不发生
变化,也就不需要重新组织Bean之间的连接。同样,EJB是在设计时决定如何连接,而相
反Jini是动态的,它在运行时发现服务并在运行时连通它们。
3.3.4 Jini不是RMI
Jini与Java RMI不同。Jini很大程度上使用了RMI,尤其是在Jini可移动代码的功能上,
可以说Jini就是建立在RMI基础上的一组服务和规范。尽管如此,Jini的服务还具有自发
连网和自修复能力,虽然也可以(工作量很大)把这些功能加入到通常的RMI应用,但是
它们不是RMI本身所具有的,通常的RMI应用也不具有这些优点。
3.3.5 Jini不是分布式操作系统
最后一点,Jini不是分布式操作系统。从有些方面看,它要比分布式操作系统大,因为
有些部分必须运行在至少提供JVM的平台上,而从另外的角度看,它又小得多,Jini所提
供的工具以及所使用的概念十分有限。真正的分布式操作系统提供了传统操作系统的所
有服务(文件读写、CPU调度、用户登录等),只不过是在一组互连的机器上实现这一功
能。Jini允许十分简单的设备加入到Jini群体,而不是要求设备必须运行一个完全的分
布式操作系统。
3.4 Jini的五个基本概念
概念的简明是Jini的目标之一。Jini支持的自发创建群体及自修复等能力,都是基于五
个基本的概念,理解了这些概念,也就明白了Jini的使用。
这些概念是:
* 发现(Discovery)。
* 查找(Lookup)。
* 租借(Leasing)。
* 远程事件(Remote Event)。
* 事务(Transaction)。
这些概念以一组软件库和规范的形式实现,可被Jini群体中的参与程序使用。
发现是用于寻找网络中群体并加入它们的过程,是Jini完成自发创建群体功能的部分。
查找是控制提供某个特定服务所需要的程序如何把自己提供给使用服务的参与者的方式
。查找在每个Jini群体中的作用相当于目录服务,它提供用于寻找一个群体中已知服务
的功能。但查找的功能实际上要比名字服务器复杂得多,名字服务器只是把字符串映像
到对象上,而Jini的查找软件可理解Java的类型层次,因此查找操作可在对象类型的基
础上进行,而且在搜寻过程中甚至还可以考虑到类的继承关系。这里讨论的查找功能(
用于Jini上下文中)比基于字符串的名字服务器复杂许多。
租借是Jini中最重要的概念之一,原因只是由于它被广泛地使用。租借技术使Jini具有
自修复能力,它保证了一个群体在某些关键服务失败的情况下,一段时间之后可以恢复
。租借还保证了长时间运行的服务(如查找服务)不会"积累"其群体的信息,若没有租
借,长时间运行的服务会无限制地增长。
远程事件是Jini服务彼此通报状态的变化所采用的范型。因为查找本身是一类服务,所
以在一个群体可用的服务发生变化时,它可以利用远程事件方式通知相关的参与者。Ji
ni的远程事件模型与JavaBeans的事件模型相似,但不完全相同,在第14章"深入理解:
远程事件"中将讨论详细的原因。不过本质上远程事件要和前面章节讨论的"远程特性"语
义相结合满足Jini的基本需求:即任何实体都可以接收所有类型的事件。
事务是Jini使包含多个服务的计算到达一个"安全"状态的机制。这里的意思是,调用者
可以得到保证,计算要么全部完成,要么都没有进行,无论哪种情况,系统都到达一个
确知的状态。Jini的事务模型可以消除分布式系统中部分失败所带来的危害,从而解决
第2章中提出的并行性问题,极大改善了服务的健壮性,使服务对网络故障有更大弹性。
Jini的事务模型和数据库编程中常用的事务模型看起来有些相似,但其内部实现却完全
不同。
本章后面的内容将对这些基本概念进行分析,并看看这些服务如何在实践中协同工作。
学习完本章后,读者将会明白创建Jini的所有基本机制。在后面的几章,为了加强对这
些概念的认识,将引入用于创建实际Jini服务和应用的编程技术。
3.4.1 发现
一个Jini实体(服务或应用)在使用其他Jini服务之前,必须先找到一个或多个Jini群
体,途径是寻找跟踪该群体中共享资源的查找服务。这个寻找可用的查找服务的过程称
为发现。Jini发现协议是Jini程序寻找Jini群体的途径,一旦找到某个群体,Jini实体
就会按照加入协议的一系列规范加入到该群体中,并在该群体中公布服务。
对于查找服务,没必要各群体一对一地映像,网络上的每个查找服务都可以为一个或多
个群体提供服务,每个群体也可以有一个或多个查找服务器支持。查找服务要明确由管
理员来启动-事实上,这是创建Jini群体时需要运行的唯一一个Jini服务。
1. 发现协议
发现协议不止一个,Jini支持多个发现协议,分别用于不同的环境下。
* 组播请求协议(Multicast Request Protocol),当一个应用或服务首次被激活,需
要寻找附近活跃的查找服务时使用此协议。
* 组播通告协议(Multicast Announcement Protocol),查找服务用此协议声明自己的
存在,当已存在的群体中启动一个新的查找服务时,其他相关的参与者都可通过组播通
告协议被通知。
* 单播发现协议(Unicast Discovery Protocol),在一个应用或服务已经知道了要连
接的特定查找服务时,使用此协议。单播协议用于直接连向某连接服务,可能此服务并
不在本地网络,只是知道它的名称。查找服务以Jini开头的URL格式来命名,作为协议的
唯一标识(如jini://turbodog.parc.xerox.com是指运行于turbodog.parc.xerox.com机
器上缺省端口的查找服务)。当需要在服务和查找服务之间建立静态连接时,可使用单
播发现协议,比如在需要直接把查找服务联合到一起时可以使用此协议。
有关发现过程的最终结论是,执行发现功能的实体有多个引用被传送到被请求群体的查
找服务中,通过这些引用,服务可表明自己能提供的功能,客户和服务就可以判断一个
群体中有哪些可用的服务了。客户还可以在查找服务上执行一些其他的操作,比如说事
件请求(参见本章"查找"一节,这一节介绍了查找服务的一些细节)。
一些应用如浏览器可能要获得查找服务的引用以显示可用服务的列表,但在大多数情况
下,执行发现操作的实体是希望自己可被群体中其他成员使用的Jini服务。把一个服务
发布给群体中的其他服务表明其可用的过程称为"加入(joining)到群体中",一个希望
加入某群体的服务首先执行发现操作以寻找该群体的查找服务,然后使用从发现中返回
的查找服务的引用,加入到群体中(同样参加下一节"查找")。为保证服务的正确操作
,Jini提供了加入协议供加入到群体的服务遵循,这里的"协议"并非网络意义下的协议
,只是一组各服务必须遵循的规范。
2. 支持多个群体
在Jini中,群体可有相应的名称。在Jini API中,这些名称被称为"组(group)"。在发
现过程中,一个服务或应用可指明它希望寻找的组,发现协议会返回所有它可以找到的
是相应组中成员的查找服务。查找服务可以是多个组中的成员,就像其他服务可以是多
个组中的成员一样。
在大多数情况下,可以把组和群体当作是一回事,组是Jini用来在其API中表示群体的概
念。群体和组之间最主要的区别在于:由于网络是分离的,不同的群体可能具有相同的
组名。例如,Xerox PARC实验室中的"public"组就不指向JavaSoft实验室中相同名称 的
"public"组。尽管名称相同,这些名称仍可以根据不同上下文来指代不同的群体。换一
种说法就是,组名并非全局唯一的,也不必全局可访问。不过在大多数情况下,可认为
组和群体两个概念可以互换。
服务如何知道要加入哪个群体?在多数情况下,服务先是简单地寻找"默认"的组,名称
是空字符串,传统上被当作是"公共"群体;其后它们使用组播协议去连接可发现的所有
查找服务。组播协议被设计为发现过程只针对本地网络中的查找服务进行,而不是把发
现协议的报文传递到整个Internet网络中。
有些情况下,服务需要加入到非默认的群体中。例如一个产品开发实验室希望在"exper
i- mental"(实验)群体中测试新的Jini服务,而同一子网上的"production"(产品)
群体是默认的设置,这两个群体可能共享资源(服务同时加入到两个群体中),也可共
享查找服务(查找服务同时是两个群体的成员),为加入到非默认的"experimental"群
体,服务要使用组名"experimental"来寻找是"experimental"群体中成员的查找服务。
在另外一些情况下,服务可能需要明确地连接到一组特殊的查找服务,比如,一个具有
特殊授权和限制的"只针对管理员"的查找服务。在这种情况下,一个特权的后备的服务
会启用单播发现协议保证只连接到特殊的查找服务,即使查找服务和后备服务运行在不
同的网络中也可以完成。可启用单播协议的功能使得Jini在创建群体的结构时更加灵活
。
第6章将更加深入地讨论各种发现协议,不过使用它们比较简单,大多数应用和服务只需
要实现DiscoveryListener接口,简单地做些参与发现的记录,然后找出附近的Jini群体
即可。
3.4.2 查找
发现是寻找查找服务的过程,而查找是指对那些查找服务可做的事情。可以把查找服务
想像成一个名字服务器,实际上也就是一个通常长时间运行的进程,用于跟踪加入到Ji
ni群体中的所有服务。不过和传统的名字服务器不同的是,名字服务器只提供一个从字
符串名字到存储对象的映像,而Jini查找服务支持更丰富的语义。可以通过对象的特殊
类型搜寻Jini查找服务,而且由于查找服务理解Java类型的语义,甚至可以通过查找存
储对象的超类和超接口进行搜寻。在发现过程成功地找到一个查找服务时,它返回一个
实现查找接口(这个接口实际上称为ServiceRegistrar,或许称为Lookup更合适些)的
对象的引用。
查找服务的内部实现细节是不公开的,就像LDAP和网络信息服务(NIS)一样,它可能是
使用一个简单的hash表、定期存盘,或者是一个功能强大的目录服务,可十分迅速地把
查找和日志写到永久存储器中。用户所知道的只是从发现过程返回的对象实现ServiceR
egistrar,并且这个对象知道如何与网络中某些机器上运行的任何真正的查找服务进行
会话。用户不知道通信的细节。它可能使用了Java RMI,或者是Vanilla套接字,或者是
其他成熟的技术。查找服务允许有各种不同的实现方式,但所有的细节都隐藏在所获得
的实现查找接口的对象之后。
1. 发布服务
在做完发现工作,获得了一个或多个查找对象之后,应该如何处理它们呢?可以把查找
服务抽象地想象为在维护一个"服务项目"列表,每个服务项目中包含一个对象和一组用
于描述服务的属性,群体中的其他参与者可下载此对象以使用服务。图3-1中给出了一个
持有三个服务项目的查找服务,每个服务项目包含一个"代理"对象和一组描述服务的属
性。稍后我们将提到,这个代理对象可被需要使用服务的客户所下载,尽管一个客户可
能不知道特定服务的实现,它可以把服务的代理作为"前端"实现与服务的互操作。
对于一个希望把自己发布到群体中,也就是想对那些要使用它的人表现为可用的服务(
如打印机),可以把自己加入到所有从发现过程中返回的查找服务中,加入的途径是使
用ServiceRegistrar接口中的register ( )方法。
图3-1 查找服务维护服务项目列表
提示:加入到群体中的每个查找服务
注意任何群体(也就是一个给定网络中的特定组名)都可能有不同数目的查找服务支持
它,为了容错,也可能有一些是活跃的冗余查找服务。
一般地,需要加入到群体中的服务将加入到支持该群体的所有查找服务,以便在一个查
找服务失败时,其他的可以替代它。除非有特别的需要,或者希望明确限定服务可被发
现的范围,通常都把服务加入到所有的查找服务中。
加入是需要把服务项目对象作为参数传递给register ( )方法并调用它,然后填充一些
可描述服务的属性。Jini为此提供了一些标准的属性:服务名、服务位置、注释等等。
对于销售许多Jini服务的公司,还应该有自己的标准属性集以描述这些服务的特殊信息
。
2. 可下载的代理
服务项目中最重要的部分即是称为服务代理的序列化的Java对象,在服务中它是唯一的
。当其他的实体,无论是另外的Jini服务还是想利用此服务的应用,找到这个服务项目
时,代理对象就会被复制到该实体的Java虚拟机中,实体通过调用此代理对象来使用服
务。
可下载服务代理的思想,是使Jini可以在不安装驱动程序或软件的情况下使用服务和设
备的关键所在,服务发布可用来访问自己的代码。例如,一个打印机发布一个理解如何
控制此打印机的代理,扫描仪发布知道如何使用此扫描仪的代理,使用服务的应用程序
下载相应代理对象并使用它,不必理解代理是如何实现的,或者是如何与后端的设备或
进程交流的。
在某些方面,Jini代理与Java Applet有些相像:Applet提供了一种不需要管理的方法来
获取并使用应用程序,Jini代理也提供了一种不需要管理的方法来获取并使用"粘合逻辑
",从而与后端相关的服务或设备进行通信。不过Applet一般是设计为"为人所使用",即
通常表现为当用户请求时以图形界面形式出现在Web页中,而Jini代理的设计是面向被查
找、下载,并在程序中使用。Jini代理也可被看作是安全的网络上的设备驱动程序,在
那些需要它们的客户要求时下载到客户端。
代理对象如何与服务交互作用的特定方式完全取决于实现者,不过还是有一些通用的方
式。
* 下载的代理对象执行服务。在这种情况下,发送到用户端的服务的代理对象独自完成
服务声明的所有功能(因此称之为"代理"实际上不公平)。在服务完全由软件实现并且
不需要使用外部资源时可采用这种策略。例如一个完全由Java程序实现的语言翻译服务
,可下载到用户端并顺利执行。在这种情况下,下载的程序不需要启用任何外部进程来
完成它的工作。
* 下载的对象是用来通知某个远程服务的RMI存根。当用集中的进程来实现服务时,常采
用这种方案。例如一个IMAP邮件服务(IMAP即Internet邮件访问协议,经常是全组的电
子邮件通过IMAP服务进程集中进行存储和管理)。IMAP邮件服务允许Jini应用在发送和
读取邮件时,不必了解IMAP的细节,但可以使用IMAP服务器的邮件数据库和传送引擎。
这时邮件服务器将允许客户下载一个小对象,这个对象实现了一些用于发送新邮件和读
取邮件信息列表的方法,这个对象将通过RMI与网络中其他机器上"真正的"IMAP服务器通
信。这种策略允许Jini应用和服务只是简单地下载一个实现了所需邮件接口的小代理对
象,而实际的邮件处理安全地运行在后端服务器上,Jini代理只是自动产生的有关对象
的RMI存根。
* 下载的对象使用私有的通信协议与服务进行联系。此策略在两种情况下最常使用。首
先是在有遗留的软件服务存在时,Jini可以很好地通过Java使遗留的非Java系统可访问
,开发者只要实现"粘合剂",即实现遗留服务所需接口的可下载小Java 对象。这个代理
对象将使用遗留系统所支持的协议进行通信,如套接字、专有数据库状态等,然后提供
一个可方便于Jini服务访问和使用的纯Java接口。第二种情况是在服务实际由硬件设备
提供时,如果硬件设备是一个打印机,代理对象就给使用者提供"类似打印机"的接口,
然后使用与打印机通信所需要的专有协议来实现,实现的细节对使用者是隐藏的。
Jini使服务和设备可带有使用它们所需的程序,这种功能的关键是代理对象。代理根据
服务的实现不同而各不相同,通常是服务的开发者编写,在服务的使用者需要时被下载
,被下载对象的代码可被使用者安全地执行。更妙的是,使用者不必知道这个特殊的代
理如何与实际的服务实现连接。打印机的所有使用者只需要知道代理实现了一个Printe
r接口,而不必知道代理如何与某个特别的打印机通信。图3-2是加入过程的示意图,图
中我们看到一个新创建的服务向新找到的两个查找服务发布它的服务代理。
3. 如何找到服务
我们已经了解了服务如何加入到群体中并发布自己的服务,接下来看一下服务的使用者
如何找到并使用作为群体中成员的服务。
使用者(它自己可以是加入了群体的服务)一旦拥有了一个查找服务的引用,就可以搜
寻所有服务项目以找到所需的服务。Jini提供了多种搜寻的方法,可以根据每个服务项
目中所包含的可下载代理对象的类型进行搜寻,也可以根据服务的特有标识符(如果知
道的话),或者还可以根据每个服务项目中包含的属性进行搜寻。这个找到所需服务的
过程是查找服务的核心(自然ServiceRegistrar接口有一个称为lookup ( )的接口完成
此功能)。无论用哪种方式,一旦指定了搜寻的参数并调用lookup ( ),返回的值就是
服务项目的代理对象。在图3-3中,将看到一个客户应用程序(Jini服务的使用者)从查
找服务下载一个特定服务的代理的过程。代理被下载后,客户就使用代理作为"前端"直
接与服务的"后端"进行通信。"后端"一般是长期运行的进程,或是连到网络上的硬件设
备。代理可能很复杂,也可能很简单,例如,一些"智能代理"可能要与后端实现私有的
通信协议,而另外一些可能只是RMI产生的存根,用于与一个后端的远程对象进行通信。
图3-2 服务加入到Jini群体
图3-3 使用Jini服务
假设要为一个数字相机编写软件。相机对外表现为一个服务(可能实现一个DigitalCam
era接口,其中包含snapShutter ( )和copyOutPicture ( )方法),你希望如果能在附
近检测到打印机,就直接把相机中的图像打印出来。首先,你要使此服务对于所有相关
实体都可用,这可以通过已讨论的加入过程来处理;其次,为了能够在任何可用的打印
机上打印,这个相机也要成为其他服务的使用者,这里是打印机。
这种情况下,一般的方案是相机搜寻其群体中的所有查找服务,寻找包含实现Printer接
口的代理的服务项目。查找服务可能会返回一个或多个实现了此接口的代理,数码相机
就会作出选择并在LCD显示器上列出这些代理,可能还要根据属性加上名称、位置、说明
信息等。当相机用户选择在特定的打印机上打印时,前端代理对象的Printer方法被调用
,输出被送到打印机。
4. 通用接口,不同的实现
读者也许会有这样的疑问,"相机如何知道去寻找有Printer ( )接口的服务项目?"显然
,服务和应用至少需要对它们所调用接口的语义有一定的理解。数字相机软件的开发者
可能不知道Printer ( )接口如何工作,但他至少应该知道这个接口是干什么的,然后把
相关内容送到打印机。如果遇到一些不太明智的命名,比如Fleezle接口,你可能不知道
它是用于做什么的,不知道该向它的方法传递什么参数,也不知道如何处理返回值。在
这种情况下,如果没有其他用户告诉你相关信息,是不可能在编程时考虑此接口的。为
此,大多数Jini服务需要实现比较通用的接口,只有这样才能够让开发者在看到服务时
知道如何程序化地与其实现互操作。
Sun,它的合作者,以及广大的Jini用户一起,正在为打印机、扫描仪、蜂窝式电话、存
储服务以及其他一些常用的网络设备和服务定义一组通用接口,这项工作仍在继续之中
。如果可能,新服务的开发者应使用适当的标准接口,以保证Jini服务可相互利用。
当然如果用户说明了如何处理,也可以使用未知的接口,为此,Jini支持存储任意的序
列化Java对象作为服务项目的属性。如前所述,服务的使用者可基于属性搜寻,也可以
基于服务代理的类型。例如,一个数字照相机可以在其群体中搜寻所有具有java.awt.c
omponent属性的服务,这些属性是显示给用户的用户接口,从而允许用户"手工地"与服
务进行交互--即使相机的程序不知道如何与未知的服务程序化地互操作。因此,用户可
以通过Fleezle服务的用户接口来认识它,即使相机的软件不能利用这个服务,也可以直
接通过相机来控制它。
通过服务代理,已经对下载代码讨论了很多。需要指出的是,Jini查找结构本身也是通
过这种机制,允许Jini服务与不同的查找进行通信。在执行发现时,所有应答查找服务
返回的服务代理,实际是针对不同的查找服务实现的。在查找服务的协调下,不论如何
实现以及使用什么通信机制,Jini服务都允许统一的使用方式。
3.4.3 租借
以上讨论了发现和查找,Jini的这两方面内容使服务群体可自发形成,并且可彼此交换
代码以实现互操作。对于如何保证实现群体的稳定性、自修复能力,以及面对网络失败
、机器崩溃和软件错误时的弹性,我们还没有提及。在软件系统(如Jini群体)需要长
时间运行,希望几个月甚至几年不出现中断时,可靠性问题尤其重要。
举一个例子,假如数字相机设备在群体的查找服务中注册加入到一个群体中(相机可通
过专用设备连入网络,或接到连网的计算机上),发布信息表明自己可用且一切正常。
可是如果用户在不关掉设备的情况下随意将相机拔掉,问题就来了。对于群体中的其他
成员来说,这和部分失败的情形有些类似,它们不知道是否相机所连的远程主机已经关
掉,或只是响应比较慢,或者是由于更改了配置不能响应网络传输,或是相机的软件出
现故障,甚至是相机已经坏掉。无论如何,由于和网络之间通信的突然结束,相机不能
在断开连接之前先退出注册。
用户不正确断开相机(这种情况可以理解且时常发生)带来的结果是,如果不采取措施
,相机的注册将永远连接在此群体的查找服务中,想要使用相机的服务可以看到它的注
册,但不能使用它。更严重的是,如果这些服务的注册不能被正确清除,查找服务会遇
到麻烦,越来越多的注册信息附着在查找服务上,使查找服务越来越慢最终崩溃。
在长时间运行的分布式系统中这种状态的存在是一个严重的问题,我们不能保证服务不
突然崩溃,或在断开连接之前都有机会取消注册。
在上例中,相机会占用查找服务中的资源,它要求查找服务使用存储和处理能力来维护
自己的注册。如果Jini仍使用传统的方法来分配资源,注册在被取消之前将保持活跃,
除非有系统管理员浏览日志后强行清除有关服务。
显然,这种情况有悖于我们希望从Jini中获得的好处,首先,它不能保证系统可自行修
复,部分失败不能被识别并清除,那些代表其他服务的占有资源的服务将无限增长;其
次更糟的是,它需要人为地管理系统。
1. 基于时间的资源保留
为解决这个问题,Jini使用了一种称为租借的技术。租借的基本思想是:不再保证可以
在无限制的时间内访问资源,资源只是在一段固定的时间内"借给"某使用者,Jini租借
要求那些证明确实与某部分资源密切相关的使用者继续占有相应资源。
Jini租借与现实生活中的租借十分相似,Jini租借可能被借出者所拒绝,租约持有者可
以续订。除非是续订,否则一段确定的时间之后租约就会到期;租约也可以提前取消(
和现实生活中不同的是,毁约没有惩罚)。租约可以通过谈判确定。不过和现实生活中
类似,租借提供方在提供租约的细节上拥有最后的发言权。
租借提供了释放Jini中未用或不需要的资源的办法。一个服务退出群体时,不管是有意
的还是无意的,它自己不必清理资源,其租约最终会到期,有关服务的记忆也被清除。
租借不仅在查找服务中,而且在系统的其他方面也广泛使用,因此,在创建或使用Jini
服务时,理解如何有效使用租借是十分重要的。
租借的一个重要作用是使局部的错误不会破坏整个系统:系统的工作比较谨慎,如果在
程序中忘记了管理租约,或者程序错误使租约得不到续订,类似的不可靠程序会使自己
退出群体,对其他部分不会造成损坏。Jini统一了程序错误(租约续订失败除外)和网
络错误、机器故障的处理方式,资源的提供者所看到的只是服务的租期已经过期,不可
再用。
租借的另一个重要作用是真正使得Jini群体的成员所使用的固定存储空间不需要维护,
系统管理员永远不必再费劲地检查日志,以确定哪些服务活跃,哪些服务非活跃,哪些
服务在系统中遗留了很多废弃数据。一定时间以后,群体能够识别出那些未使用的资源
并释放它们,就像反病毒的系统对付病毒一样。如果在PC中能够如此轻松地清除所有不
需要的应用,未使用的应用程序以及使过时的操作系统升级,那将是多么伟大的进步啊
。
2. 第三方租借
Jini的租借和现实生活中的许多租借有一个重要的区别就是:Jini租借的设计允许第三
方代表另外的实体实施租借,第三方只是完成租借机制的整个过程,租约实际上仍是有
效的(这有些像岳母以女婿的名义租了一套漂亮的房屋供她居住)。
注意:租借的类比
实际上对这种情况更贴切的类比是代理人,当你把代理权委托给某个人时,这个人就有
权代表你在合约中签名,不过代理人只是完成签名,你仍是合约的一方。
在Jini中,第三方的代理可以代表另外的实体完成租借,但不会获得任何好处,因此第
三方租借因为方便了租借者而广泛使用。
为什么需要这种方式呢,有几个原因,最重要的是方便了租借者。如果只希望关注开发
服务本身而不考虑租借API、租约续订、租约过期等等问题,那么可以把租约续借过程委
托给第三方。告诉第三方代管程序把租约续订一段时间,直到通知它结束。第三方就会
忙于和租借者接触、商谈租约期,在租约过期前实现续订。也可能存在这种情况,第三
方转告说租借者因为某种原因决定不续订这个租约。这个过程与前面所见的"代理人权力
"类似,这种方式对于租借者十分方便。
对于一些持有租约,希望长时间运行,但极少处于活跃状态的服务来说,第三方租借也
会带来方便。例如,一个为磁盘做月备份的服务每个月才运行一次,其他时间这个服务
都会处于睡眠状态。其工作可以基于Java RMI激活框架,即Java对象被自动写到永久存
储器中,过一段时间后再重建。尽管这样的服务在相当长的时间(可能甚至几年)内都
处于睡眠状态,但还需要被激活,其与查找服务间租约的期限应该相当短,可能会在分
钟级。如果月备份服务需要每10分钟被唤一次来续订其租约,每天就会有大量的计算资
源花费到唤醒和保存该服务上。如果实际上是如此,那么这和此服务每月工作一次的情
况十分不相符。
这时第三方租借是解决办法。月备份服务把租约续订权利授予第三方,这个第三方自己
可能是一个服务,并且公布说自己希望长时间代表其他服务做租约续订(因此,这个租
约续订服务可以被多个长期运行的服务共享)。这个第三方与前面例子中的第三方工作
方式相同:管理租约列表、在到期前实现续订、在不能获得续订时通知租借者。
3. 第三方租借和代管
熟悉AWT事件模型(JDK 1.1中)或JavaBeans编程的读者会注意到,第三方代理和"代管
"事件模型有些类似。"代管"事件模型允许第三方代表其他对象处理事件,这和最初的A
WT事件模型不同,AWT模型中的事件必须由事件要送往的实际对象来处理。代管更加灵活
,可支持集中事件管理器、事件列表等编程模型,第三方租借也有很多相同的优点。下
面的工具条介绍了Jini中的代管租借是如何工作的。
工具条:租借代管
第11章将深入分析租借代管,不过现在可以先看一小部分代码,以让程序员对租借代管
有个大致印象,实际上它十分方便使用。
这个例子中的代码用来向Jini查找服务注册一个新的服务,注册返回的ServiceRegistr
ation对象中包含一个租约。
这个租约可由管理其续订的第三方代管程序处理。这个例子中的租借代管程序是一个称
为Lease Renewal Manager的类,它作为非支持代码附在Jini软件的sun-util.jar文件中
。
在此例中,把对租约的处理委托给称为LeaseRenewalManager的"库"类,管理租约的这个
类的实例位于租约持有者所在的JVM中。当然也可以把对租约的管理委托给外部的处于另
外一个JVM中的进程。
所有的细节将在第11章讨论,这个小代码段只是让你对租约代管的好处有些印象。
4. 租约的实际应用
到现在为止已经解释了什么是租借,但没有介绍它是如何工作的。在Jini中,任何要占
用资源的操作都把持续时间作为参数,然后返回一个租约对象。例如,查找服务在服务
注册时可租约,这个租约并非永久的,ServiceRegistrar中的register ( )方法用一个
长整数作为参数,表示该服务希望租约保持的微秒数。查找服务返回一个ServiceRegis
tration类型的结果,其中包含了刚注册的服务的信息。ServiceRegistration中有一个
成员为Lease对象,这个对象代表查找服务所许可的租约,可用于对租约的操作,例如续
订或取消。
从这个例子中可以得到两点结论。第一,"商谈"过程比较简单,只是"一回合"的商谈,
需要获取租约的一方提出一个时间段,提供租借的一方或者
--
海纳百川,
有容乃大,
壁立千尺,
无欲则刚。
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: dip.hit.edu.cn]
※ 修改:·rhine 於 07月17日11:04:28 修改本文·[FROM: dip.hit.edu.cn]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:209.641毫秒