• 实现tomcat及Memcached、redis缓存服务器session共享


    NoSQL

    NoSQL是对非SQL、非传统关系型数据库的统称。

    NoSQL一词诞生于1998年,2009年这个词汇被再次提出指非关系型、分布式、不提供ACID的数据库设计模式。

    随着互联网时代的到来,数据爆发式增长,数据库技术发展日新月异,要适应新的业务需求。

    随着移动互联网、物联网的到来,大数据的技术中NoSQL也同样重要。

    https://db-engines.com/en/ranking

    分类

    Key-value Store

    redis、memcached

    Document Store

    mongodb、CouchDB

    Column Store列存数据库,Column-Oriented DB

    HBase、Cassandra

    Graph DB

    Neo4j

    Time Series 时序数据库

    InfluxDB
    

    Memcached不支持集群,只支持字符串类型、字节流,不支持持久化,不支持buffer缓存,而Redis支持字符串、源地址hash等类型,支持buffer缓存,且支持主从复制、集群、支持持久化等  

    Memcached只支持能序列化的数据类型,不支持持久化,基于Key-Value的内存缓存系统。

    内存分配机制

    应用程序运行需要使用内存存储数据,但对于一个缓存系统来说,申请内存、释放内存将十分频繁,非常容易导致大量内存碎片,最后导致无连续可用内存可用。

    (1)Memcached采用了Slab Allocator机制来分配、管理内存。

    (2)Page:分配给Slab的内存空间,默认为1MB,分配后就得到一个Slab。Slab分配之后内存按照固定字节大小等分成chunk。

    (3)Chunk:用于缓存记录kv值的内存空间。Memcached会根据数据大小选择存到哪一个chunk中,假设chunk有128bytes、64bytes,数据只有100bytes存储在128bytes中,存在些浪费。

            Chunk最大就是Page的大小,即一个Page中就一个Chunk

    (5)Slab Class:Slab按照大小分组,就组成不同的Slab Class

     

    如果有100bytes要存,那么Memcached会选择上图中Slab Class 2存储,因为它是120bytes的Chunk。

    Slab之间的差异可以使用Growth Factor控制,默认1.25。

    懒过期Lazy Expiration

    memcached不会监视数据是否过期,而是在取数据时才看是否过期,过期的把数据有效期限标识为0,并不清除该数据。以后可以覆盖该位置存储其它数据。

    LRU

    当内存不足时,memcached会使用LRU(Least Recently Used)机制来查找可用空间,分配给新纪录使用。

    集群

    Memcached集群,称为基于客户端的分布式集群。

    Memcached集群内部并不互相通信,一切都需要客户端连接到Memcached服务器后自行组织这些节点,并决定数据存储的节点。

    memcached选项:

    修改memcached运行参数,可以使用下面的选项修改/etc/sysconfig/memcached文件

    -u username memcached运行的用户身份,必须普通用户
    -p 绑定的端口,默认11211
    -m num 最大内存,单位MB,默认64MB
    -c num 最大连接数,缺省1024
    -d 守护进程方式运行
    -f 增长因子Growth Factor,默认1.25
    -v 详细信息,-vv能看到详细信息
    -M 内存耗尽,不许LRU
    -U 设置UDP监听端口,0表示禁用UDP

    实战一:基于session共享存储实现LAMT的会话保持(sticky模式生产中常用)

    msm

    msm(memcached session manager)提供将Tomcat的session保持到memcached或redis的程序,可以实现高可用。

    目前项目托管在Github:https://github.com/magro/memcached-session-manager

    支持Tomcat的6.x、7.x、8.x、9.x。

    Tomcat的Session管理类,Tomcat版本不同

    memcached-session-manager-2.3.2.jar
    memcached-session-manager-tc8-2.3.2.jar

    Session数据的序列化、反序列化类

    官方推荐kyro
    在webapp中WEB-INF/lib/下

    驱动类

    memcached(spymemcached.jar)
    Redis(jedis.jar) # redis的jar包

    官网下载依赖的jar包:https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration

    将spymemcached.jar、memcached-session-manage、kyro相关的jar文件都放到Tomcat的lib目录中去,这个目录是$CATALINA_HOME/lib/ ,对应本次安装就是/usr/local/tomcat/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
    jedis-3.0.0.jar  # redis相关的jar包
    

    sticky模式  

    1、当请求结束时Tomcat的session会送给memcached备份。即Tomcat session为主session,memcached session为备session,使用memcached相当于备份了一份Session。

    2、查询Session时Tomcat会优先使用自己内存的Session,Tomcat通过jvmRoute发现不是自己的Session,便从memcached中找到该Session,更新本机Session,请求完成后更新memcached。

    <t1> <t2>
     .  / .
      . X .
     . /  .
    <m1> <m2>
    

    t1和m1部署在一台主机上,t2和m2部署在同一台。

    开始部署session共享会话保持

    1、在t0和t1安装memcached服务

     #yum install memcached  -y
    

    2、修改t0和t1的配置文件,需要监听其他地址的IP地址,否则只会监听本地的IP地址,内存可以设置为1024,最大连接设置为2048

    [root@centos-7 yum.repos.d]# cat /etc/sysconfig/memcached
    PORT="11211"
    USER="memcached"
    MAXCONN="2048"  #修改最大连接数
    CACHESIZE="1024"  # 修改内存大小
    OPTIONS=""

    3、启动memcached服务,监听的是11211端口

    # systemctl start memcached

    4、将依赖的包在官网下载下来并导入到/usr/local/tomcat/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
    jedis-3.0.0.jar
    

    5、修改tomcat服务的配置文件

    特别注意,t0配置中为failoverNodes="n1(memcached1)", t1(tomcat1)配置为failoverNodes="n2(memcached2)"  

    failoverNodes故障转移节点,n1是备用节点,n2是主存储节点。另一台Tomcat将n1改为n2,其主节点是n1,备用节点是n2。

    修改t0的配置文件

    [root@mysql1 lib]# vim /usr/local/tomcat/conf/context.xml 
    
        <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
            memcachedNodes="n1:192.168.7.100:11211,n2:192.168.7.101:11211"
            failoverNodes="n1"  #改为n1时,n1为备用节点,优先使用n2的主机节点
            requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
            transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
            />
    

    修改t1的配置文件

    [root@openstack-2 lib]# vim /usr/local/tomcat/conf/context.xml 
    
        <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
            memcachedNodes="n1:192.168.7.100:11211,n2:192.168.7.101:11211"
            failoverNodes="n2" #改为n2时,优先使用n1的主节点,n2为备用节点。 
            requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
            transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
            />
    

    6、修改tomcat(0和1)的主配置文件

    #vim  /usr/local/tomcat/conf/server.xml
     <Engine name="Catalina" defaultHost="t0.baidu.com" jvmRoute="Tomcat1">  #加上后面的名称,方便辨认是哪个主机
    <Engine name="Catalina" defaultHost="t1.baidu.com" jvmRoute="Tomcat2">

    7、修改两个tomcat的server.xml配置文件

    # vim /usr/local/tomcat/conf/server.xml 
    
    <Engine name="Catalina" defaultHost="t1.baidu.com">
     </Host>
            <Host name="t1.baidu.com" appBase="/data/webapps" autoDeploy="true" >
     
          </Host>
        </Engine>
    

    8、创建t0和t1的测试页面

    # vim  /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>

    9、启动tomcat服务:

    # startup.sh

    修改httpd服务的配置文件

    修改httpd主配置文件

     # vim  /etc/httpd/conf/httpd.conf
    
    注释 #DocumentRoot "/var/www/html"

    修改httpd的反向代理配置

    [root@computer-2 ~]# cat /etc/httpd/conf.d/vhosts.conf 
    <VirtualHost *:80>
    	ServerName node1.baidu.com
    	ProxyRequests Off
    	ProxyVia On
    	ProxyPreserveHost On
    	ProxyPass / balancer://lbtomcats/
    	ProxyPassReverse / balancer://lbtomcats/
    </VirtualHost>
    <Proxy balancer://lbtomcats>
    BalancerMember ajp://t0.baidu.com:8009 loadfactor=1 route=Tomcat1
    BalancerMember ajp://t1.baidu.com:8009 loadfactor=2 route=Tomcat2
    #ProxySet stickysession=ROUTEID
    </Proxy>
    

    启动httpd服务

    # systemctl start httpd

    测试效果:

     第一次测试:

     

     第二次测试:

     

     下来模拟memcached的n2宕机,此时t0和t1都转移到memcached的n1上:

     宕机n2:systemctl stop memcached

     

      

     再次重启n2的memcached服务,此时Tomcat1就会又去优先到n2进行写入缓存:

     重启n2的memcached服务:systemctl  restart memcached

     

    实战二:基于session共享存储实现LNMT的会话保持(sticky模式生产中常用)

    1、修改nginx服务器的主配置文件 

    upstream tomcats {    #在http 段配置
    server t0.baidu.com:8080 weight=1;
    server t1.baidu.com:8080 weight=2;
    }
     
    location / {    #在server 段配置
            proxy_pass http://tomcats;
    }
    location ~* .(jsp|do)$ {
            proxy_pass http://tomcats;
    }
    

    只需要将httpd的配置改为nginx配置,upstream转发到后端服务器,其他的tomcat配置不变、memcached服务配置文件都在上面:

    2、测试效果:  

     此时tomcat1对应的n2和tomcat2对应的n1都是一个session ID,实验成功:

     

     

    实战三:基于session共享存储(memcached)实现LNMT的会话保持(non-sticky模式)

    实现原理

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

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

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

    注意:其他测试页面在上面已经存在,下面就不在写入。

    1、开始部署,在t0和t1的/usr/local/tomcat/conf/context.xml配置文件中修改

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

    2、修改nginx服务器的主配置文件 

    upstream tomcats {    #在http 段配置
    server t0.baidu.com:8080 weight=1;
    server t1.baidu.com:8080 weight=2;
    }
     
    location / {    #在server 段配置
            proxy_pass http://tomcats;
    }
    location ~* .(jsp|do)$ {
            proxy_pass http://tomcats;
    }

     3、启动nginx服务和tomcat服务

    # nginx  
    # shutdown.sh
    # startup.sh
    

     测试效果

    此时可以看到,访问tomcat时,占用的是memcached的n1

    模拟此时的n1(memcached)宕机,此时n2就会占用上来,由于n1和n2是同优先级的服务器,此时就算n1启动起来,也不会再占用到n1的缓存服务器上。

    实战四:基于session共享存储(redis)实现LNMT的会话保持(non-sticky模式)

     1、安装并配置redis服务

    #  yum install redis  -y
    
    #  vim /etc/redis.conf    #修改redis配置
     bind 0.0.0.0   #监听本地的所有IP地址
    
    # systemctl start  redis    #启动redis服务
    

    2、配置tomcat服务

    修改tomcat文件时,目前没有做redis主从复制及集群模式,生产中必须做,此时将IP地址都指向了一个redis的IP地址上

    [root@centos-7 ~]# vim /usr/local/tomcat/conf/context.xml
    
        <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
            memcachedNodes="redis://192.168.7.100:6379"
            sticky="false"
            sessionBackupAsync="false"
            lockingMode="uriPattern:/path1|/path2"
            requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
            transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
            />
    

    创建t0和t1的测试页面

    # vim  /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>

    3、修改nginx服务器的主配置文件 

    upstream tomcats {    #在http 段配置
    server t0.baidu.com:8080 weight=1;
    server t1.baidu.com:8080 weight=2;
    }
     
    location / {    #在server 段配置
            proxy_pass http://tomcats;
    }
    location ~* .(jsp|do)$ {
            proxy_pass http://tomcats;
    }

    启动nginx和tomcat服务

    #  nginx  
    # shutdown.sh
    # startup.sh
    

    测试效果:

    两个主机的session ID都一致,实验成功:

     

    总结  

    通过多组实验,使用不同技术实现了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数据是有时效性的,是否需要这样做,视情况而定。

      

     

  • 相关阅读:
    了解jQuery
    jQuery其他关系查找方法
    jQuery中的入口函数
    漫谈《挪威的森林》
    再说变
    再说鞋
    SDG
    Apache Geode简介
    2021/11/24策略模式
    2021/11/26
  • 原文地址:https://www.cnblogs.com/struggle-1216/p/12185351.html
Copyright © 2020-2023  润新知