tomcat-session共享实战案例

实战案例

环境准备:

  • 时间同步,确保NTP或Chrony服务正常运行。
  • 防火墙规则
  • 禁用SELinux
  • 五台主机
IP 主机名 服务
10.0.0.100 proxy 调度器 Nginx、HTTPD
10.0.0.101 t1 tomcat1 JDK8、Tomcat8
10.0.0.102 t2 tomcat2 JDK8、Tomcat8
10.0.0.103 m1 memcached1 memcached
10.0.0.104 m2 memcached2 memcached
  • 准备proxy主机的配置,利用nginx作为反向代理
[root@proxy ~]#cat /etc/nginx/nginx.conf
http {
......
upstream tomcat-server {
        #ip_hash; 
        server t1.magedu.org:8080;
        server t2.magedu.org:8080;
}
    server {
......
        location / {
        }
        location ~* /.(jsp|do)$ {
            proxy_pass http://tomcat-server;
        }

[root@proxy ~]#cat /etc/hosts
10.0.0.100 proxy.magedu.org proxy
10.0.0.101 t1.magedu.org t1
10.0.0.102 t2.magedu.org t2
  • 在10.0.0.101和102上准备tomcat,并安装和配置memcached的客户
[root@t1 tomcat]#vim conf/server.xml
  <Engine name="Catalina" defaultHost="t1.magedu.org" jvmRoute="Tomcat1">  
  ......
       <Host name="t1.magedu.org" appBase="/data/webapps" autoDeploy="true" > 
     </Host>  
    </Engine>
  </Service>
</Server>

[root@t1 tomcat]#vim conf/context.xml
<Context>
......
    <Manager pathname="" />
    -->
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:10.0.0.103:11211,n2:10.0.0.104:11211"                                 failoverNodes="n1"
    requestUriIgnorePattern=".*/.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
</Context>

#将相关包传到lib/目录下
asm-5.2.jar
kryo-3.0.3.jar
kryo-serializers-0.45.jar
memcached-session-manager-2.3.2.jar
memcached-session-manager-tc8-2.3.2.jar
minlog-1.3.1.jar
msm-kryo-serializer-2.3.2.jar
objenesis-2.6.jar
reflectasm-1.11.9.jar
spymemcached-2.12.3.jar

[root@t1 tomcat]#ls lib/ -t |tail 
kryo-3.0.3.jar
asm-5.2.jar
objenesis-2.6.jar
reflectasm-1.11.9.jar
minlog-1.3.1.jar
kryo-serializers-0.45.jar
msm-kryo-serializer-2.3.2.jar
memcached-session-manager-tc8-2.3.2.jar
spymemcached-2.12.3.jar
memcached-session-manager-2.3.2.jar

[root@t1 tomcat]#cat /data/webapps/ROOT/index.jsp 
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>lbjsptest</title>
</head>
<body>
<div>On  <%=request.getServerName() %></div>
<div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div>
<div>SessionID = <span style="color:blue"><%=session.getId() %></span></div>
<%=new Date()%>
</body>
</html>

#t2参考上面t1做配置
  • 在m1和m2上分别配置memcached
#m1的配置
[root@m1 ~]#dnf -y install memcached 
[root@m1 ~]#vim /etc/sysconfig/memcached 
[root@m1 ~]#cat  /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
#OPTIONS="-l 127.0.0.1,::1"
OPTIONS=""
[root@m1 ~]#systemctl start memcached.service 

#安装python3环境
[root@m1 ~]#dnf -y install python3
[root@m1 ~]#pip3 install python-memcached
[root@m1 ~]#cat showmemcached.py 

import memcache # pip install python-memcached

mc = memcache.Client(['10.0.0.103:11211'], debug=True)

stats = mc.get_stats()[0]
print(stats)
for k,v in stats[1].items():
    print(k, v)

print('-' * 30)
# 查看全部key
print(mc.get_stats('items')) # stats items 返回 items:5:number 1
print('-' * 30)
print(mc.get_stats('cachedump 5 0')) # stats cachedump 5 0 # 5和上面的items返回的值有关;0表示全部

#m2的配置
[root@m2 ~]#dnf -y install memcached 
[root@m2 ~]#vim /etc/sysconfig/memcached 
[root@m2 ~]#cat  /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
#OPTIONS="-l 127.0.0.1,::1"
OPTIONS=""
[root@m2 ~]#systemctl start memcached.service 

#安装python3环境
[root@m2 ~]#dnf -y install python3
[root@m2 ~]#pip3 install python-memcached
[root@m2 ~]#cat showmemcached.py 

import memcache # pip install python-memcached

mc = memcache.Client(['10.0.0.104:11211'], debug=True)

stats = mc.get_stats()[0]
print(stats)
for k,v in stats[1].items():
    print(k, v)

print('-' * 30)
# 查看全部key
print(mc.get_stats('items')) # stats items 返回 items:5:number 1
print('-' * 30)
print(mc.get_stats('cachedump 5 0')) # stats cachedump 5 0 # 5和上面的items返回的值有关;0表示全部
  • 查看结果,刷新浏览器可以看到SessionID前面部分不变

tomcat-session共享实战案例插图
tomcat-session共享实战案例插图(1)

#上面结果表示SessionID 保存到了m2的memcached主机上,可以执行python脚本验证
[root@m1 ~]#python3 showmemcached.py 
------------------------------
[('10.0.0.103:11211 (1)', {'items:5:number': '1', 'items:5:number_hot': '0', 'items:5:number_warm': '0', 'items:5:number_cold': '1', 'items:5:age_hot': '0', 'items:5:age_warm': '0', 'items:5:age': '14', 'items:5:evicted': '0', 'items:5:evicted_nonzero': '0', 'items:5:evicted_time': '0', 'items:5:outofmemory': '0', 'items:5:tailrepairs': '0', 'items:5:reclaimed': '0', 'items:5:expired_unfetched': '0', 'items:5:evicted_unfetched': '0', 'items:5:evicted_active': '0', 'items:5:crawler_reclaimed': '0', 'items:5:crawler_items_checked': '0', 'items:5:lrutail_reflocked': '0', 'items:5:moves_to_cold': '1', 'items:5:moves_to_warm': '0', 'items:5:moves_within_lru': '0', 'items:5:direct_reclaims': '0', 'items:5:hits_to_hot': '0', 'items:5:hits_to_warm': '0', 'items:5:hits_to_cold': '0', 'items:5:hits_to_temp': '0'})]
------------------------------
[('10.0.0.103:11211 (1)', {'59A4BE74A69C70F56FA5A01D5191F6D3-n1.Tomcat2': '[97 b; 1581605764 s]'})]

[root@m2 ~]#python3 showmemcached.py
------------------------------
[('10.0.0.104:11211 (1)', {})]
------------------------------
[('10.0.0.104:11211 (1)', {})]

停止t2和m2的服务,再观察结果

[root@t2 ~]#systemctl stop tomcat
[root@m2 ~]#systemctl stop memcached.service 

tomcat-session共享实战案例插图(2)

non-sticky模式
原理

从msm 1.4.0之后开始支持non-sticky模式。

Tomcat session为中转Session,n1为主session,n2为备session。产生的新的Session会发送给主、备memcached,并清除本地Session。

n1下线,n2转正。n1再次上线,n2依然是主Session存储节点。

memcached配置(问题)

放到 $CATALINA_HOME/conf/context.xml

<Context>
  ...
  <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:10.0.0.101:11211,n2:10.0.0.102: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>
redis配置

下载jedis.jar,放到$CATALINA_HOME/lib/,对应本次安装就是/usr/local/tomcat/lib。

# yum install redis
# vim /etc/redis.conf
bind 0.0.0.0

# systemctl start redis

放到 $CATALINA_HOME/conf/context.xml

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

浏览器访问,使用redis相关工具可以观察到redis中的信息

tomcat-session共享实战案例插图(3)
tomcat-session共享实战案例插图(4)

总结

通过多组实验,使用不同技术实现了session持久机制

  1. session绑定,基于IP或session cookie的。其部署简单,尤其基于session黏性的方式,粒度小,对负载均衡影响小。但一旦后端服务器有故障,其上的session丢失。
  2. session复制集群,基于tomcat实现多个服务器内共享同步所有session。此方法可以保证任意一台后端服务器故障,其余各服务器上还都存有全部session,对业务无影响。但是它基于多播实现心跳,TCP单播实现复制,当设备节点过多,这种复制机制不是很好的解决方案。且并发连接多的时候,单机上的所有session占据的内存空间非常巨大,甚至耗尽内存。
  3. session服务器,将所有的session存储到一个共享的内存空间中,使用多个冗余节点保存session,这样做到session存储服务器的高可用,且占据业务服务器内存较小。是一种比较好的解决session持久的解决方案。

以上的方法都有其适用性。生产环境中,应根据实际需要合理选择。

不过以上这些方法都是在内存中实现了session的保持,可以使用数据库或者文件系统,把session数据存储起来,持久化。这样服务器重启后,也可以重新恢复session数据。不过session数据是有时效性的,是否需要这样做,视情况而定。

本文链接:http://www.yunweipai.com/35198.html

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/52752.html

(0)
上一篇 2021年8月6日
下一篇 2021年8月6日

相关推荐

发表回复

登录后才能评论