1. 程式人生 > >tomcat session server實現會話綁定

tomcat session server實現會話綁定

tomcat memcached session sticky

tomcat session server

此前已經進行過Tomcat的其他配置信息,這裏不再進行重復的描述,會把重要的地方寫上,不會影響實驗

要想能夠實現追蹤有狀態的web apps,對應的狀態信息,有三種方式

session sticky
session replication cluster
session server

這裏實現session server的實現方式

memcached可以借助於第三方的項目所提供的功能,實現使用memcached保存用戶的session信息,項目稱為MSM,工作方式:
技術分享圖片

例如有兩臺Tomcat主機,Tomcat擁有所謂的會話管理器,PersistentManager和deltaManager。MSM可以引入另外一個Manager,一個新的會話。

會話是靠Tomcat內部的類實現的,因此MSM有新增了一個會話管理器類,這個會話管理器,在管理本地會話時,可以在Tomcat級別,不是應用程序級別,而是Tomcat這個程序級別,把需要管理保存的用戶會話,直接通過memcached協議,連接至memcached存儲系統,予以保存。每一個主機只要配置指定了同樣的位置,就能通過同一個位置,讀取,或者是寫入數據。如果memcached宕機了,所有會話就會丟失,而memcached自身不具備冗余能力,因此就在程序級,實現memcached的冗余,所以支持直接配置兩臺memcached主機,寫數據的時候直接寫兩個節點,讀取的時候,可以只從一個節點讀,另外一個就是熱備。每一個Tomcat都直接寫2個節點,讀的時候只從一個節點讀。如果默認讀的節點1宕機了,另外一臺主機就會轉為主動模式,回頭壞掉的修復了再重新上線。能夠把數據重新拿回來一份,就是客戶端參與從一個節點上讀出來,dump出來,導入到第二個節點上去。這就是MSM

MSM托管在GitHub中

技術分享圖片

在GitHub中搜索:memcached session manager

講述了如何安裝配置和使用MSM
技術分享圖片

支持的系統,Redis和couchbase是後期的事

  • Configure memcached-session-manager as Manager
    • Example for sticky sessions + kryo
    • Example for non-sticky sessions + kryo
    • Example for non-sticky sessions + kryo + Redis
    • Example for non-sticky sessions with couchbase + kryo
    • Example for multiple contexts sharing the same session id

kryo:

Decide which serialization strategy to use 決定使用哪一個序列化的策略

There are several session serialization strategies available, as they are described on SerializationStrategies. The default strategy uses java serialization and is already provided by the memcached-session-manager jar. Other strategies are provided by separate jars, in the section below you‘ll see which jars are required for which strategy.

序列化指的就是數據流式化,Tomcat是對象式編程語言而且是完全面向對象的,所以內部的所有的數據結構,都是對象,包括會話,而對象通常都有特定結構和元數據的,在內存中有結構,利用內存中存儲系統專門去存儲的。這種數據有特別詭異的地方是:

在內存中存好,同步到磁盤上去保存,都得流式化,只要通過網絡傳輸,就一定要拆成0101代碼發送出去,都需要流式化,往磁盤上發送也是一樣,內部總線也是0101發出去的,往磁盤上存儲都需要流式化,網絡發送也要流式化。因此,像這種會話信息,想保存到memcached中,memcached本來就只能存儲流式化數據,第一步就需要把會話流式化,然後才能存下來。流式化就需要流式化的工具,進行輔助實現。對memcached而言,流式化工具有很多

Add custom serializers to your webapp (optional) 定制使用serializers

要想使用Tomcat+MSM,需要的組件:Tomcat、memcached、二者之間加serializers(序列化工具、流式化工具)
流式化工具Tomcat內鍵的已經有可以直接使用,早些時候是必須要添加的,如果不想使用內鍵的,想調用外部的第三方的(可能會有更好的性能),就需要自己去定義

Add custom serializers to your webapp (optional) 添加自動以流式化工具

If you want to use java‘s built in serialization nothing more has to be done. If you want to use a custom serialization strategy (e.g. because of?better performance) this has to be deployed with your webapp so that they‘re available in?WEB-INF/lib/. #類庫的存放位置,把下載的類庫放進去

As msm is available in maven central (under groupId?de.javakaffee.msm) you can just pull it in using the dependency management of your build system. With maven you can use this dependency definition for the kryo-serializer:

<dependency>        #自定義使用流式化工具
    <groupId>de.javakaffee.msm</groupId>
    <artifactId>msm-kryo-serializer</artifactId>
    <version>1.9.7</version>
    <scope>runtime</scope>
</dependency>

For javolution the artifactId is?msm-javolution-serializer, for xstream?msm-xstream-serializerand for flexjson it‘s?msm-flexjson-serializer.

If you‘re not using a dependency management based on maven repositories these are the jars you need for the different serializers:
不同的流式化工具

  • kryo-serializer:?msm-kryo-serializer,?kryo-serializers-0.34+,?kryo-3.x,?minlog,?reflectasm,?asm-5.x,?objenesis-2.x
  • javolution-serializer:?msm-javolution-serializer,?javolution-5.4.3.1
  • xstream-serializer:?msm-xstream-serializer,?xstream,?xmlpull,?xpp3_min
  • flexjson-serializer:?msm-flexjson-serializer,?flexjson
    要放的類庫,這是四款流式化工具,放一個就可以了(下載下來)

如果要使用kryo-serializer,需要把對應的jar文件,下載下來,放到WEB-INF/lib/.目錄中

配置的時候可以使用的模型

Configure memcached-session-manager as?<Context>Manager

  • Example for sticky sessions + kryo
  • Example for non-sticky sessions + kryo
  • Example for non-sticky sessions + kryo + Redis 非粘性會話 + Redis

這裏通過使用Example for sticky sessions + kryo方式進行構建

Example for non-sticky sessions + kryo

The following example shows a configuration for non-sticky sessions. In this case there‘s no need for?failoverNodes, as sessions are served by all tomcats round-robin and they‘re not bound to a single tomcat. For non-sticky sessions the configuration (for both/all tomcats) would look like this:

<Context>
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
    sticky="false"
    sessionBackupAsync="false"
    lockingMode="uriPattern:/path1|/path2"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>

實現使用memcached保存用戶的session信息

版本要是一樣的
[root@server1 /etc/tomcat]# rpm -q tomcat
tomcat-7.0.76-3.el7_4.noarch

[root@server2 /etc/tomcat]# rpm -q tomcat
tomcat-7.0.76-3.el7_4.noarch

準備Tomcat7專用的類

Add memcached-session-manager jars to tomcat
Independent of the chosen serialization strategy you always need the?memcached-session-manager-${version}.jar?and either?memcached-session-manager-tc6-${version}.jar?for tomcat6,?memcached-session-manager-tc7-${version}.jar?for tomcat7 (attention: tomcat 7.0.23+),?memcached-session-manager-tc8-${version}.jar?for tomcat8 or?memcached-session-manager-tc9-${version}.jar?for tomcat9.

If you‘re using memcached, you also need the?spymemcached-${version}.jar. Tested up to v2.12.3.
If you‘re using couchbase, you need additionally these jars:?couchbase-client-1.4.0.jar?jettison-1.3.jar,?commons-codec-1.5.jar,?httpcore-4.3.jar,?httpcore-nio-4.3.jar,?netty-3.5.5.Final.jar.
If you‘re using Redis, you need the?jedis-2.9.0.jar.
Please download the appropriate jars and put them in?$CATALINA_HOME/lib/.

下載和序列化相關的jar文件,因為示例寫的是keyo,不再進行修改,直接使用kryo,也可以修改為其他的流式化工具
kryo-serializer:?msm-kryo-serializer,?kryo-serializers-0.34+,?kryo-3.x,?minlog,?reflectasm,?asm-5.x,?objenesis-2.x
要把下載的jar包放到WEB-INI/lib目錄下

下載各個包完成

查看Tomcat把庫文件存放在什麽位置
[root@server2 /app]# rpm -ql tomcat-lib
/usr/share/java/tomcat

復制主要的jar文件
[root@server2 /app]# cp memcached-session-manager-* pymemcached-2.12.3.jar/usr/share/java/tomcat

把jar包復制到另一臺機器
[root@server2 /app]# scp memcached-session-manager-* spymemcached-2.12.3.jar 192.168.111.102:/usr/share/java/tomcat

*memcached-session-manager- spymemcached-2.12.3.jar 是必須的jar包**

查看
[root@server2 /app]# ls /usr/share/java/tomcat

修改配置文件的配置,根據配置文件中的說明配置session manager

修改配置文件的配置,根據配置文件中的說明配置session manager

<Context>Manager
作為<Context>內部使用的Manager,也就意味著丟到<Context>內部
<Context>是定義application的

Configure memcached-session-manager as?<Context>Manager

Example for sticky sessions + kryo
The following example shows the configuration of the first tomcat, assuming that it runs on host1, together with memcached "n1". The attribute?failoverNodes="n1"?tells msm to store sessions preferably in memcached "n2" and only store sessions in "n1" (running on the same host/machine) if no other memcached node (here only n2) is available (even if host1 goes down completely, the session is still available in memcached "n2" and could be served by the tomcat on host2). For the second tomcat (on host2) you just need to change the failover node to "n2", so that it prefers the memcached "n1". Everything else should be left unchanged.

<Context>   # contest是定義application的
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    `memcachedNodes`="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
    `failoverNodes`="n1"
    `requestUriIgnorePattern`=".*\.(ico|png|gif|jpg|css|js)$"
    `transcoderFactoryClass`="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>

使用的類是MemcachedBackupSessionManager

  • memcachedNodes 指定memcached的節點

  • n1 是標識,memcached節點的主機名或者IP地址都可

  • failoverNodes 標識n1是什麽,這裏標識備用節點,是故障轉移節點。意味著n2是主節點,把n1當做故障轉移節點

  • requestUriIgnorePattern 如果是這臺主機上的session,就不用保存了,和圖片有關的,cookie、session都沒有用,所以,靜態內容,都進行了忽略

  • transcoderFactoryClass 如果需要把session保存在memcached中,使用什麽序列化工具,這裏使用的是KryoTranscoderFactory,就是剛才下載的一大堆的jar包,被這個指令全部調用完了

這是sticky sessions + kryo形式的

sticky sessions + kryo並不是綁定主機的, 綁定的只是sticky本身,一個用戶訪問的請求,始終是綁定在同一個session上

對於non-sticky session多出的內容

  • sticky="false"

  • sessionBackupAsync="false" session備份使用異步模式是被拒絕的。
  • lockingMode="uriPattern:/path1/path2" 鎖模型為"uriPattern:/path1/path2",使用url進行定義,這個就麻煩了

使用sticky sessions + kryo形式的

[root@server1 /etc/tomcat]# vim server.xml

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
<Context path="/myapp" docBase="myapp" reloadable="" >
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:192.168.111.102:11211,n2:192.168.111.103:11211"
failoverNodes="n1"  故障轉移節點
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" 這些session不進行保存
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>

reloadable=""是否可以重寫,默認沒有定義

復制到另外一個節點上
[root@server1 /etc/tomcat]# scp server.xml 192.168.111.103:/etc/tomcat

準備memcached(就使用本機的不然還需要別的虛擬機)

[root@server1 /etc/tomcat]# systemctl start memcached
[root@server1 /etc/tomcat]# ss -ntl

State       Recv-Q Send-Q     Local Address:Port                    Peer Address:Port              
LISTEN      0      128                    *:11211                              *:*

[root@server2 ~]# yum -y install memcached
[root@server2 ~]# systemctl start memcached
[root@server2 ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 :11211 :*

啟動Tomcat

[root@server1 /etc/tomcat]# systemctl start tomcat
[root@server1 /etc/tomcat]# systemctl status tomcat
● tomcat.service - Apache Tomcat Web Application Container
Loaded: loaded (/usr/lib/systemd/system/tomcat.service; disabled; vendor preset: disabled)
Active: active (running)

[root@server2 /app]# systemctl start tomcat

訪問(可以訪問主頁面,無法訪問myapp)
http://192.168.111.102:8080/

把所有的jar包復制到tomcat的jab目錄中
[root@server2 /app]# cp * /usr/share/java/tomcat/
cp: overwrite ‘/usr/share/java/tomcat/memcached-session-manager-2.3.0.jar’? y
cp: overwrite ‘/usr/share/java/tomcat/memcached-session-manager-tc7-2.3.0.jar’? y
cp: overwrite ‘/usr/share/java/tomcat/spymemcached-2.12.3.jar’? y

[root@server2 /app]# systemctl restart tomcat

訪問
技術分享圖片

把jar包復制到目錄中訪問,正常

把所有的包都扔進目錄中
[root@server2 /app]# scp * 192.168.111.102:/usr/share/java/tomcat/
[root@server1 /etc/tomcat]# systemctl restart tomcat

查看前端代理配置
[root@localhost /etc/nginx]# vim nginx.conf

http {
        upstream tcsrvs{
                server 192.168.111.102:8080;
                server 192.168.111.103:8080;
        }

    server {
        location / {
                proxy_pass http://tcsrvs;
                index index.jsp index.html;
        }

訪問前端代理
技術分享圖片

做了session sticky,刷新,主機會變,但是session信息不會變。
但頁面信息確實是對應的主機提供的服務。

這就是session sticky

如果是下載的rpm包的方式安裝的Tomcat,需要把對應的jar包放在/usr/local/tomcat/lib 目錄中

把jar包扔進去以後,就可以使用msm的session-manager

修改配置文件使用session-manager,放在context或者host中
多數情況下session管理是分應用程序單獨管理的,所以把它放在配置文件的contest中,而後啟動Tomcat就可以了

宕機memcached看會不會執行
[root@server2 /app]# systemctl stop memcached

刷新
技術分享圖片

所以,可以實現故障轉移了

現在把memcached啟動起來
[root@server2 /app]# systemctl start memcached

每一次轉移,換一個節點,都是有成本的,所以是不會移來移去的,除非定義了failed back

故障轉移有兩個蓋面,fill lower,自己故障了,轉到備用節點上去,原來的節點重新上線以後,無論備用節點壞還是不壞,都要回來,這叫fill back。如果沒有定義fill back,就意味著轉過去之後,至於對方壞了才會轉回來。過去之後,自己就是備用的了,重新轉回來的時候自己才是主。

這就是講到的session server

memcached沒有持久功能,如果停電,所有的session就全沒了。這是很悲劇的。所以,建議使用Redis,做session server

If you‘re using Redis, you need the?jedis-2.9.0.jar.

Example for non-sticky sessions + kryo + Redis
The following example shows a configuration which uses a Redis server at the URL "redis.example.com" for session storage for non-sticky sessions. Here the configuration (for both/all tomcats) would look like this:

<Context>
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="redis://redis.example.com"
    sticky="false"
    sessionBackupAsync="false"
    lockingMode="uriPattern:/path1|/path2"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>

其他的信息都不變,換jar包就行了。

redis支持主從,所以這裏沒有備用。

配置redis以主從模式工作就沒問題。

這裏使用主機名的好處是,使用主機名,萬一主節點宕機了,redis會自動切換另外一個節點成為主節點,但是IP變了怎麽辦?要麽使用vip提供服務,去轉移vip,要麽是使用主機名解析它,修改解析記錄。使用keepalived要好一點。

tomcat session server實現會話綁定