/ 中存储网

JBoss-4.2.3GA+Apache负载均衡集群服务器详细部署过程图解

2013-09-25 11:58:01 来源:ITJS.CN

因为公司需要做apache+jboss的负载均衡和集群方面的要求,但阿堂原来没有这方面的经验,便开始了两天的拓荒之旅,其间的痛苦就不用说了,因 为网上的文章,基本上大同小异,估计很多都是互相转载的,作了一些变动,都基本上有些错务,加上网上介绍的jboss版本都基本与我的的版本不一致,造成 网上提到的jboss目录,我这里有可能没有,这样就更增加了一些麻烦,而向网上一些哥们寻找帮助的过程中,有的要么没做过,有的就只是做了 apaceh+tomcat的负载均衡,这样就增加阿堂解决问题的难度!最后总算解决了!先不说最终的实施效果是否如期望的那样,但这个方案能正常实施, 可以说成功了90%了,至于apache等的调优等,就另当别论了!阿堂就不想在此说了!有感于自己配置的麻烦,就写了这篇总结文章和朋友们来一起分享 了,希望能对其它网友有所帮助或借签,阿堂就很开心了!

布署环境

(1)两台Linux服务器 192.168.80.13192.168.80.14

(2)JBOSS版本 4.2.3.GA(在上述两台Linux服务器分别装有此版本的Jboss服务器)

(3) Apache 2.2.17版本 (httpd-2.2.17.tar.gz可从官方网站下载此文件),Apache负载均衡服务器安装在192.168.80.13上

(4)Mod_jk版本1.2.3 (版本是 mod_jk-1.2.31-httpd-2.2.x.so,可从官方网站下载)

特别说明

(1)Mod_jk版本必须与Apache版本配套,否则,可能安装好了,apache能正常运行,但是负载均衡还是不会起作用的,如 mod_jk-1.2.31-httpd-2.2.x.so (如前面的红色文字是mod_jk的版本,后面的红色文字是Apache Server的版本)

部署测试结果

(1)Apache负载均衡已经正常使用,比如说, http://192.168.80.13/test/index.jsp ,前面192.168.80.13地址实际上是Apache服务器的地址,它会拦截随机调用集群中的两个结点192.168.80.13和 192.168.80.14对应的Jboss服务器

如下所示

Jboss-4.2.3GA+Apache负载均衡及集群方案配置过程详解

Jboss-4.2.3GA+Apache负载均衡及集群方案配置过程详解

(2)Jboss的集群功能已经生效。集群中的两个Jboss结点能进行Ajp集群通信了

本项目负载均衡方式:

目前是选择用的基于用户的负载均衡,因为基于request的负载均衡与我们目前需要的多并发,高频操作的情况不适应. (两种情况参照下面的说明)

Jboss-4.2.3GA+Apache负载均衡及集群方案配置过程详解

1、基于request的负载均衡

该种方式下,负载均衡器 (load balancer)会根据各个node的状况,把每个http request进行分发。使用这样的均衡策略,就必须在多个node之间复制用户的session,实时保持整个cluster的用户状态同步,这种操作被称为session复制(session replication)。Jboss的实现原理是使用拦截器(interceptor),根据用户的同步策略拦截request,做同步处理后再交给 server产生响应。

该方法的优点是客户不会被绑定都具体的node,只要还有一个node存活,用户状态都不会丢失,cluster都能够继续工作。缺点是node之间通信频繁,响应速度有影响,多并发、高频操作的情况下性能下降比较厉害。

2、基于用户的负载均衡

该种方式下,当用户发出第一个request后,负载均衡器动态的把该用户分配到某个节点,并记录该节点的jvm路由,以后该用户的所有request 都会被绑定这个jvm路由,用户只会与该server发生交互,这种策略被称为粘性session(session sticky)。

该方法的优点是响应速度快,多个节点之间无须通信。缺点也很明显,某个node死掉以后,它负责的所有用户都会丢失session。

配置Jboss

修改虚拟机的参数run..conf 文件中的jvm堆大小,如果是用Sun或HP的JDK需要设置MaxPermSize

set JAVA_OPTS=%JAVA_OPTS% -Xms256m -Xmx1024m -XX:MaxPermSize=128m

2. 应用部署将EJB的jar包和WEB的 war 复制到$JBOSS_HOMEserverdefaultdeplay

(后面这句话,我感觉好象没有用什么用的)如果是集群环境则复制到$JBOSS_HOMEserverdefaultfarm

3. 部署JBOSS集群服务

用 $JBOSS_HOMEserverall的配置来部署集群则不需这一步,只有下面1、2两步是default配置要多做的工作。

(1). 将$JBOSS_HOMEserveralldeploy 下的cluster-service.xml和jboss-web-cluster.sar复制到$JBOSS_HOME serverdefaultdeploy

(2). 将$JBOSS_HOMEserveralllib 下的jgroups.jar、jbossha.jar、jboss-cache.jar复制到$JBOSS_HOME serverdefaultlib

jbossha.jar(加载org.jboss.ha.framework.server.ClusterPartition)

jgroups.jar(Jboss集群底层通信协议)

jboss-cache.jar(加载org.jboss.cache.aop.TreeCacheAop)

4. 配置Jboss节点

session复制配置

jboss session复制是jboss session同步的一种实现。原理是在各Jboss节点间建立横向联系,每个节点都将本节点的session变化同步到其他所有节点上。

jboss的session复制与HTTP集群是相互配合、相互独立的两个系统。Session复制是节点间的横向联系,HTTP集群是负载均衡器与节点的纵向联系。

$JBOSS_HOME/ server/default/deploy/jboss-web-cluster.sar /META-INF/jboss-service.xml和 $JBOSS_HOME/ server/default/deploy/cluster-service.xml

注意:集群的各节点需要在同一网段.

两个文件都要修改,前者是web session复制的,后者是jboss EJB等集群

找到<config><udp,将><config>到</config>全部注释掉. Jboss session复制有UDP和TCP两种方式.UDP采用多播方式,但问题比较多,所以采用TCP方式。

找到<config><tcp,将><config>到</config>生效.并对该部分进行以下修改:

将全部down_thread和up_thread的false都改为true.

在<tcp bind_addr=” ${jboss.bind.address}”>

在<tcpping initial_hosts=”后填入本机和集群其他全部Jboss节点的IP[7810],比如<tcpping initial_hosts=” ${jboss.bind.address} [7810],192.168.80.14[7810]”></tcpping>

$JBOSS_HOME/ server/default/deploy/jboss-web-cluster.sar /META-INF/jboss-service.xm中的其他参数

ClusterName是集群名称 在同一局域网内,可以存在多个jboss集群,根据集群名称区分它们.所以,集群中各节点配置的集群名称必须一致(实际项目中我配置的集群名称是wenshi),而机器IP则没有特殊要求,只要它们能 相互连通. 理论上,可以在一台机器上安装多个Jboss实例,分属于不同的集群.但这会极大地增加复杂度,是不好的配置方式.严重不建议给自己找麻烦。

IsolationLevel是隔离等级. 可选值包括:SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED, 和 NONE。这里的隔离级别和数据库的隔离级别有同样的含义,对于大多数WEB应用程序来讲通常设置为REPEATABLE_READ。

CacheMode是缓存模式。由于session复制是通过缓存实现的,所以 实际上是复制模式.可选值包括:REPL_SYNC 和REPL_ASYNC,确定改变是应该同步还是异步复制。缺省值是REPL_ASYNC.使用同步复制,确保在请求完成之前传播改变,session同 步没有滞后,但效率低。

<config>

<TCP bind_addr="172.16.80.13" start_port="7810" loopback="true"/>

<TCPPING initial_hosts="172.16.80.13[7810],172.16.80.14[7810]" port_range="3" timeout="3500"

num_initial_members="3" up_thread="true" down_thread="true"/>

<MERGE2 min_interval="5000" max_interval="10000"/>

<FD shun="true" timeout="2500" max_tries="5" up_thread="true" down_thread="true" />

<VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false" />

<pbcast.NAKACK down_thread="true" up_thread="true" gc_lag="100"

retransmit_timeout="3000"/>

<pbcast.STABLE desired_avg_gossip="20000" down_thread="false" up_thread="false" />

<pbcast.GMS join_timeout="5000" join_retry_timeout="2000" shun="false"

print_local_addr="true" down_thread="true" up_thread="true"/>

<pbcast.STATE_TRANSFER up_thread="true" down_thread="true"/>

</config>

5. 配置应用程序

在应用程序的%jboss%serverdefaultdeployjboss-web.deployerROOT.warweb.xml文件中的<web-app>段中增加<distributable />。

在jboss-web.xml(这个文件在哪个目录,我一直不是很清楚,网上均没有说明是哪个目录中的文件,最后是新生成一个jboss-web.xml,放在与上面的web.xml同目录下)中增加以下内容:

<?xml version="1.0"?>

<jboss-web>

<context-root>trms</context-root>

<replication-config>

<replication-trigger>SET_AND_NON_PRIMITIVE_GET</replication-trigger>

<replication-granularity>SESSION</replication-granularity>

<replication-field-batch-mode>true</replication-field-batch-mode>

</replication-config>

</jboss-web>

Apache负载均衡配置

(1)下载且安装。(安装过程略)

Apache Server下载地址

http://httpd.apache.org/download.cgi

Mod_jk下载地址

http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/linux/jk-1.2.31/i386/

(2)修改%apache%confhttpd.conf

在文件末尾添加: Include conf/mod_jk.conf

(3) 在%apache%conf下新建文件mod_jk.conf

文件内容如下

# Load mod_jk module

# Specify the filename of the mod_jk lib

LoadModule jk_module modules/mod_jk.so

# Where to find workers.properties

JkWorkersFile conf/workers.properties

# Where to put jk logs

JkLogFile logs/mod_jk.log

# Set the jk log level [debug/error/info]

JkLogLevel info

# Select the log format

JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"

# JkOptions indicates to send SSK KEY SIZE

JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories

# JkRequestLogFormat

JkRequestLogFormat "%w %V %T"

# Mount your applications

JkMount /* loadbalancer

# You can use external file for mount points.

# It will be checked for updates each 60 seconds.

# The format of the file is: /url=worker

# /examples/*=loadbalancer

JkMountFile conf/uriworkermap.properties

# Add shared memory.

# This directive is present with 1.2.10 and

# later versions of mod_jk, and is needed for

# for load balancing to work properly

JkShmFile logs/jk.shm

# Add jkstatus for managing runtime data

<Location /jkstatus/>

JkMount status

Order deny,allow

Deny from all

Allow from 127.0.0.1

</Location>

其中JkMount /* router的意思是,把所有的请求都发给router处理。可以通过修改url来控制发送某些request。

(4) 在%apache%conf下新建文件workers.properties

其内容为:

# Define list of workers that will be used

# for mapping requests

worker.list=loadbalancer,node1,node2

# Define Node1

# modify the host as your host IP or DNS name.

worker.node1.port=8009

worker.node1.host=192.168.80.13

worker.node1.type=ajp13

worker.node1.lbfactor=1

worker.node1.redirect=node2

# Define Node2

# modify the host as your host IP or DNS name.

worker.node2.port=8009

worker.node2.host= 192.168.80.14

worker.node2.type=ajp13

worker.node2.lbfactor=1

worker.node2.redirect=node1

# Load-balancing behaviour

worker.loadbalancer.type=lb

worker.loadbalancer.balance_workers=node1,node2

worker.loadbalancer.sticky_session=0

#worker.list=loadbalancer

# Status worker for managing load balancer

worker.status.type=status

其中对于node的命名规则是worker.节点名.xxxx。所以上述文件定 义了两个节点:node1和node2。8009端口是jboss 默认的ajp端口,另外需要注意的是worker.node2.lbfactor参数,它是节点的负载加权,它的值越大,获得负载的机会就越大。可以根据 node的硬件性能进行调整。Worker. Router.sticky_session参数是指定是否使用粘性session。配置了http session复制就可以不需要粘性session。上面配置的是不使用粘性session。Worker.server1.redirect=为 failover转移到哪个worker

(5) 配置JBOSS支持粘性mod_jk

修改$JBOSS_HOME/ server/default/deploy/jboss-web.deployer/META-INF/jboss-service.xml

<attribute name="UseJK">false</attribute>改为ture

(6) 配置JBOSS支持粘性session

修改$JBOSS_HOME/ server/default/deploy/jboss-web.deployer/server.xml

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

<Engine name="jboss.web" defaultHost="localhost"  jvmRoute="server1"

注意:jvmRoute的值必须和mod_jk中的节点名字正确对应,否则无法正确路由

测试文件

在%Jboss_Home%serverdefaultdeployjboss-web.deployerROOT.war目录下添加一个新文件夹test,并在里面添加如下3个jsp文件:

index.jsp

<%@ page contentType="text/html;charset=ISO-8859-1" %>

<html>

<head>

<title>Test</title>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

</head>

<body >

<br><br><br>

<center>

The host is : <%=java.net.InetAddress.getLocalHost().toString()%><br>

Your session id is : <%=session.getId()%><br>

Your session detail is : <%=session.toString()%><br>

Your session context is : <%=session.getSessionContext()%><br><br>

Please input your name:<br>

<form action="test_action.jsp" method="POST" name="form">

<input type="input" name="name"/>

<input type="submit" value="submit">

</form>

</center>

</body>

</html>

test_action.jsp

<%@ page contentType="text/html;charset=ISO-8859-1" %>

<html>

<head>

<title>Test Action</title>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

</head>

<%

String name = request.getParameter("name");

session.setAttribute("name",name);

String host = java.net.InetAddress.getLocalHost().toString();

%>

<body>

<br>

<br>

<center>

The host is : <%=host%><br><br>

Your session id is : <%=session.getId()%><br>

Your session detail is : <%=session.toString()%><br>

Your session context is : <%=session.getSessionContext()%><br><br>

Your name is : <%=name%><br>

This name is set into the session.<br>

Please click <a href="http://blog.sina.com.cn/s/session.jsp">here</a>to check the session valid or not.

</center>

</body>

</html>

session.jsp

<%@ page contentType="text/html;charset=ISO-8859-1" %>

<html>

<head>

<title>Test Action</title>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

</head>

<%

String name = null;

if(session.getAttribute("name")!=null)

name = (String)session.getAttribute("name");

String host = java.net.InetAddress.getLocalHost().toString();

%>

<body>

<br>

<br>

<center>

The host is : <%=host%><br>

Your session id is : <%=session.getId()%><br>

Your session detail is : <%=session.toString()%><br>

Your session context is : <%=session.getSessionContext()%><br><br>

<%

if(name!=null){

out.print("Your name is "+name+"<br>");

out.print("The session is valid.");

}

else{

out.print("The session is invalid!!!");

}

%>

<a href="http://blog.sina.com.cn/s/index.jsp">Return!</a>

</center>

</body>

<%

if(session.getAttribute("name")!=null)

session.invalidate();

%>

</html>

访问方式: http://192.168.80.14/test/index.jsp