tomcat负载均衡与会话

tomcat负载均衡

nginx

1)在docker上创建两个tomcat容器

[root@ydong ~]# docker run --name tomcat -d --hostname ydong.com -v /data/ydong:/usr/local/ydong tomcat:9.0.37-jdk8-openjdk-slim-buster 

[root@ydong ~]# docker run --name tomcat2 -d --hostname ydong.com -v /data/ydong2:/usr/local/ydong tomcat:9.0.37-jdk8-openjdk-slim-buster

2)为两个容器准备网页

[root@ydong data]# ls ydong/ROOT/
class  index.jsp  lib  WEB-INF、

[root@ydong data]# ls ydong2/ROOT/
class  index.jsp  lib  WEB-INF


# 两个是同样的目录,但是index.jsp不一样

3)将存储卷中的文件直接复制到webapps目录下

[root@ydong data]# docker exec -it tomcat /bin/bash
root@ydong:/usr/local/tomcat# cp -r ../ydong/ROOT webapps

[root@ydong data]# docker exec -it tomcat2 /bin/bash
root@ydong:/usr/local/tomcat# cp -r ../ydong/ROOT webapps

4)测试访问界面
在这里插入图片描述

在这里插入图片描述

5)利用nginx反代,nginx和docker在同一主机上

upstream tcservs {
    
    
         server 172.17.0.2:8080;
         server 172.17.0.3:8080;
      }

location / {
    
    
             proxy_pass http://tcservs;
          }

#添加上以上规则,由于是测试,所以没设置权重和关闭了长连接以及它的proxy_cache相关选项

第一次访问
在这里插入图片描述
刷新访问

在这里插入图片描述

httpd

httpd反代用到了它的proxy modules。
示例:

vim /etc/httpd/conf.d/tomcat.conf
<proxy balancer://tcsrvs>
                    BalancerMember http://172.17.0.2:8080 loadfactor=1   
                    # loadfactor 权重
                    BalancerMember http://172.17.0.3:8080 loadfactor=1
                    ProxySet lbmethod=byrequests
                    #lbmethod:访问方式,byrequests 加权轮询
               </Proxy>

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

会话保持

会话粘性

nginx

nginx的session sticky 有几种方式

  • ip_hash
  • hash key

nginx直接在nginx.conf里修改

简单示例:

 upstream tcservs{
    
    
        ip_hash;
        server 172.17.0.2:8080;
        server 172.17.0.3:8080;
    }


        location / {
    
    
          proxy_pass http://tcservs;
        }

根据源地址hash,只要是源地址访问的都发送同一个后端服务器上

一致性hash示例:

 upstream tcservs{
    
    
        hash $request_uri consistent;
        server 172.17.0.2:8080;
        server 172.17.0.3:8080;
    }

 location / {
    
    
          proxy_pass http://tcservs;
        } 

绑定请求的uri,只要访问同一个uri,都发送到后端同一个服务器上。

httpd

httpd实现session sticky的话,需要借助cookie

示例:

Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED

<proxy balancer://tcsrvs>
                    BalancerMember http://172.17.0.2:8080  route=TomcatA  loadfactor=1
                    BalancerMember http://172.17.0.3:8080  route=TomcatB  loadfactor=1
                    ProxySet lbmethod=byrequests
		    ProxySet stickysession=ROUTEID	               
</Proxy>

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

第一次访问
在这里插入图片描述
第二次访问
在这里插入图片描述

在保持会话的时候,tomcat的server.xml文件需要添加一项JVMRoute选项。这个选项功能主要是

jvm_route的原理(from 作者 Weibin Yao):

  1. 一开始请求过来,没有带session信息,jvm_route就根据round robin的方法,发到一台tomcat上面。
  2. tomcat添加上session 信息,并返回给客户。
  3. 用户再此请求,jvm_route看到session中有后端服务器的名称,它就把请求转到对应的服务器上。

暂时jvm_route模块还不支持默认fair的模式。jvm_route的工作模式和fair是冲突的。对于某个特定用户,当一直为他服务的tomcat宕机后,默认情况下它会重试max_fails的次数,如果还是失败,就重新启用round
robin的方式,而这种情况下就会导致用户的session丢失。

总的说来,jvm_route是通过session_cookie这种方式来实现session粘性,将特定会话附属到特定tomcat上,从而解决session不同步问题,但无法解决宕机后会话转移问题。
转自:http://blog.163.com/momoliu88@126/blog/static/139208463201231104120587/

从httpd可以看出,请求报文头部带有TomcatB,后端服务器看到TomcatB的时候,tomcat中的cluster会根据对应的JVMRoute来进行响应。

tomcat session replication cluster

tomcat具有会话复制的功能、在tomcat的集群内,每个节点的会话都会同步到集群中每个节点的服务器内。这个功能是由tomcat中DeltaManager(集群增量会话管理器)实现的。

示例
以下的需要写在server.xml上的engine或者host中。 engine表示所有主机,host表示指定主机。

<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.192.131"   #此处是绑定地址,最高绑定在服务的ip地址上
                      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>

上述完成之后,还需要在web.xml中添加<distributable/>元素。 而且web.xml复制到WEB-INF下。

前面反代和上边没有区别,nginx和httpd,HAproxy都可以。

测试
在这里插入图片描述

在这里插入图片描述

可以看到,内容不同,但是会话一直存在

猜你喜欢

转载自blog.csdn.net/qq_44564366/article/details/107946536