`
touchmm
  • 浏览: 999261 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Windows 2003 Server 网络负载均衡 + Tomcat 5.0 集群

阅读更多

标题:Windows 2003 Server 网络负载均衡 + Tomcat 5.0 集群

关键字:负载平衡 集群 Tomcat Session共享

作者:JRQ

链接:http://blog.csdn.net/jrq/archive/2006/08/26/1124685.aspx

摘要:在网络上摘抄的资料基础上整理而成。仅作备忘。


正文:


一、设置Windows 网络负载均衡(Load Balance)

以本地 Administrators 组成员身份登录计算机才能完成此过程。

1.在前端网络接口卡 (NIC) 上设置静态 IP。要这样做,请执行下列操作:

1.1.单击“开始”,指向“控制面板”,再单击“网络连接”。

1.2.用鼠标右键单击“前端 NIC”,再单击“属性”。

1.3.在“此连接使用下列选定的组件”区域中,选中“Internet 协议 (TCP/IP)”复选框。

1.4.单击“属性”。

1.5.选中“使用下列 IP 地址”。

1.5.1.在“IP 地址”框中,键入分配的前端静态 IP: 100.100.100.150。

1.5.2.如果需要,在“子网掩码”框中,键入分配的前端子网掩码:255.255.255.0。

1.5.3.如果需要,在“默认网关”框中,键入分配的前端网关:100.100.100.243。

1.6.选中“使用下列 DNS 服务器地址”。

1.7.在“首选 DNS 服务器”和“备用 DNS 服务器”框中,键入适当的 IP:100.100.100.6和100.100.100.7。

1.8.单击“高级”。

1.9.在“IP 设置”选项卡上的“IP 地址”节中,单击“添加”。

1.10.在“IP 地址”框中,键入虚拟 IP 地址:100.100.100.201。

1.11.在“子网掩码”框中,键入子网掩码:255.255.255.0。

1.12.单击“添加”,再单击“确定”。

注释:虚拟 IP 地址是负载平衡的IP 地址,它是指向服务器场的条目。

2.“LAN 连接属性”对话框上的“此连接使用下列选定的组件”区域中,选中“网络负载平衡”复选框。

3.单击“属性”。

4.在“群集参数”选项卡上,执行下列操作:

4.1.在“IP 地址”框中,键入群集 IP :100.100.100.201。

群集 IP 是虚拟 IP 地址,它是指向服务器场的条目。

需要将此 IP 地址映射到 DNS 项,以便可以在 Microsoft Internet Explorer 中键入群集名称,而不用键入 IP 地址。

4.2.在“子网掩码”框中,键入子网掩码:255.255.255.0。

将 IPCONFIG /ALL 报告的此 NIC 的子网掩码用于此 NIC。

4.3.在“完整 Internet 名”框中,键入 DNS 名称:ams.dtsjy.cn。

注释:如果使用了 Microsoft Windows Internet 名称服务 (WINS) 解析,请输入 WINS 名称,无需输入域扩展
例如,应输入 server_farm 而不是 server_farm.organization.com。

4.4.在“群集操作”节中,单击“单播”(默认选项)。

4.5.保留“允许远程控制”复选框为其默认设置(清除)。

5.在“主机参数”选项卡上,执行下列操作:

5.1.在“优先级”框中,对第一台前端 Web 和搜索服务器输入 1,对第二台前端 Web 和搜索服务器输入 2。

5.2.在“专用 IP 配置”区域的“IP 地址”框中,键入初始分配给此前端 NIC 的地址:100.100.100.150。

注释:要为前端 NIC 分配两个 IP 地址。

5.3.在“子网掩码”框中,键入初始分配给此前端 NIC 的子网掩码:255.255.255.0。

5.4.请勿更改“初始主机状态”节中的任何设置。

6.在“端口规则”选项卡上,单击“编辑”。

7.在“筛选模式”节中,单击“多个主机”。

8.在“关系”组中,单击“无”;负载量选择“相等”或输入负载的比例(百分比),可按照“二八”比例分配负载量。

9.单击“确定”,然后再次单击“确定”。

注释:如果显示一个对话框,提示您必须在 TCP/IP 组件中输入新地址,则说明您没有完成之前的所有步骤。

请单击“确定”,然后在继续操作之前执行下列步骤:

9.1.在前端 NIC 的“属性”对话框的“常规”选项卡上,单击“Internet 协议 (TCP/IP)”,再单击“属性”。

9.2.单击“高级”。

9.3.在“IP 设置”选项卡上的“IP 地址”节中,单击“添加”。

9.4.在“IP 地址”框中,键入虚拟 IP 地址:100.100.100.201。

9.5.在“子网掩码”框中,键入子网掩码: 255.255.255.0。

9.6.单击“添加”,再单击“确定”。

10.重新启动服务器。

11.在所有前端 Web 和搜索服务器上重复前面的步骤。请确保更改每一台服务器的优先级设置,使其唯一。

12.测试网络负载平衡:

12.1.打开命令提示符,然后从服务器场之外的客户端计算机 ping 服务器场的虚拟名称。

例如,如果 server_farm 是输入的完整 Internet 名,或者使用了 WINS,则应该键入 ping server_farm。

在本示例中 Server_farm 是虚拟服务器场名称。

12.2.请确认是否收到答复。

如果未收到答复,请使用服务器场的虚拟 IP 地址 ping 服务器场。虚拟 IP 地址是在前面的步骤中指定的群集 IP 地址。

如果未收到答复,请与负责 DNS/WINS、路由和静态 IP 支持的网络操作联系人联系。

12.3.键入 ping virtual_server_farm_name -t。

此命令将执行连续的 ping 操作。

12.4.在第一台前端 Web 和搜索服务器上执行下列操作:

12.4.0.在任务栏上,单击“开始”,指向“控制面板”,再指向“网络连接”,然后单击与网络负载平衡相关的 NIC 的“本地连接”。

12.4.1.在“常规”选项卡上,单击“禁用”。

12.5.在第二台前端 Web 和搜索服务器上执行下列操作:

12.5.0.在任务栏上,单击“开始”,指向“控制面板”,再指向“网络连接”,然后单击与网络负载平衡相关的 NIC 的“本地连接”。

12.5.1.在“常规”选项卡上,单击“禁用”。

12.6.在连续 ping 服务器场的虚拟名称的客户端计算机上,应该会出现一条消息,说明请求超时。

12.7.在第一台前端 Web 和搜索服务器的任务栏上,单击“开始”,指向“控制面板”,再指向“网络连接”。

然后用鼠标右键单击与网络负载平衡相关的 NIC 的“本地连接”,再单击“启用”。

12.8.在连续 ping 服务器场的虚拟名称的客户端计算机上,应该会在 10 秒钟内显示对 ping 的答复。

如果未显示答复,请确认网络负载平衡配置和网络配置是否正确。

12.9.在第一台前端 Web 和搜索服务器上执行下列操作:

12.9.0.在任务栏上,单击“开始”,指向“控制面板”,再指向“网络连接”,然后单击与网络负载平衡相关的 NIC 的“本地连接”。

12.9.1.在“常规”选项卡上,单击“禁用”。

12.10.在连续 ping 服务器场的虚拟名称的客户端计算机上,应该会出现一条消息,说明请求超时。

12.11.在第二台前端 Web 和搜索服务器的任务栏上,单击“开始”,指向“控制面板”,再指向“网络连接”。

然后用鼠标右键单击与网络负载平衡相关的 NIC 的“本地连接”,再单击“启用”。

12.12.在连续 ping 服务器场的虚拟名称的客户端计算机上,应该会在 10 秒钟内显示对 ping 的答复。

如果未显示答复,请确认网络负载平衡配置和网络配置是否正确。

12.13.在第二台前端 Web 和搜索服务器上执行下列操作:

12.13.0.在任务栏上,单击“开始”,指向“控制面板”,再指向“网络连接”,然后单击与网络负载平衡相关的 NIC 的“本地连接”。

12.13.1.在“常规”选项卡上,单击“禁用”。

12.14.在连续 ping 服务器场的虚拟名称的客户端计算机上,应该会出现一条消息,说明请求超时。

12.15.在第一台前端 Web 和搜索服务器的任务栏上,单击“开始”,指向“控制面板”,再指向“网络连接”。

然后用鼠标右键单击与网络负载平衡相关的 NIC 的“本地连接”,再单击“启用”。

12.16.在第二台前端 Web 和搜索服务器的任务栏上,单击“开始”,指向“控制面板”,再指向“网络连接”。

然后用鼠标右键单击与网络负载平衡相关的 NIC 的“本地连接”,再单击“启用”。

12.17.在连续 ping 服务器场的虚拟名称的客户端计算机上,按下 Ctrl+C 中断 ping 循环。


二、设置DNS

设置DNS服务,域名:ams.dtsjy.cn,解析为对应的虚拟 IP :100.100.100.201 。


三、设置服务心跳(HeartBaet)

设置IP和掩码即可。

Web服务心跳之一

IP:192.168.10.1

掩码: 255.255.255.0

Web服务心跳之二

IP:192.168.10.2

掩码: 255.255.255.0


四、设置 Tomcat 5.0 集群

打开 Tomcat 安装目录中的\conf\server.xml 文件,把 Server/Service/Engine/Host 下的 Cluster 结点前后的注释符删除并保存。

注意,在新安装的Tomcat5.0中可找到 Cluster 结点。如果已经在Tomcat的管理程序中设置过Tomcat的连接池,则在server.xml 文件中不会有 Cluster 结点,因为Cluster 结点默认是被注释的,在设置连接池的过程中,系统会自动删除server.xml 文件中的注释内容。

修改后的server.xml,大致成为如下的样子:

--------------

<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
expireSessionsOnShutdown="false"
useDirtyFlag="true">

<Membership
className="org.apache.catalina.cluster.mcast.McastService"
mcastAddr="228.0.0.4"
mcastPort="45564"
mcastFrequency="500"
mcastDropTime="3000"/>

<Receiver
className="org.apache.catalina.cluster.tcp.ReplicationListener"
tcpListenAddress="auto"
tcpListenPort="4001"
tcpSelectorTimeout="100"
tcpThreadCount="6"/>

<Sender
className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
replicationMode="pooled"/>

<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/>
</Cluster>

---------------

此时,mcastAddr的默认值是“228.0.0.4”,修改此值并保存。

对应不同的Web服务器,mcastAddr 为其心跳的IP地址。

Web服务之一: mcastAddr="192.168.10.1"

Web服务之二: mcastAddr="192.168.10.2"

其他内容保持不变。


在 Tomcat 5.0 中对 Cluster 的配置,将使Tomcat群集中能够实现Session的复制,即群集中各个Web服务节点的Session保持一致,实现Session共享。


注:对server.xml中的Cluster的一段文字的翻译:


<!-- Defines a cluster for this node,
By defining this element, means that every manager will be changed.
So when running a cluster, only make sure that you have webapps in there
that need to be clustered and remove the other ones.
A cluster has the following parameters:
为这个结点定义一个群集,通过定义这个元素,意味着每个管理员都将被改变。
因此,当运行一个群集时,只有确认在必须被聚集和移除其他的地方有你的web软件。
一个群集有下面这些参数:

className = the fully qualified name of the cluster class
className = 这个群集类的全限定名

name = a descriptive name for your cluster, can be anything
name = 你的群集的描述名,可以是任何描述

debug = the debug level, higher means more output
debug = 调试级别,更高意味着更多的输出

mcastAddr = the multicast address, has to be the same for all the nodes
mcastAddr = 多播地址,所有的节点都必须有同样的多播地址

mcastPort = the multicast port, has to be the same for all the nodes
mcastPort = 多播端口,对所有的节点都必须有同样的多播端口

mcastBindAddr = bind the multicast socket to a specific address
mcastBindAddr = 绑定多播套接字到一个指定的地址

mcastTTL = the multicast TTL if you want to limit your broadcast
mcastTTL = 多播生存期,如果你想要限制你的广播的话

mcastSoTimeout = the multicast readtimeout
mcastSoTimeout = 多播读取超时

mcastFrequency = the number of milliseconds in between sending a "I'm alive" heartbeat
mcastFrequency = 发送“I'm alive”(我还活着)信息的间隔毫秒数

mcastDropTime = the number a milliseconds before a node is considered "dead" if no heartbeat is received
mcastDropTime = 多长时间没有收到“I'm alive”就将这个节点标识为死节点(单位:毫秒)

tcpThreadCount = the number of threads to handle incoming replication requests, optimal would be the same amount of threads as nodes
tcpThreadCount = 用于处理重复引入请求的线程数,最好是每个节点都有相同的线程数

tcpListenAddress = the listen address (bind address) for TCP cluster request on this host,
in case of multiple ethernet cards.
auto means that address becomes
InetAddress.getLocalHost().getHostAddress()
tcpListenAddress = 在有多块以太网卡的主机上的监听TCP群集请求的地址(绑定地址),
auto意味着地址由InetAddress.getLocalHost().getHostAddress()取得。

tcpListenPort = the tcp listen port
tcpListenPort = tcp监听端口

tcpSelectorTimeout = the timeout (ms) for the Selector.select() method in case the OS
has a wakup bug in java.nio. Set to 0 for no timeout
tcpSelectorTimeout = 在操作系统中有java.nio唤醒错的情况下,使用Selector.select()的超时
毫秒数。设为0则没有超时限制

printToScreen = true means that managers will also print to std.out
printToScreen = true意味着管理员的相关信息也将打印输出到std.out

expireSessionsOnShutdown = true means that
expireSessionsOnShutdown = true 意味着?????

useDirtyFlag = true means that we only replicate a session after setAttribute,removeAttribute has been called.
false means to replicate the session after each request.
false means that replication would work for the following piece of code:
<%
HashMap map = (HashMap)session.getAttribute("map");
map.put("key","value");
%>
useDirtyFlag = true意味着我们只能在调用setAttribute,removeAttribute后才能复制一个会话;
false意味着在每个请求后复制会话。
false意味着复制将以下列代码方式工作:
<%
HashMap map = (HashMap)session.getAttribute("map");
map.put("key","value");
%>

replicationMode = can be either 'pooled', 'synchronous' or 'asynchronous'.
* Pooled means that the replication happens using several sockets in a synchronous way. Ie, the data gets replicated, then the request return. This is the same as the 'synchronous' setting except it uses a pool of sockets, hence it is multithreaded. This is the fastest and safest configuration. To use this, also increase the nr of tcp threads that you have dealing with replication.
* Synchronous means that the thread that executes the request, is also the
thread the replicates the data to the other nodes, and will not return until all
nodes have received the information.
* Asynchronous means that there is a specific 'sender' thread for each cluster node,
so the request thread will queue the replication request into a "smart" queue,
and then return to the client.
The "smart" queue is a queue where when a session is added to the queue, and the same session
already exists in the queue from a previous request, that session will be replaced
in the queue instead of replicating two requests. This almost never happens, unless there is a
large network delay.
replicationMode = 可以是“pooled”、“synchronous”或者“asynchronous”
* Pooled意味着在多个套接字上同步进行复制。例如,先复制数据,然后请求返回。
这与“synchronous”相同,除了它使用一个套接字池,因此,它是多线程的。它是
最快和最高级的设置,使用这个配置也增加了处理复制的tcp线程的域。
* Synchronous指执行请求的线程,它也是向其他节点复制数据的线程,并且直到
所有的节点都己经收到信息后才返回。
* Asynchronous,对每个群集节点而言,这是一个特别的“sender”(发送者)线程,
因此请求线程将复制请求排队到一个小队列中,然后,返回给用户。
这个小队列是一个当会话被添加到队列中,而从先前的请求中,同一个会话己经存在
,这个会话将被放置在队列中以代替重复的两个请求。这几乎从不会发生,除非存在
较大的网络延迟。
-->
<!--
When configuring for clustering, you also add in a valve to catch all the requests
coming in, at the end of the request, the session may or may not be replicated.
A session is replicated if and only if all the conditions are met:
1. useDirtyFlag is true or setAttribute or removeAttribute has been called AND
2. a session exists (has been created)
3. the request is not trapped by the "filter" attribute

The filter attribute is to filter out requests that could not modify the session,
hence we don't replicate the session after the end of this request.
The filter is negative, ie, anything you put in the filter, you mean to filter out,
ie, no replication will be done on requests that match one of the filters.
The filter attribute is delimited by ;, so you can't escape out ; even if you wanted to.

filter=".*\.gif;.*\.js;" means that we will not replicate the session after requests with the URI
ending with .gif and .js are intercepted.
-->
<!-- 当配置群集时,你也添加一个值来捕获所有传入的请求,在请求结束时,这个会话可能被子复制,
也可能不被复制。一个会话是否复制取决于下列条件是否发生:
1. useDirtyFlag为真,或者setAttribute或者removeAttribute己经被调用。
2. 会话己经存在(己经被创建了)。
3. 请求没有被“filter”属性所捕获。

这个filter(过滤器)属性用于过滤那些不能修改会话的请求,因此,我们在这个请求结束后不复制
会主。这个过滤器是消极的,例如,你向过滤器发送了一些东西,然后被过滤出去,在那个匹配的过
滤器上不会发生复制。
过滤器属性以分号为分隔,因此你不能换行,即使你想这么做。

filter=".*\.gif;.*\.js;"意味着在进行以.gif和.js结束的URI请求后不复制会话。

五、启动Web服务

当 Load Balance 和 Cluster 配置完毕,可启动Web服务。

启动Web服务,需按照在 Load Balance 中设置的“优先级”顺序,依次启动Tomcat服务。

主服务启动时,Tomcat控制台会输出大致如下的信息:

---------------

Creating ClusterManager for context /thams using class org.apache.catalina.cluster.session.DeltaManager

- Starting clustering manager...:/thams
- Manager[/thams], skipping state transfer. No members active in cluster group.

---------------

次级服务启动时,Tomcat控制台会输出大致如下的信息:

---------------

Creating ClusterManager for context /thams using class org.apache.catalina.cluster.session.DeltaManager

- Starting clustering manager...:/thams
- Manager[/thams], requesting session state from org.apache.catalina.cluster.mcast.McastMember
[tcp://192.168.10.1:4001,192.168.10.1,4001, alive=20500]. This operation will timeout if no session state
has been received within 60 seconds
- Manager[/thams], session state received in 109 ms.

---------------


六、测试

可以使用如下代码做测试:

-------------

<%@ page contentType="text/html; charset=GBK" pageEncoding="GBK"
import="java.util.Enumeration"%>

<html>
<head>
<title>Cluster App Test</title>
</head>

<body>
服务器信息: <%out.print(request.getLocalAddr() + " : " + request.getLocalPort());%>
<BR>
<BR>

<%
out.println("Session ID = " + session.getId());

// 如果有新的 Session 属性设置
String dataName = request.getParameter("dataName");

if (dataName != null && dataName.length() > 0)
{
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
%>
<BR>
<BR>

<%

out.print("<b>Session 列表如下:</b><BR>");

Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( "<BR>"+name + " = " + value);
}
%>
<form action="index.jsp" method="POST">
名称:<input type=text size=20 name="dataName">
<br>
<BR>
值:<input type=text size=20 name="dataValue">
<br>
<BR>
<input type=submit>
</form>
</body>
</html>

---------------

测试操作如下:

在 IE 中打开第一个Web服务的测试页面,在 Form 里随便设置一个 Session 属性提交,然后把 IE 地址栏中的地址修改为第二个Web服务的测试页面,刷新,就可以看到 Session ID 不变,Session的属性列表中的值同前一个页面显示的。

同样,如果在第二Web服务的测试页面中设置Session的值,在第一个第一个Web服务的测试页面中也能看到。

注意:必须在同一个 IE 窗口中进行如上测试,以保证是同一个 Session ,如果是两个窗口,则 Session 可能不同,也互相看不到 Session 复制的结果。

[-- 完 --]


by JRQ

2006/08/26夜 于湘西怀化


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics