JNDI
集群的实现
Java EE
规范要求
Java EE
容易需要提供对
JNDI
规范的实现。在
Java EE
应用中,
JNDI
的主要角色就是提供了一个中间层,资源可通过较为透明的方式获得。这使
Java EE
组件提高了重用度。
具有完整功能的集群
JNDI
是
Java EE
集群的重要内容,因为几乎每个
EJB
组件都从查找
(lookup)
其
JNDI
树的
home
接口开始。各个厂商实现
JNDI
集群的方法不同,主要是根据其集群的结构而定。
全局共享
JNDI
树
WebLogic
和
JBoss
都使用集群范围全局共享的
JNDI
上下文以便客户端能查找并绑定对象。绑定到全局
JNDI
上下文的内容将被基于
IP
的多播技术复制到整个集群中,这样当一个服务器实例宕机时,还能保证绑定对象可获得。
如上图所示,全局共享的
JNDI
树实际上包含了每个节点上所有本地的
JNDI
的集合。集群中的每个节点都有其自己的
JNDI
命名服务器,它将所有的信息复制到集群中其它所有的命名服务器中。这样,每个命名服务器的树中都有其他命名服务器的对象拷贝。这样的冗余结构使全局
JNDI
树实现了高可用。
实际上,集群的
JNDI
树有两个用途。管理员可以用它来进行部署任务。在一台服务器上部署了
EJB
模块或配置了
JDBC/JMS
服务后,所有的
JNDI
树都会被复制到其它服务器实例。在应用运行期间,程序用
JNDI
的
API
访问
JNDI
树来存储和检索对象,所以自定义的对象也被全局复制。
独立
JNDI
虽然
JBoss
和
WebLogic
采用了全局共享
JNDI
,但
SUN JES
、
IBM WebsPhere
和其他一些服务器采用了独立
JNDI
树技术。在独立
JNDI
树集群环境下的成员服务器不知道或者并不关心集群中的其他服务器。那这样岂不是意味着不对
JNDI
进行集群?因为几乎每个
EJB
访问都从
JNDI
树中查找其
home
接口开始,所以如果不对
JNDI
树进行集群就会丧失集群的功能。
实际上,独立
JNDI
树依然能实现高可用,只要
Java EE
的应用都是同构的。我们将其称为同构集群,因为所有的实例配置相同,部署了同样的应用。在这样的条件下,一个叫
“
代理
”
的特殊管理工具可用来实现高可用,如下图:
SUN JES
和
IBM WebSphere
都将代理安装在集群的每个实例上。当部署
EJB
模块并绑定其他
JNDI
服务时,管理终端通过对所有代理发送命令来达到与全局共享
JNDI
树同样的效果。
但是独立
JNDI
解决方案将不支持复制由运行的应用绑定和检索的判定对象。原因如下:在
Java EE
应用中,
JNDI
扮演的角色是对管理外部资源提供中间层,而不是运行时数据的存储。如果有需要的话,各自的
LDAP
服务器或有
HA
功能的数据库能够实现。
Sun
和
IBM
都有它们的
LDAP
服务器产品,而且都已经随着集群特性分发。
集中式
JNDI
一些
Java EE
产品使用集中式的
JNDI
树,命名服务器驻留在一台服务器上,所有服务器实例将
EJB
组件和其他管理对象注册至命名服务器中。
命名服务器本身实现了高可用,对客户端透明。所有客户端通过单独的命名服务器查找
EJB
组件。这种结构加大了安装和管理的复杂度,所以不为大多数厂商采用。
对
JNDI
服务器的初始访问
当客户端访问
JNDI
服务器时,需要知道
hostname/IP
地址和远程
JNDI
服务器端口号。在全局共享与独立
JNDI
树解决方案中,均有多个
JNDI
服务器。那么客户端会先连接哪台
JNDI
服务器呢?如何实现负载均衡和失败转移呢?
通常,软件或硬件负载均衡器可在远程客户端和所有的
JNDI
服务器之间执行负载均衡和失败转移的任务。但是几乎没有厂商采用这样的办法,而使用一些简单的解决方案。
- Sun JES和JBoss通过“java.naming.provider.url”让JNDI设置接收由逗号分离的URL列表来实现集群。例如,java.naming.provider.url=server1:1100,server2:1100,server3:1100,server4:1100
客户端将尝试逐个与列表中的每台服务器,一旦连接上之后就停止尝试。
- JBoss也实现了自动恢复的功能。当属性字符串“java.naming.providing.url”为空时,客户端将尝试通过网络多播调用恢复引导JNDI服务器。