jboss集群session复制原理:
jboss session复制是jboss session同步的一种实现。原理是在各Jboss节点间建立横向联系,每个节点都将本节点的session变化同步到其他所有节点上。
jboss的session复制与HTTP集群是相互配合、相互独立的两个系统。session复制是节点间的横向联系,HTTP集群是负载均衡器与节点的纵向联系。
10.0.2.203 �C 安装JDK 1.6,JBoss 7,JBoss节点名称为jboss1
10.0.2.202 �C 安装JDK 1.6,JBoss 7,JBoss节点名称为jboss2
10.0.2.200 �C 安装Apache httpd,mod_jk #需要在官网下载mod_jk模块,重命名为mod_jk,放置于/etc/httpd/modules 下
以下实验注意iptables 和 selinux 的影响。
安装jdk和jboss 此处就不多说了,jboss不需要修改
/usr/local/jboss-4.2.2.GA/server/all/deploy/jboss-web.deployer 目录下的
server.xml文件的 <Connector port="8080" address="${jboss.bind.address}"默认地址,使用 mod_proxy时修改了此处。
下面是apache 的配置:
a:在/etc/httpd/conf.d/目录下创建mod_jk.conf文件,内容为:
LoadModule jk_module modules/mod_jk.so #指定模块路径
JkWorkersFile conf.d/workers.properties #指定mod_jk的workers定义
JkLogFile logs/mod_jk.log #指定jk的日志输出文件
JkLogLevel info #指定日志级别
JkLogStampFormat "[%a %b %d %H:%M:%S: %Y]" #用来配置log文件的日期/时间格式. 使用strftime()的格式化字符串,默认是[%a %b %d %H:%M:%S %Y]
#Options Description(选项的说明)
# %b 发送的字节, 不包括 HTTP headers (CLF format)
# %B 发送的字节, 不包括 HTTP headers
# %H 协议
# %m 请求方式(get/post)
# %p 服务器响应请求的规范端口.
# %q 查询字符串 (如果存在以?开头,否则是空串)
# %r 请求的第一行.
# %s HTTP状态码
# %T 请求间隔, 处理请求耗费的时间 秒.微秒
# %U 请求的url路径,不包含查询字符串.
# %v 响应请求的规范服务器名字
# %V 根据UseCanonicalName设置的服务器名字.
# %w Tomcat worker 名字
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T" #设置个人用户请求的log格式
#JkMount /* loadbalancer
JkMountFile conf.d/uriworkermap.properties #加载workers的请求处理分配文件
#JkMount /* status
JkShmFile logs/jk.shm #共享内存
<Location /jkstatus/> 对/jkstatus 新建访问控制
JkMount status
Order deny,allow
Deny from all
Allow from 10.0.2.0
</Location>
b:接着在/etc/httpd/conf.d/目录下创建workers.properties 文件,内容为:
worker.list=loadbalancer,status # worker列表
worker.jboss1.port=8009 #ajp13 端口号
worker.jboss1.host=10.0.2.203
worker.jboss1.type=ajp13
worker.jboss1.lbfactor=1 #server的加权比重,值越高,分得的请求越多
worker.jboss1.cachesize=10
worker.jboss2.port=8009
worker.jboss2.host=10.0.2.202
worker.jboss2.type=ajp13
worker.jboss2.lbfactor=1
worker.jboss2.cachesize=10
#重试次数
worker.retries=3
worker.loadbalancer.type=lb #用于负载均衡
worker.loadbalancer.balance_workers=jboss1,jboss2 #指定分担请求的server列表,用逗号分隔
worker.loadbalancer.sticky_session=1 #设置用于负载均衡的server的session可否共享
#一次请求中 session 只会在一个jboss上,当该jboss奔溃后,请求会跳转到其他jboss上,但是其session不会复制到跳转后的jboss上
worker.loadbalancer.sticky_session_force=0 #当jboss1崩溃后,请求转发到jboss2
worker.status.type=status #描述是用于httpd自身状态监控的status
c:然后 在/etc/httpd/conf.d/目录下创建uriworkermap.properties 文件,内容为:
/*=loadbalancer #所有请求都由loadbalancer这个server处理
/jkstatus=status #所有包含jkstatus请求的都由status这个server处理
!/*.gif=loadbalancer #所有以.gif结尾的请求都不由loadbalancer这个server处理,以下几个都是一样的意思
!/*.jpg=loadbalancer #这里的"!”类似于java中的"!”,是“非”的意思
!/*.png=loadbalancer
!/*.css=loadbalancer
!/*.js=loadbalancer
!/*.htm=loadbalancer
!/*.html=loadbalancer
以下是jboss 实例的配置:
a:在10.0.2.203主机,编辑 $JBOSS_HOME/server/all/deploy/jboss-web.deployer/server.xml 文件
<Engine name="jboss.web" defaultHost="localhost" jvmRoute="jboss1">
在Engine 处添加 jvmRoute="jboss1",在10.0.2.202主机也相应地修改为jboss2
b:在10.0.2.203和10.0.2.202主机分别编辑 $JBOSS_HOME/server/all/deploy/jboss-web.deployer/
META-INF/jboss-service.xml 文件
<attribute name="UseJK">true</attribute> #将UseJK的值改为true,使用mod_jk
c:在10.0.2.203和10.0.2.202主机分别编辑
/usr/local/jboss-4.2.2.GA/server/all/deploy/jboss-web.deployer/conf/web.xml 文件
<?xml version="1.0"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<distributable/> #添加此项,开启jboss的session复制
<!-- ... -->
</web-app>
d:这里要做的是基于request的cluster,也就让各个节点之间互相复制session状态。有两种复制模式,同步与异步。使用同步的方式,jboss会把session复制的操作和对request的响应放到一个应用事务(application transaction),session复制完成后才去处理request。异步复制则发送session复制的消息后马上处理request,session复制则会稍有延迟。但是在多框架的web页面中,这样的集群方式会有问题。由于frame在同一时间发出多个request,会造成一些混乱,这也是采用基于用户的集群方式的原因之一。
<attribute name="CacheMode">REPL_ASYNC</attribute>
REPL_ASYNC(异步)或者REPL_SYNC(同步)。
attribute name="ClusterName"> 这个属性是设置你的集群的名字
在下面还有个<attribute name="ClusterConfig"> 这个属性是设置每个节点在进行session复制的时候是如何通信的,有TCP和UDP两种,默认使用UDP。如果使用udp方式,那么应该将udp的lookback属性指定为true。采用UDP方式问题比较多,所以采用TCP方式,应该指定bind_addr的值为本机ip,并且在TCPPING标签的initial_hosts属性中列出所有节点,格式是”机器名[端口号]”,将<TCP>到</TCP>标签内的全部down_thread和up_thread的false都改为true。还需要注释掉<!--<config><udp>...</udp></config>-->。
e:在10.0.2.203和10.0.2.202 主机写index.jsp测试页面,放置于/usr/local/jboss-4.2.2.GA/server/all/deploy/jboss-web.deployer/ROOT.war 目录下,内容为:
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " + session.getId()+"<br>");
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session list</b>");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
%<form action="index.jsp" method="POST">
%id:<input type=text size=20 name="dataName">
%<br>
%key:<input type=text size=20 name="dataValue">
%<br>
%<input type=submit>
%</form>
%</body>
%</html>
最后浏览器访问:10.0.2.90/jkstatus
可以从jkstatus看到关于设置的大量信息
浏览器访问10.0.2.90/index.jsp
接着填写内容并提交
可以看到提交的内容并sticky在一台jboss实例
此时将jboss1停掉,可以看到session在jboss2上面,提交内容,再启动jboss1,停掉jboss2,可以看到session在jboss1上面。(此实验session从jboss2到jboss1有点问题,待解决)
查看/usr/local/jboss-4.2.2.GA/server/all/deploy/jboss-web-cluster.sar/META-INF目录下的jboss-web.xml 文件:
ClusterName是集群名称,
在同一局域网内,可以存在多个jboss集群,根据集群名称区分它们.所以,集群中各节点配置的集群名称必须一致,而机器IP则没有特殊要求,只要它们能相互连通. 理论上,可以在一台机器上安装多个Jboss实例,分属于不同的集群.但这会极大地增加复杂度,是不好的配置方式.
IsolationLevel是隔离等级.
可选值包括:SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED, 和 NONE。这里的隔离级别和数据库的隔离级别有同样的含义,对于大多数WEB应用程序来讲通常设置为REPEATABLE_READ。
CacheMode是缓存模式。
由于session复制是通过缓存实现的,所以实际上是复制模式.可选值包括:REPL_SYNC 和REPL_ASYNC,确定改变是应该同步还是异步复制。缺省值是REPL_ASYNC.使用同步复制,确保在请求完成之前传播改变,session同步没有滞后,但效率低。