摘要
Cluster 技术在很多重要应用中都很关键,利用 Cluster 可以保证系统的 高可用性。但往往 Cluster 在很多人眼里都是高不可攀的,认为这是非常 高端的技术。其实不然,你也可以尝试在你的应用内部实现一种相对比较 简单的 Cluster,这种方式对很多中小型的 Web 应用已经足够了。(2004-05-06 10:58:11)
By lanf, 出处:http://www.javaresearch.org/article/showarticle.jsp?column=2&thread=13315
作者: dengkane 转载自Java研究组织
Cluster 技术在很多重要应用中都很关键,利用 Cluster 可以保证系统的
高可用性。但往往 Cluster 在很多人眼里都是高不可攀的,认为这是非常
高端的技术。其实不然,你也可以尝试在你的应用内部实现一种相对比较
简单的 Cluster,这种方式对很多中小型的 Web 应用已经足够了。
这种应用级别的 Cluster 技术一个独特的优势就是你可以不依赖于任何
应用程序服务器,象 Tomcat, WebSphere, WebLogic 等,完全是是自己
应用内部的实现。这样可以实现在混合环境下的 Cluster,比如我们可以
利用一个 Windows 2000 下跑的 Tomcat 和 一个在 Linux 下跑的 WebSphere
组成一个 Cluster。
我们要实现的 Cluster 功能如下:
1.有三台服务器,一台做 Balancer,另外两台做 Application Server;
2.Balancer 可以根据两台 Application Server 的负载情况来分配用户请求;
3.在某台 Application Server down 掉后,Balancer 可以马上知道,并在以后
不再向这个 Application Server 转发用户请求;
4.在启动新的 Application Server 后,Balancer 也可以马上知道,并在以后
会向该 Application Server 转发用户请求;
具体实现方法如下:
首先我们要保证 session 信息能在几台 Application Server 间传递,你的
Web 应用一般都需要用户登录,并保留登录信息在 session 里。如果用户是
在一台 Application Server 上登录的,那再访问另外一台 Application Server
的时候应该怎样判断该用户已在别的服务器上登录过了呢?
我们可以用 Cookie 解决这个问题,但 Cookie 有一个限制,就是 domain,即
你在一台服务器上设置了一个 Cookie 后,只有这台服务器才能访问到这个 Cookie,
其他服务器根本访问不到。我们必须想个办法让其他服务器也能访问到,这是我们
这个 Cluster 实现中的关键点之一。
我们可以这样解决,在一台 App Server 登录后,App Server 先设置一个 Cookie,
然后再发给客户端一个象下面这样的 JSP
<html>
<head>
</head>
<body>
<form action="http://balancer_setcookie_jsp_url" method="POST" name="frmSetCookie">
<input type="hidden" name="cookieValue" value="<%=cookieValue%>">
<input type="hidden" name="redirectURL" value="<%=redirectURL%>">
</form>
<script lnguage="JavaScript">
document.frmSetCookie.submit();
</script>
</body>
</html>
上面这段程序会立即自动提交个 balancer_setcookie_jsp_url 这个在 Balancer 上的
程序,这个程序是这样处理的:
<%
String redirectURL = request.getParameter("redirectURL");
String cookieValue = null;
cookieValue = request.getParameter("cookieValue");
if (cookieValue != null)
{
Cookie c = new Cookie("itman",cookieValue);
c.setPath("/");
response.addCookie(c);
%>
<html>
<head>
</head>
<body>
<script language="JavaScript">
document.location.href = "<%=redirectURL%>";
</script>
</body>
</html>
<%
}
else
{
if (redirectURL != null)
{
response.sendRedirect(redirectURL);
}
else
{
//error handling
}
}
%>
这个 Balancer 上的程序先取到 App Server 传来的 cookieValue 和 redirectURL
这两个参数,然后设一个 Cookie,然后再转回到 redirectURL 所设定的 URL 去,
这样就可以保证 Balancer 也能访问到这个 Cookie 值了。
现在 Balancer 可以取到 App Server 所设的 Cookie 了,下次客户访问过来的
时候就先取到 Cookie 值,然后选择一个负载最少的 App Server 把请求转发过去。
转发过去的时候也是采用上面 App Server 为 Balancer 设 Cookie 的方法,
Balancer 给要转的 App Server 设一个 Cookie,这个 App Server 就可以判断
出该用户是否已登录了。
现在我们已经解决了不同的 App Server 传递登录信息的问题,下面需要处理的是
Balancer 和 App Server 之间的信息交换问题。
每个 App Server 在运行时都需要定时给 Balancer 传递一个 heart-beat,Balancer
上会有个后台线程在实时检测,如果发现那个 App Server 的 heart-beat 已经超时
就去掉它,在以后不再转用户请求过来。
具体实现方式是这样的:
Balancer 上启动一个 RMI Service thread,作为 App Server 注册 heart-beat
信息用,App Server 也会起来一个线程,专门是每隔指定的时间就访问 Balancer
上的 RMI Service 来注册自己。Balancer 会维护一个可用 App Server 的列表,
并记录转发用户请求的次数,这样就可以在下次用户请求过来的时候选择出负载
最低的 App Server 并把请求转过去。
在新起来一台 App Server 后,会立即向 Balancer 注册,这样 Balancer 就会加入
到 App Server 列表中。
在一台 App Server 当掉后,Balancer 收不到它的 heart-beat 就会把它从 App Server
列表中去掉。
这种 Cluster 实现方式是很容易理解的,也很有效,可以有效保证应用的高可用性。