EJB3在JBoss5内集群探究

EJB3JBoss5x内集群探究

本文介绍ejb3在jboss5x内集群的基本配置及注意事项,我们主要的目的是在jboss5x内集群ejb3,,然后被客户端(可以是web应用程序),不涉及到jboss http请求集群内容。具体见下:

一、             程序准备

我们准备两个项目ejb.rar、webapp.war,其中前者是ejb3项目、后者是web应用程序,主要代码如下:

ejb.rar主要代码:

 

接口:

package com.sample;   

@Remote

//@Local  

public interface HelloBeanItf {   

public void doSomething();    

}  

实现:

package com.sample;   

import java.io.Serializable;   

import javax.ejb.*;   

import org.jboss.annotation.ejb.Clustered;   

 

@Stateless  

@Clustered  

public class HelloBean implements HelloBeanItf {   

int counter = 0;   

public void doSomething() {     

 counter++;   

                   System.out.println("Stateless : Value of counter is " + counter);   

}  

}  

上面是无状态的session bean,注意标注@Clustered是必须的,如果不进行标注那么这个session bean将不会被集群。同样有状态的session bean的集群声明也是这样的,如下:

@Stateful  

@Clustered  

public class HelloBean2 implements HelloBeanItf,Serializable {   

int counter = 0;   

public void doSomething() {     

 counter++;   

                   System.out.println("Stateful : Value of counter is " + counter);   

}   

}

 

webapp.war主要代码:

创建index.jsp文件用以调用无状态session bean,在主要代码如下:

<%   

public void jspInit () {   

try {   

HelloBeanItf ejb = null;   

InitialContext ctx = new InitialContext();   

for(int i=0;i<10;i++){

              //ejb = (HelloBeanItf) ctx.lookup("HelloBean/local");   

ejb = (HelloBeanItf) ctx.lookup("HelloBean/remote");   

}

       }   

       catch (Exception exc) {    

               exc.printStackTrace();   

 }   

}   

ejb.doSomething();   

%>   

Stateless EJB invoked    

创建index2.jsp文件用以调用有状态session bean,在主要代码如下:

<%   

public void jspInit () {   

try {   

HelloBeanItf ejb = null;   

InitialContext ctx = new InitialContext();   

for(int i=0;i<10;i++){

               //ejb = (HelloBeanItf) ctx.lookup("HelloBean2/local");   

ejb = (HelloBeanItf) ctx.lookup("HelloBean2/remote");   

}

       }   

       catch (Exception exc) {    

               exc.printStackTrace();   

 }   

}   

ejb.doSomething();   

%>   

Stateful EJB invoked    

 

 

Classpath下添加jndi.porperties文件,具体如下:

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

java.naming.provider.url=192.168.1.2:1099, 192.168.1.3:1099

二、             配置jboss

配置jboss要稍微麻烦点,我们在三台机器上分别部署jboss名称分别为jboss1、jboss2、jboss3,对应的ip分别为192.168.1.1、192.168.1.2、192.168.1.3。配置具体步骤如下:

(1)    使jboss能通过ip访问,分别找到jboss2与jboss3安装目录下的文件jboss-home\server\all\deploy\jbossweb.sar\server.xml并打开,把

<Connector protocol="HTTP/1.1" port="8080" address="${jboss.bind.address}"  connectionTimeout="20000" redirectPort="8443" />

改为:

<Connector protocol="HTTP/1.1" port="8080" address="0.0.0.0" connectionTimeout="20000" redirectPort="8443" />

(2)    配置jvmRoute,打开jboss2及jboss3内的文件jboss-home\server\all\deploy\jbossweb.sar\server.xml,修改

 

<Engine name="jboss.web" defaultHost="localhost" >

jboss2改为:<Engine name="jboss.web" defaultHost="localhost" jvmRoute="jboss2">

jboss3改为:<Engine name="jboss.web" defaultHost="localhost" jvmRoute="jboss3">

(3)    设置ServerPeerID,打开jboss2及jboss3内的文件jboss-home\ server\all\deploy\messaging\ messaging-service.xml,修改

 

<attribute name="ServerPeerID">${jboss.messaging.ServerPeerID:0}</attribute>

jboss2改为:<attribute name="ServerPeerID">${jboss.messaging.ServerPeerID:2}</attribute>

jboss3改为:<attribute name="ServerPeerID">${jboss.messaging.ServerPeerID:3}</attribute>

 

三、             部署

我们把ejb分别部署到jboss2和jboss3内,使它们进行集群。把web客户端部署到jboss1内用以访问ejb,具体如下:

(1)    复制ejb.jar到jboss2的jboss-home\server\all\farm下,使用all进行部署是因为all内包含所有的服务,集群服务及jboss cache服务都是我们所需的,放入farm内是为了当几个jboss集群后它们将自动完成部署ejb到各自的farm目录内,不过这个功能偶尔会部署失败,可以手工copy一份。当然我们也可以手工把ejb分别复制jboss2、jboss3的jboss-home\server\all\deploy目录下,集群效果一样。

(2)    分别进入jboss2、jboss3主机上控制台进入jboss安装目录使用 run.bat –c all -b 0.0.0.0 命令启动jboss。

当然我们也可以分别用run.bat –c all -b 192.168.1.2 run.bat –c all -b 192.168.1.3分别启动

(3)    部署webapp.war到jboss1的目录jboss-home\server\default\deploy下,并启动jboss1

(4)    部署webapp.war到jboss2的目录jboss-home\server\all\deploy下,用以跟jboss1的web客户端做比对。

四、             运行分析

(1)    运行jboss1内的web客户端

在浏览器上输入http://192.168.1.1/webapp/index.jsp,后我们观察下jboss2、jboss3的控制台

jboss2

jboss3

Stateless : Value of counter is 1

Stateless : Value of counter is 1

Stateless : Value of counter is 2

Stateless : Value of counter is 2

Stateless : Value of counter is 3

Stateless : Value of counter is 1

Stateless : Value of counter is 2

Stateless : Value of counter is 3

Stateless : Value of counter is 4

Stateless : Value of counter is 5

再刷新一次如下:

jboss2

jboss3

Stateless : Value of counter is 3

Stateless : Value of counter is 4

Stateless : Value of counter is 4

Stateless : Value of counter is 5

Stateless : Value of counter is 5

Stateless : Value of counter is 6

Stateless : Value of counter is 7

Stateless : Value of counter is 8

Stateless : Value of counter is 9

Stateless : Value of counter is 10

第一次访问时我们循环了10次,发现在jboss上分别运行了5次,这就达到了负载均衡的目的。第二次访问了我们看jboss内counter是的规律是11223344…这说明jboss1内产生了两个HelloBean 的实例进行轮训访问,而jboss2内只有一个HelloBean 的实例,这完全符合无状态session bean的特性,至于为什么jboss2内有两个实例,还未搞清楚,有待探究。

 

然后我们在浏览器内输入http://192.168.1.1/webapp/index2.jsp,后我们观察下jboss2、jboss3的控制台

jboss2

jboss3

 

Stateful : Value of counter is 1

Stateful : Value of counter is 2

Stateful : Value of counter is 3

Stateful : Value of counter is 4

Stateful : Value of counter is 5

Stateful : Value of counter is 6

Stateful : Value of counter is 7

Stateful : Value of counter is 8

Stateful : Value of counter is 9

Stateful : Value of counter is 10

再刷新一次如下:

jboss2

jboss3

Statefu l: Value of counter is 1

Stateful : Value of counter is 2

Stateful : Value of counter is 3

Stateful : Value of counter is 4

Stateful : Value of counter is 5

Statefu l: Value of counter is 6

Stateful : Value of counter is 7

Stateful : Value of counter is 8

Stateful : Value of counter is 9

Stateful : Value of counter is 10

 

如再连续刷新两次发现输入跟上面一样。第一次访问时我们循环了10次,发现在jboss3上分别运行了10次产生了一个HelloBean2实例,第二次jboss2上运行10次产生了一个HelloBean2实例,这样我们可以看出,每次访问时集群会随机给我们找一个ejb服务,而每次访问都会产生一个新的session bean实例,这完全符合有状态session bean的特性。

(2)    关闭jboss3,我们按照上一步操作进行,发现访问正常进行,所有的请求都在jboss2上响应了,这样我们就达到了故障转移的目的。

(3)    以同样的方式重新启动jboss3,我们分别通过http://192.168.1.2/webapp/index.jsphttp://192.168.1.2/webapp/index2.jsp,进行访问,不难发现所有的请求都在jboss2上得到了响应,这是因为如果如果jboss内的web客户端访问集群ejb时,如果要访问的ejb集群本机也参与的话那么群集只返回本机的ejb,当然如果本机的ejb挂掉的话集群是可以随机分配其它jboss内的ejb的。

(4)    我们可以把HelloBeanItf 的注解改为@Local,把index.jsp、index2.jsp内的 ctx.lookup("HelloBean2/remote");  改为 ctx.lookup("HelloBean2/local");然后按照之前方式重新部署,我们发现只能通  http://192.168.1.2/webapp/index.jsphttp://192.168.1.2/webapp/index2.jsp进行访问,而且请求全部在jboss2上响应,这也符合Local的session bean的特性。

 

五、讨论

通过上面的测试我们可以想象,我们可以构造这样一个集群系统,在一个jboss内构建对外的web客户端来访问其它多个集群后的ejb服务的系统是完全可行的,这样要求这个对外web客户端的jboss不能参与ejb的集群。这种方式看上去有点类似于apache+mod_jk+jboss的http集群,但本质上是不太一样的。这两种方式的集群到底哪个更优本人还未进行过测试,希望以后能有机会亲自测试体验下。以上是我对jboss内集群ejb的一些探究,不足与错误忘大家指点。

posted on 2010-11-11 18:43  张皓  阅读(1617)  评论(0编辑  收藏  举报

导航