一、Apache反向代理介绍
Apache可以通过mod_jk和mod_proxy模块跟Tomcat整合,mod_proxy只能在apache 2.2.x系列的版本才能直接提供,它可以提供更丰富的功能和安全性;而对于apache1.3.x和2.0.x来说mod_jk才更合适,这俩种方式都可以使用tomcat内置的ajp和http类型的连接器来实现apache代理tomcat集群。
二、实验的环境:
192.168.30.116 OS:Centos6.4 x86_64 apache.luojianlong.com
192.168.30.117 OS:Centos6.4 x86_64 TomcatA.luojianlong.com
192.168.30.119 OS:Centos6.4 x86_64 TomcatB.luojianlong.com
Apache versrion: httpd-2.4.6
Tomcat version: apache-tomcat-7.0.53
拓扑图如下:
三、使用apache的mod_jk来实现反向代理
首先在apache.luojianlong.com上编译安装apache
# 安装apr和apr-util [root@apache ~]# tar xvf apr-1.4.6.tar.bz2 [root@apache ~]# cd apr-1.4.6 [root@apache apr-1.4.6]# ./configure --prefix=/usr/local/apr --disable-ipv6 # 如果报错rm: cannot remove `libtoolT‘: No such file or directory # 直接打开 configure,把 $RM “$cfgfile” 那行删除掉,重新再运行 # ./configure 就可以了 [root@apache apr-1.4.6]# make && make install [root@apache ~]# tar xvf apr-util-1.5.2.tar.bz2 [root@apache ~]# cd apr-util-1.5.2 [root@apache apr-util-1.5.2]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr [root@apache apr-util-1.5.2]# make && make install # 安装apache [root@apache ~]# tar xvf httpd-2.4.6.tar.bz2 [root@apache ~]# cd httpd-2.4.6 [root@apache httpd-2.4.6]# ./configure --prefix=/usr/local/apache > --sysconfdir=/etc/httpd > --enable-so > --enable-ssl > --enable-cgi > --enable-rewrite > --with-zlib > --with-pcre > --with-apr=/usr/local/apr > --with-apr-util=/usr/local/apr-util > --enable-mpms-shared=all > --with-mpm=event > --enable-proxy > --enable-proxy-http > --enable-proxy-ajp > --enable-proxy-balancer > --enable-lbmethod-heartbeat > --enable-heartbeat > --enable-slotmem-shm > --enable-slotmem-plain > --enable-watchdog [root@apache httpd-2.4.6]# make && make install [root@apache ~]# vi /etc/httpd/httpd.conf # 编辑配置文件取消下面的这一行的注释 LoadModule slotmem_shm_module modules/mod_slotmem_shm.so [root@apache ~]# /usr/local/apache/bin/apachectl start [root@apache ~]# ps aux | grep apache root 18345 0.0 0.0 105796 2336 ? Ss 16:59 0:00 /usr/local/apache/bin/httpd -k start daemon 18346 0.2 0.1 450056 4384 ? Sl 16:59 0:00 /usr/local/apache/bin/httpd -k start daemon 18347 0.0 0.1 450056 4384 ? Sl 16:59 0:00 /usr/local/apache/bin/httpd -k start daemon 18348 0.2 0.1 450056 4392 ? Sl 16:59 0:00 /usr/local/apache/bin/httpd -k start
在2台tomcat上面安装tomcat
# 首先安装配置jdk环境 [root@TomcatA ~]# tar zxvf jdk-7u25-linux-x64.gz -C /usr/local/ [root@TomcatA local]# ln -s jdk1.7.0_25 jdk [root@TomcatA ~]# vi /etc/profile.d/jdk.sh export JAVA_HOME=/usr/local/jdk export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib export PATH=/usr/local/jdk/bin:$PATH [root@TomcatA ~]# . /etc/profile.d/jdk.sh [root@TomcatA ~]# java -version java version "1.7.0_25" Java(TM) SE Runtime Environment (build 1.7.0_25-b15) Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode) # 安装配置tomcat [root@TomcatA ~]# tar zxvf apache-tomcat-7.0.53.tar.gz -C /usr/local/ [root@TomcatA ~]# cd /usr/local/ [root@TomcatA local]# ln -s apache-tomcat-7.0.53 tomcat [root@TomcatA ~]# vi /etc/profile.d/tomcat.sh export CATALINA_HOME=/usr/local/tomcat export PATH=/usr/local/tomcat/bin:$PATH [root@TomcatA ~]# . /etc/profile.d/tomcat.sh [root@TomcatA ~]# catalina.sh start Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/jdk Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Tomcat started. [root@TomcatA ~]# jps 18724 Bootstrap 18744 Jps [root@TomcatA ~]# ss -antpl | grep :8080 LISTEN 0 100 :::8080 :::* users:(("java",18724,42)) [root@TomcatA ~]# scp -pr jdk-7u25-linux-x64.gz apache-tomcat-7.0.53.tar.gz root@192.168.30.119:/root/ # TomcatB上同样上面的步骤安装jdk和tomcat
访问都正常
[root@TomcatA ~]# curl -I http://192.168.30.117:8080 HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/html;charset=ISO-8859-1 Transfer-Encoding: chunked Date: Fri, 04 Apr 2014 09:35:50 GMT [root@TomcatA ~]# curl -I http://192.168.30.119:8080 HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/html;charset=ISO-8859-1 Transfer-Encoding: chunked Date: Fri, 04 Apr 2014 09:36:45 GMT
配置基于mod_jk的负载均衡
修改Tomcat配置文件,添加Host标签,创建项目加载的类库文件夹,并为每一个Tomcat实例的引擎添加jvmRoute参数,并通过其为当前引擎设置全局惟一标识符,需要注意的是,每一个实例的jvmRoute的值均不能相同。
# 为每一个Tomcat实例的引擎添加jvmRoute参数,并通过其为当前引擎设置全局惟一标识符,需要注意的是,每一个实例的jvmRoute的值均不能相同。 [root@TomcatA ~]# vi /usr/local/tomcat/conf/server.xml # 添加以下内容 <Engine name="Catalina" defaultHost="192.168.30.117" jvmRoute="TomcatA"> <Host name="192.168.30.117" appBase="/tomcat/web" unpackWARs="true" autoDeploy="true"> <Context path="" docBase="/tomcat/web"/> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="www_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> [root@TomcatA ~]# mkdir /tomcat/web/WEB-INF/classes -p [root@TomcatA ~]# mkdir /tomcat/web/WEB-INF/lib -p
为了方便后面的测试,为2台服务器分别建立index.jsp测试页
[root@TomcatA ~]# cd /tomcat/web/ [root@TomcatA web]# vi index.jsp <%@ page language="java" %> <html> <head><title>TomcatA</title></head> <body> <h1><font color="red">TomcatA </font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("abc","abc"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html> [root@TomcatA ~]# catalina.sh stop Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/jdk Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar [root@TomcatA ~]# catalina.sh start Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/jdk Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Tomcat started. [root@TomcatA ~]# curl http://192.168.30.117:8080/index.jsp <html> <head><title>TomcatA</title></head> <body> <h1><font color="red">TomcatA </font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <td>AB5025287773B482327CF6F5D982389F.TomcatA</td> </tr> <tr> <td>Created on</td> <td>1396605416275</td> </tr> </table> </body> </html>
将配置文件和项目目录发送到TomcatB服务器,然后修改
[root@TomcatA ~]# scp -pr /usr/local/tomcat/conf/server.xml root@192.168.30.119:/usr/local/tomcat/conf/ [root@TomcatA ~]# scp -pr /tomcat/ root@192.168.30.119:/ [root@TomcatB ~]# cd /usr/local/tomcat/conf/ [root@TomcatB conf]# vi server.xml # 将Engine标签中的defaulthost的值改为192.168.30.119,jvmRoute的值改为TomcatB,Host标签中的name的值改为192.168.30.119,jvmRoute的值改为TomcatB
为TomcatB建立测试页面
[root@TomcatB ~]# cd /tomcat/web/ [root@TomcatB web]# vi index.jsp <%@ page language="java" %> <html> <head><title>TomcatB</title></head> <body> <h1><font color="blue">TomcatB </font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("abc","abc"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html> [root@TomcatB ~]# catalina.sh stop Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/jdk Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar [root@TomcatB ~]# catalina.sh start Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/jdk Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Tomcat started. [root@TomcatB ~]# curl http://192.168.30.119:8080/index.jsp <html> <head><title>TomcatB</title></head> <body> <h1><font color="blue">TomcatB </font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <td>9F9DAF404E0EDDE92AD63400A4ED8283.TomcatA</td> </tr> <tr> <td>Created on</td> <td>1396605796342</td> </tr> </table> </body> </html>
配置apache通过mod_jk模块与Tomcat连接,mod_jk是ASF的一个项目,是一个工作于apache端基于AJP协议与Tomcat通信的连接器,它是apache的一个模块,是AJP协议的客户端(服务端是Tomcat的AJP连接器)。
[root@apache ~]# tar zxvf tomcat-connectors-1.2.37-src.tar.gz [root@apache ~]# cd tomcat-connectors-1.2.37-src/native [root@apache native]# ./configure --with-apxs=/usr/local/apache/bin/apxs [root@apache native]# make && make install
apache要使用mod_jk连接器,需要在启动时加载此连接器模块,为了便于管理与mod_jk模块相关的配置,这里使用一个专门的配置文件/etc/httpd/extra/httpd-jk.conf来保存相关指令及其设置。其内容如下:
[root@apache ~]# vi /etc/httpd/extra/httpd-jk.conf LoadModule jk_module modules/mod_jk.so JkWorkersFile /etc/httpd/extra/workers.properties JkLogFile logs/mod_jk.log JkLogLevel debug JkMount /* lbcluster1 JkMount /jkstatus/ stat1
编辑/etc/httpd/extra/workers.properties,添加如下内容:
[root@apache ~]# vi /etc/httpd/extra/workers.properties worker.list = lbcluster1,stat1 worker.TomcatA.type = ajp13 worker.TomcatA.host = 192.168.30.117 worker.TomcatA.port = 8009 worker.TomcatA.lbfactor = 5 worker.TomcatB.type = ajp13 worker.TomcatB.host = 192.168.30.119 worker.TomcatB.port = 8009 worker.TomcatB.lbfactor = 5 worker.lbcluster1.type = lb worker.lbcluster1.sticky_session = 1 worker.lbcluster1.balance_workers = TomcatA, TomcatB worker.stat1.type = status
对于apache代理来说,每一个后端的Tomcat实例中的engine都可以视作一个worker,而每一个worker的地址、连接器的端口等信息都需要在apache端指定以便apache可以识别并使用这些worker。约定俗成,配置这些信息的文件通常为workers.properties,其具体路径则是使用前面介绍过的JkWorkersFile指定的,在apache启动时,mod_jk会扫描此文件获取每一个worker的配置信息。比如,我们这里使用/etc/httpd/extra/workers.properties。
workers.properties文件一般由两类指令组成:一是mod_jk可以连接的各worker名称列表,二是每一个worker的属性配置信息。它们分别遵循如下使用语法。
worker.list = < a comma separated list of worker names >
worker. <worker name> .<property> = <property value>
其中worker.list指令可以重复指定多次,而worker name则是Tomcat中engine组件jvmRoute参数的值。如:
worker.TomcatA.host=172.16.100.1
根据其工作机制的不同,worker有多种不同的类型,这是需要为每个worker定义的一项属性woker.<work name>.type。常见的类型如下:
ajp13:此类型表示当前worker为一个运行着的Tomcat实例。
lb:lb即load balancing,专用于负载均衡场景中的woker;此worker并不真正负责处理用户请求,而是将用户请求调度给其它类型为ajp13的worker。
status:用户显示分布式环境中各实际worker工作状态的特殊worker,它不处理任何请求,也不关联到任何实际工作的worker实例。具体示例如请参见后文中的配置。
worker其它常见的属性说明:
host:Tomcat 7的worker实例所在的主机;
port:Tomcat 7实例上AJP1.3连接器的端口;
connection_pool_minsize:最少要保存在连接池中的连接的个数;默认为pool_size/2;
connection_pool_timeout:连接池中连接的超时时长;
mount:由当前worker提供的context路径,如果有多个则使用空格格开;此属性可以由JkMount指令替代;
retries:错误发生时的重试次数;
socket_timeout:mod_jk等待worker响应的时长,默认为0,即无限等待;
socket_keepalive:是否启用keep alive的功能,1表示启用,0表示禁用;
lbfactor:worker的权重,可以在负载均衡的应用场景中为worker定义此属性;
另外,在负载均衡模式中,专用的属性还有:
balance_workers:用于负载均衡模式中的各worker的名称列表,需要注意的是,出现在此处的worker名称一定不能在任何worker.list属性列表中定义过,并且worker.list属性中定义的worker名字必须包含负载均衡worker。具体示例请参见后文中的定义。
method:可以设定为R、T或B;默认为R,即根据请求的个数进行调度;T表示根据已经发送给worker的实际流量大小进行调度;B表示根据实际负载情况进行调度。
sticky_session:在将某请求调度至某worker后,源于此址的所有后续请求都将直接调度至此worker,实现将用户session与某worker绑定。默认为值为1,即启用此功能。如果后端的各worker之间支持session复制,则可以将此属性值设为0
除了需要使用LoadModule指令在apache中装载模块外,mod_jk还需要在apache的主配置文件中设置其它一些指令来配置其工作属性。如JkWorkersFile则用于指定保存了worker相关工作属性定义的配置文件,JkLogFile则用于指定mod_jk模块的日志文件,JkLogLevel则可用于指定日志的级别(info, error, debug),此外还可以使用JkRequestLogFormat自定义日志信息格式。而JkMount(格式: JkMount <URL to match> <Tomcat worker name>)指定则用于控制URL与Tomcat workers的对应关系。
为了让apache能使用/etc/httpd/extra/httpd-jk.conf配置文件中的配置信息,需要编辑/etc/httpd/httpd.conf,添加如下一行:
[root@apache ~]# vi /etc/httpd/httpd.conf # 添加 Include /etc/httpd/extra/httpd-jk.conf [root@apache ~]# /usr/local/apache/bin/apachectl -t Syntax OK [root@apache ~]# /usr/local/apache/bin/apachectl restart
测试效果
测试发现,当worker.lbcluster1.sticky_session = 1时,同一个客户端访问始终都是TomcatA的页面
下面修改worker.lbcluster1.sticky_session = 0
[root@apache ~]# vi /etc/httpd/extra/workers.properties worker.lbcluster1.sticky_session = 0 [root@apache ~]# /usr/local/apache/bin/apachectl restart
测试发现,访问请求被平均发送到Tomcat A 和 B
这样就体现出Sticky sessions的意义了。
四、配置apache通过mod_proxy模块与Tomcat连接
要使用mod_proxy与Tomcat实例连接,需要apache已经装载mod_proxy、mod_proxy_http、mod_proxy_ajp和proxy_balancer_module(实现Tomcat集群时用到)等模块:
[root@apache ~]# /usr/local/apache/bin/httpd -D DUMP_MODULES | grep proxy proxy_module (shared) proxy_connect_module (shared) proxy_ftp_module (shared) proxy_http_module (shared) proxy_fcgi_module (shared) proxy_scgi_module (shared) proxy_wstunnel_module (shared) proxy_ajp_module (shared) proxy_balancer_module (shared) proxy_express_module (shared)
编辑/etc/httpd/extra/mod_proxy.conf
[root@apache ~]# vi /etc/httpd/extra/mod_proxy.conf ProxyVia On ProxyRequests Off ProxyPreserveHost Off <proxy balancer://lbcluster1> BalancerMember ajp://192.168.30.119:8009 loadfactor=10 route=TomcatA BalancerMember ajp://192.168.30.117:8009 loadfactor=10 route=TomcatB ProxySet lbmethod=byrequests </proxy> <Location /balancer-manager> SetHandler balancer-manager Proxypass ! Require all granted </Location> ProxyPass / balancer://lbcluster1/ ProxyPassReverse / balancer://lbcluster1/ <Proxy *> Require all granted </Proxy> # 为了防止前面使用mod_jk模块带来的影响,要注释掉httpd.conf中的 [root@apache ~]# vi /etc/httpd/httpd.conf 注释 Include /etc/httpd/extra/httpd-jk.conf 添加 Include /etc/httpd/extra/mod_proxy.conf [root@apache ~]# /usr/local/apache/bin/apachectl restart
关于如上apache指令的说明:
ProxyPreserveHost {On|Off}:如果启用此功能,代理会将用户请求报文中的Host:行发送给后端的服务器,而不再使用ProxyPass指定的服务器地址。如果想在反向代理中支持虚拟主机,则需要开启此项,否则就无需打开此功能。
ProxyVia {On|Off|Full|Block}:用于控制在http首部是否使用Via:,主要用于在多级代理中控制代理请求的流向。默认为Off,即不启用此功能;On表示每个请求和响应报文均添加Via:;Full表示每个Via:行都会添加当前apache服务器的版本号信息;Block表示每个代理请求报文中的Via:都会被移除。
ProxyRequests {On|Off}:是否开启apache正向代理的功能;启用此项时为了代理http协议必须启用mod_proxy_http模块。同时,如果为apache设置了ProxyPass,则必须将ProxyRequests设置为Off。
ProxyPass [path] !|url [key=value key=value ...]]:将后端服务器某URL与当前服务器的某虚拟路径关联起来作为提供服务的路径,path为当前服务器上的某虚拟路径,url为后端服务器上某URL路径。使用此指令时必须将ProxyRequests的值设置为Off。需要注意的是,如果path以“/”结尾,则对应的url也必须以“/”结尾,反之亦然。
另外,mod_proxy模块在httpd 2.1的版本之后支持与后端服务器的连接池功能,连接在按需创建在可以保存至连接池中以备进一步使用。连接池大小或其它设定可以通过在ProxyPass中使用key=value的方式定义。常用的key如下所示:
min:连接池的最小容量,此值与实际连接个数无关,仅表示连接池最小要初始化的空间大小。
max:连接池的最大容量,每个MPM都有自己独立的容量;都值与MPM本身有关,如Prefork的总是为1,而其它的则取决于ThreadsPerChild指令的值。
loadfactor:用于负载均衡集群配置中,定义对应后端服务器的权重,取值范围为1-100。
retry:当apache将请求发送至后端服务器得到错误响应时等待多长时间以后再重试。单位是秒钟。
如果Proxy指定是以balancer://开头,即用于负载均衡集群时,其还可以接受一些特殊的参数,如下所示:
lbmethod:apache实现负载均衡的调度方法,默认是byrequests,即基于权重将统计请求个数进行调度,bytraffic则执行基于权重的流量计数调度,bybusyness通过考量每个后端服务器的当前负载进行调度。
maxattempts:放弃请求之前实现故障转移的次数,默认为1,其最大值不应该大于总的节点数。
nofailover:取值为On或Off,设置为On时表示后端服务器故障时,用户的session将损坏;因此,在后端服务器不支持session复制时可将其设置为On。
stickysession:调度器的sticky session的名字,根据web程序语言的不同,其值为JSESSIONID或PHPSESSIONID。
上述指令除了能在banlancer://或ProxyPass中设定之外,也可使用ProxySet指令直接进行设置。
打开浏览器测试
发现负载均衡正常,访问监控页面http://192.168.30.116/balancer-manager
可以看到俩个后端节点,工作正常。
到此,Apache使用俩种方式代理tomcat集群已经配置完成。
本文出自 “龍行天下” 博客,请务必保留此出处http://luojianlong.blog.51cto.com/4412415/1390767
Apache反向代理Tomcat集群,布布扣,bubuko.com
原文:http://luojianlong.blog.51cto.com/4412415/1390767