现在的位置: 首页 > 综合 > 正文

Apache和Tomcat 配置负载均衡

2014年09月05日 ⁄ 综合 ⁄ 共 7512字 ⁄ 字号 评论关闭

本文转载自:

http://zyycaesar.iteye.com/blog/294089

http://zyycaesar.iteye.com/blog/295227

并根据自己的操作加上了图片等。在此非常感谢原作者提供了这么好的入门文章!


--------------以下为正文-------------------


一、软件准备

Apache 2.2.25http://httpd.apache.org/download.cgi

下载msi安装程序,选择no ssl版本(httpd-2.2.25-win32-x86-no_ssl.msi)

Tomcat 6.0.39http://tomcat.apache.org/download-60.cgi

下载 apache-tomcat-6.0.39-windows-x86.zip 文件

注意:由于ApacheTomcat项目与集群相关的模块均处于持续发展和优化过程中,因此笔者不保证本文配置方法对所有ApacheTomcat版本均适用。

二、软件安装

Windows下安装Apache(默认端口为80,可自行选择修改),并注册为Windows服务。服务启动后在浏览器中输入http://localhost测试,页面出现"It works!"表示Apache正常工作。

Linux下安装Apache Http Server ,可参考:
http://blog.csdn.net/wangjunjun2008/article/details/38314387


解压tomcatzip文件分别到两个文件夹,命名为tomcat1tomcat2。分别启动tomcat1tomcat2,确保tomcat正常,然后关闭tomcat

本文仅为讲解配置过程,Apachetomcat均工作在同一台机器上;实际部署时没有任何限制,Apachetomcat可部署在不同的服务器上。


三、Apache配置

Apache2.2集成了mod_jk功能,相对于1.3版本,不需要再进行繁琐的worker.properties配置,配置过程大幅简化。

(一)编辑conf/httpd.conf文件,去掉以下文本前的注释符,以便让Apache在启动时自动加载代理模块:

LoadModule proxy_module modules/mod_proxy.so

LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

LoadModule proxy_connect_module modules/mod_proxy_connect.so

LoadModule proxy_ftp_module modules/mod_proxy_ftp.so

LoadModule proxy_http_module modules/mod_proxy_http.so

LoadModule proxy_scgi_module modules/mod_proxy_scgi.so

 

(二)继续向下查找文档,找到<IfModule dir_module>节点(约243行),在DirectoryIndex index.html后加上index.jsp, 这一步只是为了配置完tomcat后能看到小猫首页,可以不做。


(三)继续向下查找文档,找到 #Include conf/extra/httpd-vhosts.conf(473),去掉前面的注释。

 

(四)编辑 ${Apache_Home}/conf/extra/httpd-vhosts.conf 文件,在最下面加上以下代码:

<VirtualHost *:80>

    ServerAdmin test@163.com #管理员邮箱

    ServerName 172.24.2.62 #域名(没有域名则用IP)

    ServerAlias localhost

    ProxyPass / balancer://modjk/ stickysession=jsessionid nofailover=On

    ProxyPassReverse / balancer://modjk

    ErrorLog "logs/modjktest-error.log"

    CustomLog "logs/modjktest-access.log" common

</VirtualHost>

[说明]

”balancer://” 是告诉Apache进行负载均衡的代理, ”modjk” 是集群名(可随意取);

日志引擎ErrorLog负责记录错误,日志文件名任意取;

日志引擎CustomLog负责记录所有的http访问以及返回状态,日志文件名任意取;

 

(五)修改 ${Apache_Home}/conf/httpd.conf 文件,在文档最下面追加以下代码:

ProxyRequests Off
<proxy balancer://modjk
    BalancerMember ajp://127.0.0.1:8090 loadfactor=1 route=jvm1
    BalancerMember ajp://127.0.0.1:8091 loadfactor=1 route=jvm2
</proxy>

[说明]

ProxyRequests Off 是告诉Apache需要使用反向代理;(利用Apache进行负载均衡必须使用反向代理,关于更多负载均衡和反向代理详情可以参阅笔者另一篇博客http://zyycaesar.iteye.com/blog/293839);

<proxy balancer://modjk>配置tomcat集群的节点,其中"modjk"必须与上面的集群名保持一致;

Apache通过ajp协议与tomcat进行通信,IP地址和端口唯一确定了tomcat节点及其ajp端口;

loadfactor是负载因子,Apache会按负载因子的比例分发请求,取值范围是1~100,负载因子越大,对应的tomcat就会处理越多的请求;若两个tomcat都是1,Apache就按1:1的比例分发请求;若是2和1,则按2:1的比例分发请求;

route参数对应tomcat配置中的引擎路径(下面会说明)。

四、Tomcat配置

如果仅仅为了配置一个可用的集群,Tomcat的配置将会非常简单:

分别打开tomcat1tomcat2server.xml配置文件,修改如下标签的端口号(tomcat1tomcat2不在同一台服务器上运行,则无需修改端口):


tomcat1修改如下标签port属性值:

<Server port="8010" shutdown="SHUTDOWN">

<Connector port="8080" protocol="HTTP/1.1" ... redirectPort="8443" />

<Connector port="8090" protocol="AJP/1.3" redirectPort="8443" />

<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>


tomcat2修改如下标签port属性值:

<Server port="8011" shutdown="SHUTDOWN">

<Connector port="8081" protocol="HTTP/1.1" ... redirectPort="8443" />

<Connector port="8091" protocol="AJP/1.3" redirectPort="8443" />

<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm2">

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>


[注意]

AJP协议端口对应${Apache_Home}/conf/httpd.confBalancerMember中配置的ajp连接端口!

Engine 标签增加jvmRoute属性,其值对应${Apache_Home}/conf/httpd.confBalancerMember中配置的route参数!

打开 <Cluster /> 标签的注释,配置的作用是在集群中的所有tomcat节点间共享会话(Session),如果仅仅为了获得一个可用的tomcat集群,则无需打开<Cluster /> 标签。

 

 

server.xml修改完毕,下一步需要对具体的应用进行配置,用于测试分别在tomcat1tomcat2做如下操作:

${Tomcat_Home}/webapps/下新建test目录,test目录下新建test.jsp文件,文件内容为:

<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html>
<head>
</head>
<body>
<%
	out.println("Server IP = " + request.getLocalAddr() + "<br>");
	out.println("Server Port = " + request.getLocalPort() + "<br>");
	out.println("<br>");
	out.println("SessionId = " + session.getId() + "<br>");
	out.println("<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 列表</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="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>

test目录下新建WEB-INF目录,WEB-INF目录下新建web.xml,web.xml文件内容为:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5"> 

	<description>test</description>
</web-app>

[说明]

<distributable />标签的作用是:通知tomcat服务器,当前应用需要在集群中的所有节点间实现Session共享;(如果tomcat中的所有应用都需要Session共享,可以把${Tomcat_Home}/conf/context.xml中的<Context>改为<Context distributable="true">,这样就不需对tomcat下的所有应用的web.xml再进行单独配置

 

启动tomcat1,tomcat2;

访问http://localhost,可以看到小猫页面。

访问http://localhost/test/test.jsp,可以看到包括服务器地址端口SessionId等信息在内的页面,如下图:

[注意]

此处的SessionId与平常的SessionId相比多了”.jvm2”,这里的jvm2 为处理当前请求的tomcat服务器的jvmRoute值,通过该名称可知是集群中的哪个服务器处理了当前请求。

在文本框中输入名称和值,点击按钮,信息就保存到了Session中,并且显示到页面上;不断点击按钮,可以发现输入的信息并未丢失,而且SessionId小数点之前的部分保持不变,而小数点后面的字符不停的变化,表明是由不同的tomcat服务器处理了这些请求,这样就实现了负载均衡,并且集群中的不同节点间可以实现会话的共享。此时如果停止一个tomcat服务器(比如tomcat1),Apache将会自动把后续请求转发到集群中的其他服务器中,重启tomcat1后,Apache会自动侦测到tomcat1的状态为可用,然后会继续在tomcat1和tomcat2间进行负载均衡。

 

如果需要向集群中增加节点,首先需要对tomcat作类似配置,然后修改${Apache_Home}/conf/httpd.conf 文件,增加BalancerMember, 指向新增的tomcat即可。

--------------正文结束-------------------


 

按照作者的描述,一步一步配置,最终实现了负载均衡,但是Session共享却无法实现;其他读者也有遇到类似的问题,从评论中摘抄相关的部分如下:

 

楼 xiejin2008 2009-12-14   引用

我用的tomcat6版本,apache2.2 均衡负载可以实现,点击按钮,后面的jvm1,jvm2不停地的交换显示,但是前面的sessionID总是变化的,所以并没有成功设置成session共享,请求楼主,可能哪个地方存在问题呢?

 

楼 xiejin2008 2009-12-14   引用

楼主刚刚重新测试,下载tomcat5版本,发现tomcat5中是可以是实现session复制的
tomcat1 tomcat2Apache Tomcat Version 6.0.20 
在这样的集群条件下面,均衡负载时可以实现的,但是并没有实现session的共享
tomcat3 tomcat4Apache Tomcat Version 5.5.28 
在这样的集群条件下面,均衡负载时可以实现的,并且可以实现session的共享
发现两个版本的tomcat中 conf/server.xml里面的文件内容不一样 
主要是这段
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster" 
         managerClassName="org.apache.catalina.cluster.session.DeltaManager" 
         expireSessionsOnShutdown="false" 
         useDirtyFlag="true" 
         notifyListenersOnReplication="true"> 
  <Membership className="org.apache.catalina.cluster.mcast.McastService" 
                mcastAddr="228.0.0.4" 
                mcastPort="45564" 
                mcastFrequency="500" 
                mcastDropTime="3000"/> 
  <Receiver ..................... 
以上这段是tomcat5里面的;
以下这段是tomcat6里面的:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> 
仅仅就这一句话,没有那么多详细的配置内容

 

楼 fangin 2010-04-13   引用

我测试的结果是负载均衡可实现。session复制可实现。但现象和楼主描述的有点出入,
sessionid第一次进入页面后就不再变化,小数点前和小数点后都不会变化

 

楼 zah5897 2010-09-27   引用

我的是apache 2.2.16  tomcat 6.0.26按照Lz的配置完全通过,上面说没有配置通过的估计是有些地方配置错了所导致的,我之前也有session不能共享的情况,后来来回找了几遍终于通过了

 

楼 zenghong237 2011-01-11   引用

楼主啊。在一台机器上测试通过,可是当部署在两台机器上的时候session不会共享啊

 

17 楼 一绿青苔 2014-06-14   引用

为什么局域网内可以访问,放到服务器上,配置之后,本机没有问题,其他机器访问就无法访问了,为啥呢?

 

目前仍然未解决该问题.......


PS:有关 Apache和Tomcat集群中,cluster实现原理,可以参考原作者的另一篇博文(Tomcat集群Cluster实现原理剖析)

抱歉!评论已关闭.