tomcat的负载均衡,会话保持

一台主机nginx做代理,两台tomcat主机做负载均衡
首先两台tomcat主机安装对应的安装包
yum install -y java-1.8.0-openjdk-devel tomcat tomcat-webapps tomcat-admin-webapps tomcat-docs-webapp
修改tomcat_users.xml增加三段,以便使用自带的两个应用

<role rolename="admin-gui"/>
<role rolename="manager-gui"/>
<user name="admin" password="admin" roles="admin-gui,manager-gui"/>

在tomcat服务器上创建一个应用

mkdir -pv /var/lib/tomcat/webapps/test/{WEB-INF,META-INF,calsses,lib}
然后创建应用程序jsp文件
在A主机上

            <%@ page language="java" %>
                    <html>
                        <head><title>TomcatA</title></head>
                        <body>
                            <h1><font color="red">TomcatA.magedu.com</font></h1>
                            <table align="centre" border="1">
                                <tr>
                                    <td>Session ID</td>
                                <% session.setAttribute("magedu.com","magedu.com"); %>
                                    <td><%= session.getId() %></td>
                                </tr>
                                <tr>
                                    <td>Created on</td>
                                    <td><%= session.getCreationTime() %></td>
                                </tr>
                            </table>
                        </body>
                    </html>

在B主机上
            <%@ page language="java" %>
                    <html>
                        <head><title>TomcatB</title></head>
                            <body>
                            <h1><font color="blue">TomcatB.magedu.com</font></h1>
                            <table align="centre" border="1">
                                <tr>
                                    <td>Session ID</td>
                                <% session.setAttribute("magedu.com","magedu.com"); %>
                                    <td><%= session.getId() %></td>
                                </tr>
                                <tr>
                                    <td>Created on</td>
                                    <td><%= session.getCreationTime() %></td>
                                </tr>
                            </table>
                            </body>
                    </html> 

在httpd代理服务器上配置httpd服务

基于httpd的代理
<VirtualHost *:80>
        ServerName  node1.lvqing.com
        ProxyRequests Off #关闭正向代理
        ProxyVia on #是否在响应报文中加via
        ProxyPreserveHost On #是否将请求报文首部一并转给后端
                <Proxy *>
                        Require all granted
                </Proxy>
        ProxyPass / http://192.168.31.200:8080/ #把根反代给指定主机
        ProxyPassReverse / http://192.168.31.200:8080/ #如果后端主机返回重定向>是否让客户端知道
                <Location />
                        Require all granted
                </Location>
</VirtualHost>

访问没有问题

 

13920922-3d7f6e08d9156f6d.png

换一种代理方式ajp代理,使用前可使用httpd -M查看是否启用proxy-ajp模块,没有的话需要手动加载
注意:ajp的代理端口是8009

          <VirtualHost *:80>
                ServerName     node2.lvqing.com             ProxyRequests Off
                ProxyVia        On
                ProxyPreserveHost On
                <Proxy *>
                    Require all granted
                </Proxy>
                    ProxyPass / ajp://192.168.31.200:8009/ 
                    ProxyPassReverse / ajp://192.168.31.200:8009/ 
                <Location />
                    Require all granted
                </Location>
            </VirtualHost>

同样代理到了,ajp代理相对于httpd代理更安全,客户端除非经过代理服务器否则无法与tomcat通信

 

13920922-0a7199553253303d.png

image.png

 

但是前面都没有实现负载均衡的功能,接下来我们来编辑配置
首先是nginx的负载均衡,编辑配置文件添加一段

upstream tcservs {
        hash $request_uri consistent; #使用uri一致性哈希算法保持会话粘性
        #hash $cookie_name consistent 对cookie做哈希也可以
        server 192.168.31.200:8080;
        server 192.168.31.201:8080;
    }
vim /etc/nginx/conf.d/lvqin.conf
server {
        listen 80;
        server_name node1.lvqing.com;

        location / {
                proxy_pass http://tcservs;
        }
}

然后是httpd的负载均衡需要proxy_balancer_module模块
balancer的详细语法可以查看http://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypass

Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
#相当于在cookie中加上ROUTEID以求实现session sticky
如果第一次访问的是tomcatA则下次再访问cookie会被注入route=TomcatA以便绑定
            <proxy balancer://tcsrvs>
                BalancerMember http://172.18.100.67:8080 route=TomcatA loadfactor=1
                BalancerMember http://172.18.100.68:8080 route=TomcatB loadfactor=2
                ProxySet lbmethod=byrequests
                ProxySet stickysession=ROUTEID
            </Proxy>



            <VirtualHost *:80>
                ServerName node1.lvqing.com                     
                ProxyVia On
                ProxyRequests Off
                ProxyPreserveHost On
                <Proxy *>
                    Require all granted
                </Proxy>
                ProxyPass / balancer://tcsrvs/
                ProxyPassReverse / balancer://tcsrvs/
                <Location />
                    Require all granted
                </Location>
             </VirtualHost> 

还可以启用balancer的管理接口

在上面定义的虚拟主机中添加
                <Location /bstatus>
                        SetHandler balancer-manager
                        ProxyPass !
                        Require all granted
                </Location>

可以看到图片

 

13920922-f7b26520e8b63444.png

image.png

然后负载均衡的目的就达到了很简单,难题是如何保持会话,一共三种方式:

会话保持:
       (1) session sticky
           source_ip
               nginx: ip_hash
               haproxy: source
               lvs: sh
           cookie:
               nginx:hash 
               haproxy: cookie
       (2) session cluster:delta session manager
       (3) session server:redis(store), memcached(cache)

tomcat自己支持第二种会话集群的方式内部有一个cluster的组件,但这种方式只适用于较小规模的集群。
编辑两台主机的配置文件server.xml添加cluser组件
注意:cluster组件应当放在host或engine组件中,多播地址应该一致


        <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="225.0.0.4"
                                port="45564"
                                frequency="500"
                                dropTime="3000"/>
                <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                                address="auto"
                                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.MessageDispatch15Interceptor"/>
                </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.JvmRouteSessionIDBinderListener"/>
                <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

这样子我们前端代理的会话绑定就可以取消了
注意:绑定的地址为auto时,会自动解析本地主机名,并解析得出的IP地址作为使用的地址;

需要为test提供一个web.xml配置文件并添加上distribution,属性,意思是为test做分布式会话
因为这个test是我们自己创建的没有web.xml所以复制一个到/var/lib/tomcat/webapps/test/WEB-INF中添加一段<distributable/>
查看TomCatA的日志信息可以发现B已经成问会话集群的成员了

13920922-7df020ad14dd7655.png

image.png


接下来不管我们代理到后端的哪一台主机但session的ID都不会变

 

httpd除了http,ajp还有第三种协议连接jk,但现在已经不怎么使用了,这里实验测试一下安装httpd第三方模块提供服务

得到源码
tar xvf tomcat-connectors-1.2.40-src.tar.gz
./configure --with-apxs=/usr/bin/apxs
安装时需要指定apxs的位置,这个服务是为httpd的第三方模块提供一个接口
make && make install
最后提示我们修改模块的执行权限,照做
chmod 755 /usr/lib64/httpd/modules/mod_jk.so
但现在还不会自动装载进去,需要我们手动编辑一个模块加载文件
vim /etc/httpd/conf.modules.d/mod_jk.conf
loadModule jk_module /usr/lib64/httpd/modules/mod_jk.so

然后我们httpd -M就可以看到这个模块了

 

13920922-b4b25699a0f83fd6.png

image.png

接下来我们实验使用memcache来做第三方会话管理器msm
在两台tomcat主机上安装memcache,然后去网站上下载管理器软件http://repo1.maven.org/maven2/de/javakaffee/msm/
下载后的jar类文件放在tomcat的类文件目录即可
/user/share/java/tomcat
然后修改server.xml文件在host或者context中添加一个manager

<Context path="/var/lib/tomcat/webapps/test" docBase="/var/lib/tomcat/webapps/test" reloadable="true">                                
              <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
                memcachedNodes="n1:192.168.31.200:11211,n2:192.168.31.201:11211"
                failoverNodes="n2"
                requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
                transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
              />
             </Context>
ls
javolution-5.5.1.jar
memcached-session-manager-1.8.2.jar
memcached-session-manager-tc7-1.8.2.jar
msm-javolution-serializer-1.8.2.jar
spymemcached-2.10.2.jar
#全都放在/user/share/java/tomcat文件中
mv *.jar /user/share/java/tomcat

启动tomcat后接下来我们就可以看到实验效果了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值