session sticky + session cluster 实战

前言

在做负载均衡集群的时候,如果后端是应用服务器,我们就有一个不得不考虑的一个问题:会话绑定。为了追踪会话,我们常见的有三种方式:
(1)session sticky:会话粘性,常见有2种方式:

  • source_ip:采用源地址绑定方式

    • nginx:ip_hash,ip地址哈希

    • haproxy:source

    • lvs:sh,源地址哈希

  • cookie:基于cookie绑定

    • nginx:hash

    • haproxy:cookie

(2)session cluster:session集群
(3)session server:session服务器,结合memcache或redis。

下面以Tomcat为例,来分别演示一下。

Tomcat Session Cluster结合httpd作为反代有如下三种实现方式:

    Tomcat Cluster
        (1) httpd + tomcat cluster
            httpd: mod_proxy, mod_proxy_http, mod_proxy_balancer
            tomcat cluster:http connector
        (2) httpd + tomcat cluster
            httpd: mod_proxy, mod_proxy_ajp, mod_proxy_balancer
            tomcat cluster:ajp connector
        (3) httpd + tomcat cluster
            httpd: mod_jk
            tomcat cluster:ajp connector

session sticky + session cluster 实战

实验步骤

在node3和node4上安装部署tomcat

[root@node3 ~]# yum install java-1.8.0-openjdk-devel tomcat-lib.noarch tomcat-admin-webapps.noarch tomcat-webapps.noarch -y

创建测试页面:

[root@node4 ~]# mkdir -pv /usr/share/tomcat/webapps/test/{WEB-INF,lib,classes}
mkdir: created directory ‘/usr/share/tomcat/webapps/test’
mkdir: created directory ‘/usr/share/tomcat/webapps/test/WEB-INF’
mkdir: created directory ‘/usr/share/tomcat/webapps/test/lib’
mkdir: created directory ‘/usr/share/tomcat/webapps/test/classes’
[root@node4 ~]#

为了演示效果,node3上测试页面内容如下:

<%@ page language="java" %>
    <html>
        <head><title>Tomcat:Node3</title></head>
        <body>
            <h1><font color="red">Tomcat:Node3</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>

为了演示效果,node4上测试页面内容如下:

<%@ page language="java" %>
    <html>
        <head><title>Tomcat:Node4</title></head>
        <body>
            <h1><font color="blue">Tomcat:Node4</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>

启动tomcat,访问测试:

session sticky + session cluster 实战

session sticky + session cluster 实战

1)用nginx反代:session sticky(ip_hash)的实现

在node2上安装nginx,配置:

在/etc/nginx/nginx.conf中的http上下文中定义服务器组

upstream tcsrvs {
        server 172.16.47.103:8080;
        server 172.16.47.104:8080;
    }

在/etc/nginx/conf.d/default.conf中使用代理

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

启动nginx,浏览器访问node2的ip:

session sticky + session cluster 实战

可以看到,负载均衡功能已经实现了,但是Session ID一直在变,session绑定问题还没决解决。

要想基于session sticky绑定,我们可以做ip_hash,在upstream段中加入ip_hash,再来访问:

session sticky + session cluster 实战

可以看到,session id一直保持不变,会话绑定的问题解决了,但是用户也被绑定到一台主机上了。

停掉nginx,在node2上安装httpd:yum install httpd -y

配置httpd,让其负载均衡node3和node4,要用到mod Proxy balancer模块,要确保该模块存在,可以使用httpd -M,查看

<proxy balancer://tcsrvs>
    BalancerMember http://172.16.47.103:8080
    BalancerMember http://172.16.47.104:8080
    ProxySet lbmethod=byrequests
</Proxy>

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

启动httpd,访问node2,可以看到,同nginx一样,实现了负载均衡,但是session问题没解决

session sticky + session cluster 实战

要实现会话的绑定,修改配置如下:

Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED   
<proxy balancer://tcsrvs>
    BalancerMember http://172.16.47.103:8080 route=Tomcatnode3 loadfactor=1 
    BalancerMember http://172.16.47.104:8080 route=Tomcatnode4 loadfactor=2 
    ProxySet lbmethod=byrequests
    ProxySet stickysession=ROUTEID  
</Proxy>

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

可以看到会话被绑定了。如果要是用ajp的话,只需要把http改为ajp就可以,但是要确保ajp模块被加载。

session sticky + session cluster 实战

另外,proxy balancer有一个web管理界面,类似于tomcat的gui界面,如果要启用的话,需要加入以下配置:

<Location /balancer-manager>
     SetHandler balancer-manager
     ProxyPass !
     Require all granted
</Location>

session sticky + session cluster 实战

使用session sticky会有很多问题,它是通过把会话与主机绑定来实现会话保持的,但如果某一台主机挂了,该主机上用户的session也就丢失了,所以我们可以采用session cluster来保存用户会话。

3)session cluster

正常情况下,session信息是保存在用户所访问的服务器上的,服务器挂了,用户的session也就丢失了,但是我们可以通过session cluster的方式来实现将用户的session信息保存在后端的所有服务器上,这样,无论用户的请求被调度至哪一台服务器,session都不会丢失。

四种常见的session manager

  • StandardManager:

  • PersistentManager: 可以将session信息保存在持久存储中

  • DeltaManager: 将session信息通过多播的形式共享到其他节点

  • BackupManager: 将session信息共享到特定的一个节点上

我们使用DeltaManager方式来配置:

以下配置可以放在host中,也可以放在engine中,生效范围不同

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

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"
                   mapSendOptions="6"/>
          <!--
                         <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.47.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="172.16.47.104"
                      port="5000"
                      selectorTimeout="100"
                      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"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
          </Channel>

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

          <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 name="Catalina" defaultHost="localhost" jvmRoute="Tomcatnode4" >,这个jvmRoute必须得配置

然后执行如下操作,注意,node3,4上都要执行。

[root@node4 /usr/share/tomcat/webapps]# cp /etc/tomcat/web.xml test/WEB-INF/

vim test/WEB-INF/web.xml ,加入如下配置。
<distributable/>

重启tomcat,通过日志tail -f /var/log/tomcat/catalina.2017-02-09.log ,可以看到cluster的工作过程,这里就不截图了

利用上面nginx的配置,不过要去掉ip_hash,我们启动nginx,然后浏览器访问:

session sticky + session cluster 实战

可以看到被调度到不同主机上了,但是Session ID一直没有变,这样,我们就实现了session cluster的功能。

总结

这篇文章实现了tomcat session 保持的各种方法,但是实际上这些方式用的并不多,试想当后端tomcat服务器很多的情况下,它们要一直多播通信,在用户高并发的情况下,很可能会造成网络拥堵。所以在实际生产环境中的解决方法是做session server,我们下篇文章再演示。

原创文章,作者:Lurker,如若转载,请注明出处:http://www.178linux.com/68266

(1)
LurkerLurker
上一篇 2017-02-13 11:30
下一篇 2017-02-13 15:12

相关推荐

  • Linux磁盘管理详解

    linux磁盘管理 添加磁盘步骤: fdisk 管理磁盘分区 格式化文件系统。 设备挂载 开机自动挂载 UUID挂载 取消挂载点 Parted(gpt大于2G分区) 查看文件系统的使用情况。 df 查看挂载信息与磁盘使用量 du 查看使用量 查看分区状况lsblk 查看设备信息blkid linux磁盘管理 当全新安装了一块新的硬盘设备后,为了更充分、安全的…

    Linux干货 2016-09-07
  • Nginx基本使用方法及各模块基本功能

    一、Nginx介绍     Nginx是由俄罗斯软件工程师Igor Sysoev开发的一个高性能的HTTP和反向代理服务器,具备IMAP/POP3和SMTP服务器功能,Nginx最大的特点是对高并发的支持和高效的负载均衡,在高并发的需求场景下,是Apache服务器不错的替代品。目前,包括新浪、腾讯等知名网站都已使用Nginx作为Web应用…

    Linux干货 2016-01-21
  • Linux基础 & bash基础特性

    Q1:描述计算机的组成及其功能。 计算机的组成:运算器、控制器、存储设备、输入设备、输出设备。 运算器: 运算器是计算机中执行各种算术和逻辑运算操作的部件。运算器的基本操作包括加、减、乘、除四则运算,与、或、非、异或等逻辑操作,以及移位、比较和传送等操作,亦称算术逻辑部件。 存储设备: 计算机总是需要记录与读取数据的,而这些数据当然不可能每次都由用户经过键盘…

    Linux干货 2016-10-30
  • 马哥教育网络班21期+第六周课程练习

    请详细总结vim编辑器的使用并完成以下练习题 1、复制/etc/rc.d/rc.sysinit文件至/tmp目录,将/tmp/rc.sysinit文件中的以至少一个空白字符开头的行的行首加#;  ~]# cp /etc/rc.d/rc.sysinit /tmp/  ~]# vim /tmp…

    Linux干货 2016-08-22
  • 行编辑器sed

    行编辑器sed   Sed,grep,awk命令被称为文本编辑三剑客,目前学习了grep命令,sed命令 自我觉得sed命令更强大,排名第一,grep暂居第二,awk没学不太清楚。   这次的博客写一下刚学习的sed命令,grep命令是全局搜索剪切,sed命令则是逐行进行处理,它一次处理一行内容。Sed命令有两个空间,…

    2017-08-26
  • NET25-第7周作业

    1、创建一个10G分区,并格式为ext4文件系统; (1) 要求其block大小为2048, 预留空间百分比为2, 卷标为MYDATA, 默认挂载属性包含acl; [root@node1 ~]# fdisk /dev/sdb Device contains neither a valid DOS partition table, nor Sun, SGI o…

    Linux干货 2017-03-15