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.www58058.com/68266

(1)
LurkerLurker
上一篇 2017-02-13
下一篇 2017-02-13

相關推薦

  • 第二周博客作業

    1、Linux上的文件管理類命令都有哪些,其常用的使用方法及其相關示例演示? cat(concatenate)#從頭開始看     文本文件查看工具 SYNOPSIS:     cat [OPTION]… [FILE]… -A 輸出行最后加上$號 -n 輸出行號 例…

    Linux干貨 2016-12-12
  • 啟動流程與內核管理

    centos6和centos5啟動流程與內核管理,啟動過程中遇到的系統不能啟動,各個階段該怎么解決

    Linux干貨 2018-01-02
  • 鏈接分析算法之:HITS算法

     HITS(HITS(Hyperlink – Induced Topic Search) ) 算法是由康奈爾大學( Cornell University ) 的Jon Kleinberg 博士于1997 年首先提出的,為IBM 公司阿爾馬登研究中心( IBM Almaden Research Center) 的名為“CLEVER”的研究…

    開發運維 2015-07-20
  • 如何在微軟Azure云機上添加新磁盤

    大家好: 最近在項目實踐中,分享下如何在微軟Azure云機上添加新磁盤。 首先需要查看下是否有未用上的磁盤,先fdisk -l查(看下圖)并和Azure技術確認該磁盤是否可永久保存數據: 然后找到未分區的磁盤號,如上圖中的/dev/sdc,再 fdisk /dev/sdc后開始在該新磁盤上進行分區創建: 為方便管理,我們一般就創建一個分區,然后進行格式化: …

    Linux干貨 2016-11-27
  • LINUX-初學正則表達式

    正則表達式    簡介       REGEXP:由一類特殊字符及文本字符由一類特殊字符及文本字符所編寫的模式,其中有些字符(元字符)                    不表示字符字面意義,而表示控制或通配…

    2017-06-04
  • 馬哥教育網絡班20期+第2周課程練習

    一、Linux上的文件管理類命令都有哪些,其常用的使用方法及其相關示例演示。     1、cat:用于連接文件并打印到標準輸出設備上,常用來顯示文件的內容         命令使用格式     &nb…

    Linux干貨 2016-06-23
欧美性久久久久