Tomcat 相关服务器学习我爱编程

[转][笔记] 6.Tomcat系列之Apache负载均衡请求至

2016-08-13  本文已影响248人  C86guli

转自陈明乾的博客,可能有一定更新。

转原文声明:
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://freeloda.blog.51cto.com/2033581/1301888

一、前言
二、环境准备
三、负载均衡实现
四、DeltaManager实现
五、Nginx实现Tomcat负载均衡

注,操作系统 CnetOS6.8 x86_64

一、前言


本博文中的所有内容是基于上一篇写的,不清楚的博友可以先看一下上一篇博文:http://freeloda.blog.51cto.com/2033581/1301382。在上一篇博文中我们分别用mod_proxy和mod_jk实现了tomcat服务器的反向代理,在这一篇博文中我们要实现tomcat服务器的负载均衡和tomcat集群的会话共享。好了,下面我们就来具体的说一下吧!

二、环境准备


1.实验拓扑

Apache: 192.168.0.171
Tomcat1: 192.168.0.181
Tomcat2: 192.168.0.182

     Apache
        |
       / \
Tomcat1  Tomcat2

2.同步各节点时间

[root@apache ~]# ntpdate 202.120.2.101
[root@tomcat1 ~]# ntpdate 202.120.2.101
[root@tomcat2 ~]# ntpdate 202.120.2.101

3.安装jdk

[root@tomcat2 src]# rpm -ivh jdk-7u40-linux-x64.rpm

4.配置jdk环境变量

[root@tomcat2 java]# vim /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/jdk1.7.0_40
export PATH=$PATH:$JAVA_HOME/bin
[root@tomcat2 java]# java -version
java version "1.7.0_40" 
Java(TM) SE Runtime Environment (build 1.7.0_40-b43) 
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)

5.安装tomcat

[root@tomcat2 src]# tar xf apache-tomcat-7.0.42.tar.gz -C /usr/local/
[root@tomcat2 src]# cd /usr/local/ 
[root@tomcat2 local]# ln -sv apache-tomcat-7.0.42 tomcat 
"tomcat" -> "apache-tomcat-7.0.42" 
[root@tomcat2 local]# cd tomcat/ 
[root@tomcat2 tomcat]# ls 
bin conf lib LICENSE logs NOTICE RELEASE-NOTES RUNNING.txt temp webapps work

6.配置tomcat环境变量

[root@tomcat2 tomcat]# vim /etc/profile.d/tomcat.sh
export CATALINA_HOME=/usr/local/tomcat
export PATH=$PATH:$CATALINA_HOME/bin
[root@tomcat2 tomcat]# . /etc/profile.d/tomcat.sh
[root@tomcat2 tomcat]# catalina.sh version 
Using CATALINA_BASE:  /usr/local/tomcat 
Using CATALINA_HOME:  /usr/local/tomcat 
Using CATALINA_TMPDIR: /usr/local/tomcat/temp 
Using JRE_HOME:    /usr/java/jdk1.7.0_40 
Using CLASSPATH:    /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar 
Server version: Apache Tomcat/7.0.42 
Server built:  Jul 2 2013 08:57:41 
Server number: 7.0.42.0 
OS Name:    Linux 
OS Version:   2.6.32-358.el6.x86_64 
Architecture:  amd64 
JVM Version:  1.7.0_40-b43 
JVM Vendor:   Oracle Corporation

7.为tomcat提供init脚本

root@tomcat2 tomcat]# vim /etc/init.d/tomcat
#!/bin/sh
# Tomcat init script for Linux. 
# 
# chkconfig: 2345 96 14 
# description: The Apache Tomcat servlet/JSP container. 
CATALINA_HOME=/usr/local/tomcat 
export CATALINA_HOME 
# export CATALINA_OPTS="-Xms128m -Xmx256m" 
exec $CATALINA_HOME/bin/catalina.sh $*

下面我们来增加执行权限

[root@tomcat ~]# chmod +x /etc/init.d/tomcat

8.测试一下

[root@tomcat2 tomcat]# service tomcat start
Using CATALINA_BASE:  /usr/local/tomcat 
Using CATALINA_HOME:  /usr/local/tomcat 
Using CATALINA_TMPDIR: /usr/local/tomcat/temp 
Using JRE_HOME:    /usr 
Using CLASSPATH:    /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar 
[root@tomcat2 tomcat]# netstat -ntulp 
Active Internet connections (only servers) 
Proto Recv-Q Send-Q Local Address        Foreign Address       State    PID/Program name
tcp    0   0 0.0.0.0:22         0.0.0.0:*          LISTEN   1042/sshd    
tcp    0   0 127.0.0.1:25        0.0.0.0:*          LISTEN   1119/master   
tcp    0   0 127.0.0.1:6010       0.0.0.0:*          LISTEN   1153/sshd    
tcp    0   0 127.0.0.1:6011       0.0.0.0:*          LISTEN   1262/sshd    
tcp    0   0 :::8080           :::*            LISTEN   1541/java    
tcp    0   0 :::22            :::*            LISTEN   1042/sshd    
tcp    0   0 ::1:25           :::*            LISTEN   1119/master   
tcp    0   0 ::1:6010          :::*            LISTEN   1153/sshd    
tcp    0   0 ::1:6011          :::*            LISTEN   1262/sshd    
tcp    0   0 ::ffff:127.0.0.1:8005    :::*            LISTEN   1541/java    
tcp    0   0 :::8009           :::*            LISTEN   1541/java

用浏览器访问 192.168.0.182:

Snip20160801_15.png

好了,大家可以看到访成功。说明我们的tomcat安装完成,下面我们来配置一下。

9.修改配置文件

[root@tomcat1 ~]# cd /usr/local/tomcat/conf/
[root@tomcat1 conf]# cp server.xml server.xml.bak
[root@tomcat1 conf]# vim server.xml


<Connector port="80" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
               
<Engine name="Catalina" defaultHost="www.test.com" jvmRoute="TomcatB">

<Host name="www.test.com"  appBase="/web"
            unpackWARs="true" autoDeploy="true">
        <Context path="" docBase="webapp" reloadable="true"/>

下面来检查一下配置文件,

[root@tomcat1 conf]# service tomcat configtest
...
INFO: Initializing ProtocolHandler ["http-nio-80"]
Aug 12, 2016 9:24:48 AM org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
INFO: Using a shared selector for servlet write/read
Aug 12, 2016 9:24:48 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-nio-8009"]
Aug 12, 2016 9:24:48 AM org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
INFO: Using a shared selector for servlet write/read
Aug 12, 2016 9:24:48 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 1322 ms

创建虚拟主机文档目录并创建测试文件,

[root@tomcat1 conf]# mkdir -pv /web/webapp
mkdir: 已创建目录 "/web"
mkdir: 已创建目录 "/web/webapp"
[root@tomcat1 conf]# cd /web/webapp
[root@tomcat1 webapp]# vim index.jsp
<%@ page language="java" %>
<html>
 <head><title>TomcatB</title></head>
 <body>
 <h1><font color="blue">TomcatB </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@tomcat1 webapp]# service tomcat start
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
[root@tomcat1 webapp]# ss -ntl
State       Recv-Q Send-Q              Local Address:Port                Peer Address:Port
LISTEN      0      1                ::ffff:127.0.0.1:8005                          :::*
LISTEN      0      100                            :::8009                          :::*
LISTEN      0      100                            :::80                            :::*
LISTEN      0      128                            :::22                            :::*
LISTEN      0      128                             *:22                             *:*
LISTEN      0      100                           ::1:25                            :::*
LISTEN      0      100                     127.0.0.1:25                             *:*
Snip20160812_74.png

好了,到这里我们准备工作就全部完成了,下面我们来配置tomcat的负载均衡。对了,还有个问题得说明一下。有博友会问了,你只配置了tomcat2,拓扑图中有三台机器还有两台你怎么不配置呢,是这样的由于我们实验是接着上一篇博客做的,另外两台机器的配置在上一篇博文中有,不清楚的博友参考一下http://freeloda.blog.51cto.com/2033581/1301382,我这里就不重复说明了。

三、负载均衡实现


两种方式都能实现负载均衡:

1.基于mod_proxy模块实现负载均衡
2.基于mod_jk模块实现负载均衡

下面我们就来分别演示一下,

3.1.基于mod_proxy实现负载均衡


需要的模块:

至少有一种调度算法模块:

以及:

首先这些模块必须存在,其次在配置中开启它们:

查看模块:

[root@vm1 etc]# cd /usr/local/apache/modules/
[root@vm1 modules]# ls | grep mod_proxy
mod_proxy_ajp.so
mod_proxy_balancer.so
mod_proxy_connect.so
mod_proxy_express.so
mod_proxy_fcgi.so
mod_proxy_ftp.so
mod_proxy_hcheck.so
mod_proxy_http.so
mod_proxy_scgi.so
mod_proxy.so
mod_proxy_wstunnel.so

[root@vm1 modules]# ls | grep balancer
mod_proxy_balancer.so
[root@vm1 modules]# ls | grep lbmethod
mod_lbmethod_bybusyness.so
mod_lbmethod_byrequests.so
mod_lbmethod_bytraffic.so
mod_lbmethod_heartbeat.so

在配置中开启模块:

LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so

LoadModule proxy_module modules/mod_proxy.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_fcgi_module modules/mod_proxy_fcgi.so
LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_express_module modules/mod_proxy_express.so
LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so

LoadModule watchdog_module modules/mod_watchdog.so

首先我们来修改一下httpd.conf配置文件,启用httpd-proxy.conf配置文

[root@apache ~]# vim /etc/httpd/httpd.conf


Include /etc/httpd/extra/httpd-proxy.conf
#Include /etc/httpd/extra/httpd-jk.conf

下面我们来修改httpd-proxy.conf配置文件,

[root@vm1 extra]# cat httpd-proxy.conf
ProxyRequests Off
<proxy balancer://lbcluster>
BalancerMember http://192.168.0.181:80 loadfactor=1 route=TomcatA
BalancerMember http://192.168.0.182:80 loadfactor=1 route=TomcatB
#ProxySet lbmethod=byrequests
ProxySet lbmethod=bytraffic
#ProxySet stickysession=JSESSIONID|jsessionid
ProxySet nofailover=On
</proxy>
<VirtualHost *:80>
ServerAdmin admin@test.com
ServerName www.test.com
ProxyPass "/" "balancer://lbcluster/"
ProxyPassReverse "/" "balancer://lbcluster/"
<Proxy *>
Require all granted
</Proxy>
<Location />
Require all granted
</Location>
</VirtualHost>

测试配置:

[root@vm1 extra]# service httpd configtest
Syntax OK

访问 192.168.0.171 测试切换:

Snip20160813_105.png Snip20160813_106.png

测试成功!

关于如上apache指令的说明:

ProxyPreserveHost

{On|Off}:如果启用此功能,代理会将用户请求报文中的Host:行发送给后端的服务器,而不再使用ProxyPass指定的服务器地址。如果想在反向代理中支持虚拟主机,则需要开启此项,否则就无需打开此功能。

ProxyVia

{On|Off|Full|Block}:用于控制在http首部是否使用Via:,主要用于在多级代理中控制代理请求的流向。默认为Off,即不启用此功能;On表示每个请求和响应报文均添加Via:;Full表示每个Via:行都会添加当前apache服务器的版本号信息;Block表示每个代理请求报文中的Via:都会被移除。如下图,

Snip20160812_72.png

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如下所示:

上述指令除了可使用ProxySet指令直接进行设置,也能在banlancer://或ProxyPass中设定之外,具体参考:

http://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypass
http://httpd.apache.org/docs/2.4/mod/mod_proxy_balancer.html

ProxyPassReverse

对 HTTP 响应报文的 URL 进行调整。

用于让 apache 调整HTTP重定向响应报文中的Location、Content-Location及URI首部字段所对应的URL,在反向代理环境中必须使用此指令避免重定向报文绕过proxy服务器。因为 HTTP 重定向到了后端服务器,而后端服务器应该隐藏在反向代理的后面,应该对用户不可见。可参考:

http://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypassreverse

3.2.基于mod_jk实现负载均衡


说明:
为了避免用户直接访问后端Tomcat实例,影响负载均衡的效果,建议在Tomcat 7的各实例上禁用HTTP/1.1连接器。

为每一个Tomcat 7实例的引擎添加jvmRoute参数,并通过其为当前引擎设置全局惟一标识符。如下所示。需要注意的是,每一个实例的jvmRoute的值均不能相同。

<Engine name="Catalina" defaultHost="www.test.com" jvmRoute="TomcatA">

<Engine name="Catalina" defaultHost="www.test.com" jvmRoute="TomcatB">

同样的首先来修改httpd.conf配置文件,

[root@apache ~]# vim /etc/httpd/httpd.conf
#启用httpd-jk.conf

#Include /etc/httpd/extra/httpd-proxy.conf
Include /etc/httpd/extra/httpd-jk.conf

下面我们来修改一下httpd-jk.conf配置文件,

[root@apache ~]# vim /etc/httpd/extra/httpd-jk.conf
LoadModule jk_module modules/mod_jk.so #加载mod_jk模块
JkWorkersFile /etc/httpd/extra/workers.properties #配置文件位置 
JkLogFile logs/mod_jk.log #日志 
JkLogLevel debug #日志级别 
JkMount /* lbcluster #负载均衡器名称 
JkMount /jkstatus/ stat1 #状态信息

接下来,编辑/etc/httpd/extra/workers.properties,添加如下内容:

[root@apache ~]# vim /etc/httpd/extra/workers.properties
worker.list = lbcluster,stat1 #列表信息
worker.TomcatA.type = ajp13 #支持ajp协议 
worker.TomcatA.host = 192.168.0.181 #TomcatA实例IP
worker.TomcatA.port = 8009 #TomcatA实例端口号 
worker.TomcatA.lbfactor = 1 #负载均衡权重为1 
worker.TomcatB.type = ajp13 
worker.TomcatB.host = 192.168.0.182 
worker.TomcatB.port = 8009 
worker.TomcatB.lbfactor = 1 
worker.lbcluster.type = lb #负载均衡work,lb内置的类 
worker.lbcluster.sticky_session = 0 #会话是否绑定 
worker.lbcluster.balance_workers = TomcatA, TomcatB #TomcatA, TomcatB 集群中的实列 
worker.stat1.type = status #状态信息

测试一下配置正确性:

[root@vm1 extra]# service httpd configtest
Syntax OK

访问测试:

Snip20160813_108.png Snip20160813_110.png

测试成功!

再说明一下配置:

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定义的一项属性worker.<work name>.type。常见的类型如下:

3.3.查看两种状态信息


两种状态信息:

(1).基于mod_proxy模块状态信息

首先修改配置文件 /etc/httpd/httpd.conf:

[root@vm1 extra]# vi /etc/httpd/httpd.conf

Include /etc/httpd/extra/httpd-proxy.conf
#Include /etc/httpd/extra/httpd-jk.conf

修改 /etc/httpd/extra/httpd-proxy.conf:

[root@vm1 extra]# vi /etc/httpd/extra/httpd-proxy.conf
ProxyRequests Off
<proxy balancer://lbcluster>
    BalancerMember ajp://192.168.0.181:8009 loadfactor=1 route=TomcatA
    BalancerMember ajp://192.168.0.182:8009 loadfactor=1 route=TomcatB
    ProxySet lbmethod=byrequests
    #ProxySet lbmethod=bytraffic
    #ProxySet stickysession=JSESSIONID|jsessionid
    ProxySet nofailover=On
</proxy>
<VirtualHost *:80>
    ServerAdmin admin@test.com
    ServerName www.test.com
    ProxyPass "/" "balancer://lbcluster/"
    ProxyPassReverse "/" "balancer://lbcluster/"
    <Location /balancer-manager>
        SetHandler balancer-manager
        Proxypass !
        Require all granted
    </Location>
    <Proxy *>
        Require all granted
    </Proxy>
    <Location />
        Require all granted
    </Location>
</VirtualHost>

访问 http://192.168.0.171/balancer-manager 测试:

Snip20160813_112.png

好了,基于的mod_proxy模块状态信息已配置完成,下面我们演示一下基于mod_jk模块的状态信息。

(2).基于mod_jk模块的状态信息

首先修改httpd.conf配置文件,

[root@vm1 extra]# vi /etc/httpd/httpd.conf

#Include /etc/httpd/extra/httpd-proxy.conf
Include /etc/httpd/extra/httpd-jk.conf

重启 httpd:

[root@vm1 extra]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

访问测试:http://192.168.0.171/jkstatus/

Snip20160813_113.png

好了,到这里我们状态信息查看就到这里了,下面我们来配置会话共享集群。

四、DeltaManager实现


1.会话管理

种类:

(1).标准会话管理器(StandardManager):

<Manager className="org.apache.catalina.session.StandardManager" 
     maxInactiveInterval="7200"/>

默认保存于 $CATALINA_HOME/work/Catalina/<hostname>/<webapp-name>/下的 SESSIONS.ser 文件中。

(2).持久会话管理器(PersistentManager):

将会话数据保存至持久存储中,并且能在服务器意外中止后重新启动时重新加载这些会话信息。持久会话管理器支持将会话保存至文件存储(FileStore)或JDBC存储(JDBCStore)中。

保存至文件中的示例:

<Manager className="org.apache.catalina.session.PersistentManager" 
 saveOnRestart="true"> 
 <Store className="org.apache.catalina.session.FileStore" 
  directory="/data/tomcat-sessions"/> 
</Manager>

每个用户的会话会被保存至directory指定的目录中的文件中,文件名为<session id>.session,并通过后台线程每隔一段时间(checkInterval参数定义,默认为60秒)检查一次超时会话。

保存至JDBCStore中的示例:

<Manager className="org.apache.catalina.session.PersistentManager" 
 saveOnRestart="true"> 
 <Store className="org.apache.catalina.session.JDBCStore" 
  driverName="com.mysql.jdbc.Driver" 
  connectionURL="jdbc:mysql://localhost:3306/mydb?user=jb;password=pw"/> 
</Manager>

2.Manager组件

Manger对象用于实现HTTP会话管理的功能,Tomcat中有5种Manger的实现:

(1).StandardManager
Tomcat6的默认会话管理器,用于非集群环境中对单个处于运行状态的Tomcat实例会话进行管理。当Tomcat关闭时,这些会话相关的数据会被写入磁盘上的一个名叫SESSION.ser的文件,并在Tomcat下次启动时读取此文件。

(2).PersistentManager
当一个会话长时间处于空闲状态时会被写入到swap会话对象,这对于内存资源比较吃紧的应用环境来说比较有用。
(3).DeltaManager
用于Tomcat集群的会话管理器,它通过将改变的会话数据同步给集群中的其它节点实现会话复制。这种实现会将所有会话的改变同步给集群中的每一个节点,也是在集群环境中用得最多的一种实现方式。

(4).BackupManager
用于Tomcat集群的会话管理器,与DeltaManager不同的是,某节点会话的改变只会同步给集群中的另一个而非所有节点。

(5).SimpleTcpReplicationManager
Tomcat4时用到的版本,过于老旧了。

3.DeltaManager具体实现过程

(1).修改server.xml配置文件

tomcat1:

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

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="192.168.0.181"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

以上内容定义在Engine容器中,则表示对所有主机均启动用集群功能。如果定义在某Host中,则表示仅对此主机启用集群功能。(注,tomcat1与tomcat2都要修改!),我们这里将内容定义在 Engine 容器中。

tomcat 2:

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

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="192.168.0.182"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

这里使用的是 Tomcat 8.5.4 版本,要做 session 复制,必须做以下的事情:

主要有几点要注意:

(2).修改web.xml

tomcat1:

[root@tomcat1 ~]# cd /web/webapp/
[root@tomcat1 webapp]# ls 
index.jsp 
[root@tomcat1 webapp]# mkdir WEB-INF 
[root@tomcat1 webapp]# ls 
index.jsp WEB-INF 
[root@tomcat1 webapp]# cp /usr/local/tomcat/conf/web.xml WEB-INF/
[root@tomcat1 ~]# vim /usr/local/tomcat/conf/web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">

<distributable/>

tomcat2:

同上

测试配置,重启 tomcat:

service tomcat configtest
service tomcat start

现在我们使用的还是 mod-jk 负载均衡,复习一下这个:

sticky_session:在将某请求调度至某worker后,源于此址的所有后续请求都将直接调度至此worker,实现将用户session与某worker绑定。默认为值为1,即启用此功能。如果后端的各worker之间支持session复制,则可以将此属性值设为0。

我们是设为的0,所以可以直接测试:

Snip20160813_114.png Snip20160813_115.png

大家可以从图中看到,不管你怎么刷新SessionID都不会变,说明我们的Tomcat的DeltaManager集群配置完成,实现了多台主机之间会话共享。

再来试试 mod_proxy 负载均衡,配置如前,

[root@vm1 extra]# vi /etc/httpd/httpd.conf
Include /etc/httpd/extra/httpd-proxy.conf
#Include /etc/httpd/extra/httpd-jk.conf

[root@vm1 extra]# vi /etc/httpd/extra/httpd-proxy.conf
ProxyRequests Off
<proxy balancer://lbcluster>
    BalancerMember ajp://192.168.0.181:8009 loadfactor=1 route=TomcatA
    BalancerMember ajp://192.168.0.182:8009 loadfactor=1 route=TomcatB
    ProxySet lbmethod=byrequests
    #ProxySet lbmethod=bytraffic
    #ProxySet stickysession=JSESSIONID|jsessionid # 不能开启,一旦开启,则不能实现均衡效果
    ProxySet nofailover=On
</proxy>
<VirtualHost *:80>
    ServerAdmin admin@test.com
    ServerName www.test.com
    ProxyPass "/" "balancer://lbcluster/"
    ProxyPassReverse "/" "balancer://lbcluster/"
    <Location /balancer-manager>
        SetHandler balancer-manager
        Proxypass !
        Require all granted
    </Location>
    <Proxy *>
        Require all granted
    </Proxy>
    <Location />
        Require all granted
    </Location>
</VirtualHost>


[root@vm1 extra]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

测试访问:

Snip20160813_114.png Snip20160813_115.png

实现了一样的效果,sessinoID 不管怎么刷新,都不会改变。最后我们来实现一下,Nginx负载均衡Tomcat。

五、Nginx实现Tomcat负载均衡


1.实验拓扑

Nginx: 192.168.0.171
Tomcat1: 192.168.0.181
Tomcat2: 192.168.0.182

      Nginx
        |
       / \
Tomcat1  Tomcat2

2.添加 nginx.repo,使用 yum 安装 nginx:

[root@vm1 ~]# vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

[root@vm1 ~]# yum install nginx

Installed:
  nginx.x86_64 0:1.10.1-1.el6.ngx

3.停止httpd

[root@vm1 ~]# service httpd stop

4.配置nginx负载均衡

[root@vm1 ~]# cat /etc/nginx/conf.d/default.conf
upstream tomcat {
    server 192.168.0.181;
    server 192.168.0.182;
}
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        #root   /usr/share/nginx/html;
        #index  index.html index.htm;
        proxy_pass http://tomcat;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

5.检查配置并启动 nginx

[root@vm1 ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@vm1 ~]# service nginx start
Starting nginx:                                            [  OK  ]
[root@vm1 ~]# ss -ntl
State      Recv-Q Send-Q          Local Address:Port            Peer Address:Port
LISTEN     0      128                         *:80                         *:*
LISTEN     0      128                        :::22                        :::*
LISTEN     0      128                         *:22                         *:*
LISTEN     0      100                       ::1:25                        :::*
LISTEN     0      100                 127.0.0.1:25                         *:*

6.进行测试

Snip20160813_114.png Snip20160813_115.png

好了,到这里Nginx实现tomcat的负载均衡与会话共享配置完成。最后,希望大家有所收获吧,_……

上一篇 下一篇

猜你喜欢

热点阅读