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_proxy #mod_proxy默认系统就提供
安装jdk和jboss 此处就不多说了,因为jboss默认只监听127.0.0.1,所以需要修改
/usr/local/jboss-4.2.2.GA/server/default/deploy/jboss-web.deployer 目录下的
server.xml文件,
<Connector port="8080" address="0.0.0.0" #8080是监听端口,后面是监听IP(IP需要修改)
下面是apache 的配置:
<IfModule mod_proxy.c>
ProxyRequests Off
ProxyPass /mycluster !
#
<Proxy balancer://mycluster>
BalancerMember http://10.0.2.203:8080 route=node1 loadfactor=1
BalancerMember http://10.0.2.202:8080 route=node2 loadfactor=1
ProxySet lbmethod=bytraffic
# ProxySet stickysession=ROUTEID
# Order deny,allow
# Deny from all
# Allow from 10.0.2.0
</Proxy>
ProxyTimeout 600
ProxyPass / balancer://mycluster
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e;paht=/" env=BALANCER_ROUTE_CHANGED
<Location /mycluster>
SetHandler balancer-manager
Order Deny,Allow
Deny from all
Allow from all
</Location>
注意:测试时注意iptables和selinux对实验的影响,当开启selinux时,客户端不能访问,报503错误,查看日志提示permission deny,执行 setenforce 0 就可以访问。这个503错误 也可能是jbos未启动导致的。
此时启动两台主机的jboss服务,然后再重启apache服务,打开浏览器访问 http://10.0.2.200/mycluster 监控页面,可以看到访问统计情况,接着访问 http://10.0.2.203 (最好将两台主机的jboss默认页面修改,添加各自的IP,方便查看)
此时实现了session的sticky。
下面是session 共享的配置:
从上面的实验来看,只做到了负载均衡,但有个问题,客户端连接到服务端,正在提交内容时,一台jboss实例不幸停机了,后面提交的内容会转发到正常的jboss实例,但是之前提交的内容不会复制正常的jboss实例,此时需要配置session的复制,也就是session的共享。
/usr/local/jboss/server/default/deploy/jboss-web.deployer/server.xml 文件,
将<Engine name="jboss.web" defaultHost="10.0.2.203" > 修改成<Engine name="jboss.web" defaultHost="10.0.2.202" jvmRoute="node2">
另一台jboss实例 修改成node1
然后编辑
/usr/local/jboss/server/all/deploy/jboss-web.deployer/ROOT.war/WEB-INF/web.xml 文件
添加如下
....
<distributable/> #如果没有添加,则不会session复制
</web-app>
接着在
/usr/local/jboss/server/all/deploy/jboss-web.deployer/ROOT.war/ 目录下 创建index.jsp 测试文件
内容为:
<%@ 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>
在node1和node2上先后启动服务
/usr/local/jboss/bin/run.sh -c all -Djboss.bind.address=10.0.2.202
/usr/local/jboss/bin/run.sh -c all -Djboss.bind.address=10.0.2.203
最后启动apache服务。
访问:http://station1/index.jsp,输入值并提交,查看日志,关闭正在处理session会
话的jboss,再次提交页面,如能看到session会话被复制到另一台jboss上表示成功,此动作
对用户是透明的。
浏览器访问,并提交内容
10.0.2.202 的jboss实例输出的内容
从访问的监控来看,在客户端提交内容后,提交的所有内容(包括之前提交的内容)都会复制到另一台jboss实例,jboss默认使用UDP广播方式进行session复制,这样来看,导致了不必要的冗余数据的session复制,占用了一定的网络带宽。(不知有什么好的办法,让每次只更新新提交的内容,这样也可以节约带宽,后续完善。)
还有当一台jboss实例停掉后,客户端访问时才检查到jboss不工作了。
当其中一台主机的jboss实例停掉后,另一台正常的jboss实例能够检测到,并打印出信息
当停掉的jboss实例又恢复后,另一台正常的jboss可以检测到:并打印出信息
当客户端请求到来后,apache不会转发到恢复的jboss实例,还是由当前的jboss实例来处理。
注意:貌似mod_proxy 不可以将session的sticky和共享一起配置,但apache的mod_jk和nginx可以集成配置。