电子表格FineReport教程:[24]集群
1、前述
Windows集群同J2EE的集群不同,因为它是操作系统自带的集群支持,它没有J2EE集群对java的web应用的良好支持,例如session粘滞。所以对Windows集群,需要特别配置一下,以此来支持集群的功能。
2、原理
均衡负载会根据情况,将外部请求分配给集群内的服务器处理。当一个会话(Session)在A服务器上产生并开始,产生了一部分会话信息将保存到A服务器的内存中。假如这次会话中的一次请求被均衡负载调度器分配到了B服务器去处理,那么问题就产生了,B服务器中的内存中并没有这个会话的信息,那么就会报查询超时(session time out)。而我们通过配置文件的配置,会在集群的服务器间建立联系。当B服务器收到请求,发现这个请求的会话不是自己产生的,那么它会根据请求中的信息,判断出这个会话是由哪台服务器产生。接着它会将这个请求通过内网转发给相应的那台服务器去处理。这样相当于就实现了J2EE集群的会话粘滞的功能。简单的说,会话粘滞就是保持一个会话中的多次交互都由一台集群中的服务器处理。这样就不会再产生上述的问题。
3、 前提
集群的服务器间,需要有内网间通信的支持。不同服务器上的报表应用必须是一致的。
1、环境准备
Apache:Apache是http服务器,我们利用其对Tomcat进行负载均衡,下载地址http://httpd.apache.org/download.cgi#apache22,这里使用的版本是Apache HTTP Server 2.0.64;
Tomcat:Tomcat7.0.6;
JK:JK是Tomcat提供给http服务器的插件,这里使用的版本是tomcat-connectors-1.2.37-windows-i386-httpd-2.0.x
2、软件安装
Apache
下载完成之后,直接安装apache,安装完成之后,在浏览器中输入http://localhost/,能够看到下图则说明安装成功:
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/df087f0f8b56ad044e1df35adae10ef85956d0c8.jpg)
3、omcat
解压下载好的tomcat压缩包,复制三分解压好的tomca文件夹,分别重命名为tomcat1,tomcat2,tomcat3。
4、配置过程
Apache配置修改
修改httpd.conf
我的Apache安装在C:\Program Files (x86)\Apache Group\Apache2,找到conf目录下的httpd.conf,在文件的最后一行添加:
include "C:\Program Files (x86)\Apache Group\Apache2\conf\mod_jk.conf"
新建mod_jk.conf文件
在conf目录下新建mod_jk.conf文件,内容如下:
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkMount /*.jsp controller
注:第一行最后的文件名为jk的文件名,根据下载的jk的名字不同而不同。第二行表示指定哪些请求交给tomcat处理,"controller"为在workers.propertise里指定的负载分配控制器名,第三行表示可以进行集群的文件类型,这里写*.jsp表示集群的文件只能是jsp文件,如果不区分文件类型,则直接写成JkMount /* controller即可。
jk
解压下载的jk文件,将里面的so文件复制到Apache安装目录的modules目录下,这里下载的jk文件名为mod_jk.so。
新建并编辑workers.properties文件
在conf文件夹下新建workers.properties,内容如下:
#server
worker.list = controller
#========tomcat1========
worker.tomcat1.port=11009
worker.tomcat1.host=localhost
worker.tomcat1.type=ajp13
worker.tomcat1.lbfactor = 1
#========tomcat2========
worker.tomcat2.port=12009
worker.tomcat2.host=localhost
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor = 1
#========tomcat3========
worker.tomcat3.port=13009
worker.tomcat3.host=localhost
worker.tomcat3.type=ajp13
worker.tomcat3.lbfactor = 1
#========controller,负载均衡控制器========
worker.controller.type=lb
worker.controller.balanced_workers=tomcat1,tomcat2,tomcat3
worker.controller.sticky_session=false
worker.controller.sticky_session_force=1
#worker.controller.sticky_session=1
如果需要配置远程的tomcat服务器的话,只需要将worker.tomcat3.host=localhost中的localhost改为远程服务器的IP地址即可。本次配置都是本地的tomcat,并且在一台机器上,所以端口号都不相同,如果在不同服务器上,端口号则不需要更改。
5、Tomcat配置
前面已经将tomcat复制了三份,修改每一份中的server.xml配置,打开conf/server.xml文件,修改如下图:
tomcat1:
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/50a010f85856d53dce513c5a47d2bb665059cac8.jpg)
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/cd93a566515985407c5fe051b5a23a42a17ac4c8.jpg)
6、tomcat2:
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/3fe32442a07aa010ce46088bbfbb19efa35f3ec9.jpg)
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/18aebc5f0c14c27babf7623a2a46b7b1eff939c9.jpg)
7、tomcat3:
注:由于我这三个tomcat全是本地的,并且在一台服务器上,所以需要修改三种类型的端口号,如果是远程服务器,则只需要修改AJP13的connector的port,其他端口号不需要修改。不论是本地服务器还是远程服务器,AJP13的connector的jvmRoute名称和workers.properties中配置都必须对应。
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/a007a9b1eef97fbd3309d000b74133bad24133c9.jpg)
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/32fbcd41037de1374f03c60ff6c5cf672a5f2ac9.jpg)
8、结果测试
在tomcat下面的项目文件夹中修改web.xml,如这里使用test项目,则修改三个tomcat下面的test项目中的web.xml,在每个web.xml的<display-name>节点后添加新的节点<distributable/>。
在每个test项目文件夹下新建test.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>");
// 如果有新的 Session 属性设置
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.println("<b>Session 列表</b><br>");
System.out.println("============================");
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="test.jsp" method="POST">
名称:<input type=text size=20 name="dataName">
<br>
值:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>
9、session测试
项目部署好之后,启动三个tomcat以及Apache,启动顺序随意,然后再浏览器中输入http://localhost/test/test.jsp,结果如下图:
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/e076d77622bc7dc54612cfec5e460596b91429c9.jpg)
10、刷新页面,如下图:
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/ce26355fd5460596356110633e03c8d247fe25c9.jpg)
11、再次刷新,如下图:
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/b955ead0b503c8d2d78ba3fd498333bf3aef21c9.jpg)
12、多次刷新页面的sessionID看是同一个ID,说明session是复制成功了。那么session中的存储的东西呢,在输入框中分别输入1、1,2、2,3、3后,显示结果如下图:
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/c3c22dbf3bef354fc7cd508d23db574afb321bc9.jpg)
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/51f9aa3ea8db574a6147772fa7f7dfb2dd1917c9.jpg)
![电子表格FineReport教程:[24]集群](https://exp-picture.cdn.bcebos.com/92dd32f7dfb2dc196e59bfa895def4dca13910c9.jpg)
13、节点插拔测试
关闭Tomcat
关闭tomcat3,刷新页面,可以不断访问tomcat1和tomcat2,再关闭tomcat2,只能够访问tomcat1,说明节点关闭时运行正常。
启动tomcat
如果重启Tomcat2,无论怎么刷新,始终访问Tomcat3,无法访问tomcat2,这时利用另外台机器访问页面,发现Tomcat2正常,然后在刷本地页面,又可以访问Tomcat2了。对于每个新来的session,Apache按照节点配置中的lbfactor比重选择访问节点,如果某节点node1不能访问,则寻找下一可访问节点,并且将此node1就在该访问session的访问黑名单中,以后该session的访问直接不考虑node1,即使node1又可以访问了。而新来的session是无黑名单的,如果新的session能够访问到node1了,则会将node1在其他所有session访问的黑名单删除,这样其他session就又能访问node1节点了。经过以上测试,说明Tomcat集群和负载均衡已经实现了。
1、增加配置文件cluster.xml
将配置包resource文件夹下的cluster.xml打开,如果没有cluster.xml,则新建一个,基本内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<ClusterConfig useCluster="true"> //useCluster=”true”表示启用集群配置
<ClusterService>
<ServiceName>A</ServiceName> //给这台服务器取一个区别于其他机器的别名
<ip>192.168.0.1</ip> //这台服务器在内网中的IP地址
<port>8080</port> //报表应用的端口
<WebAppName>WebReport</WebAppName> //报表应用的名称
</ClusterService>
<ClusterService>
<ServiceName>B</ServiceName>
<ip>192.168.0.2</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
</ClusterConfig>
这里的每个ClusterService都是集群中一台服务器的相关信息。配置好后,系统会根据自身的IP和端口号去匹配找到相应的信息。当然也可能会有一些原因导致系统无法正确的匹配找到。这时您可以设置isSelf属性来指定自身的属性。
注:xml文件的第一行<??>前面不能有空格,并且请注意xml文件的编码。
另:xml文件的保存格式是 utf-8 no Bom的格式。一般用写字板打开配置包下的cluster.xml文件,修改保存就可以。
2、示例
例如这个配置文件部署在A服务器下,那么ServiceName为A的那个ClusterService节点后加一个属性 isSelf=”true”,表示下这是本机的信息。如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<ClusterConfig useCluster="true" userShare="true">
<ClusterService isSelf="true"> //A服务器的配置信息,后面增加了属性isSelf=”true”表示本机
<ServiceName>A</ServiceName>
<ip>192.168.0.1</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
<ClusterService> //B服务器的配置信息
<ServiceName>B</ServiceName>
<ip>192.168.0.2</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
</ClusterConfig>
3、ServiceName是为一台服务器取的别名,只是为了区别标记一下。最好简单方便,如A、B、C或者A1、A2等。注意!不能是中文。
IP、PORT、和WebAppName上面的注释中有介绍。
IP是该台服务器内网中的IP,就是其它服务器能与之通信的IP。
Port是报表应用的端口号,假如是部署在tomcat下,那么就是tomcat的端口号,默认是8080.例如我们的内置服务器是8079.
WebAppName是报表应用的名称,我们默认的是WebReport。
那么,B服务器下的cluster.xml的配置信息如下:
<?xml version="1.0" encoding="UTF-8" ?>
<ClusterConfig useCluster="true" userShare="true">
<ClusterService> //A服务器的配置信息
<ServiceName>A</ServiceName>
<ip>192.168.0.1</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
<ClusterService isSelf="true"> //B服务器的配置信息,后面增加了属性isSelf=”true”表示本机
<ServiceName>B</ServiceName>
<ip>192.168.0.2</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
</ClusterConfig>
那么正确的配置结果,就是在A服务器上,假如有浏览器,就能访问到B服务器上的报表应用。这个url中的IP、端口号和web应用名称就是上面配置信息里的。注:xxx.cpt只是举个例子
4、那综上说明,假如集群中多了一台C服务器,给它取个别名就叫C。内网IP是192.168.0.3,装了tomcat,端口默认是8080。报表应用名称也是默认是WebReport。那么服务器下的配置文件,应该如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<ClusterConfig useCluster="true" userShare="true">
<ClusterService>
<ServiceName>A</ServiceName>
<ip>192.168.0.1</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
<ClusterService>
<ServiceName>B</ServiceName>
<ip>192.168.0.2</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
<ClusterService>
<ServiceName>C</ServiceName>
<ip>192.168.0.3</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
</ClusterConfig>
最后,请根据上面的格式,写好cluster.xml文件,且将其拷贝到各服务器的报表应用(WEB-INF\resources)文件夹下。当然,有isSelf属性指定的特定服务器的配置文件,还需保存到相应的服务器路径下。
5、测试配置是否生效
当集群中的服务器都已经按照上述步骤配置好,且重新启动报表应用后,测试各个服务器之间的通讯是否正常。
例如,在A服务器下,先本机测试下报表能否访问,测一张简单的模板就行。能正常访问(ie浏览器可能需要将其localhost或127.0.0.1的本机地址,添加到信任站点中才能显示页面),
上述url地址,其前面的部分,按情况换上相应报表应用的端口号和应用名称。而后,假如本机设置正常,就能看到如下的信息:(以上述A、B两台服务器的配置文件举例)
Cluster is start
SELF:
ServiceName:B
IP:192.168.100.227
PORT:8080
WebAppName:WebReport
Other Server List:
NO1: ServiceName:A = 192.168.100.227:7080/WebReport
------------------------------------------
Test it(op = cluster_test) - RE:
Cluster is start!
Cluster Share is not start!
SELF:
ServiceName:A
IP:192.168.100.227
PORT:7080
WebAppName:WebReport
Other Server List:
NO1: ServiceName:B = 192.168.100.227:8080/WebReport
这样说明,配置生效,A服务器能与B服务器间能够互相通信。再次查看下信息是否有误。
假如显示:Cluster is close!,那说明该机的配置没有生效。请检查配置文件后,重新启动应用,且再次依照上面步骤测试,直至出现上面的结果为止。
假如前面一部分显示是这样:
Cluster is start!
Can not find Own Service Info.
LocalIP:192.168.0.39
LocalPort:8070。
6、说明集群配置了,但系统无法根据自身找到的IP和端口匹配到配置文件中的信息。而系统找到的IP是192.168. 0.39,端口是8070。可能您配置成了192.168.0.38:8080,那系统就找不到相应的节点信息了。当然由于各种原因,可能系统无法拿到正确的IP和端口,这时请您检查后,设置正确的IP和端口后,在相应的ClusterService的节点上加isSelf属性(isSelf=”true”)。
假如,SELF下的信息不正确,或没有信息,也请检查配置文件。
假如,下面列出的其它机器的信息不正确,或有遗漏,也请检查配置信息后,重启报表应用重试。
假如,其它服务器的回应,没有回应OK,例如回应Connection timed out: connect。请检查下那台服务器的配置信息,检查网络连接,ping下那台机器的ip地址,看看是否能ping通。然后查看那台服务器报表应用的端口和应用名称,是否设置正确。
可在浏览器中,输入地址直接在内网中访问下那台机上的报表应用,看看设置的ip、端口号等是否设置正确。修改后,重新启动报表应用,重试。