Httpd+Tomcat+memcached实现session server

何为会话保持



会话保持是负载均衡最常见的问题之一,也是一个相对比较复杂的问题。会话保持有时候又叫做粘滞会话(Sticky Sessions)。会话保持是指在负载均衡器上的一种机制,可以识别客户端与服务器之间交互过程的关连性,在作负载均衡的同时还保证一系列相关连的访问请求会保持分配到一台服务器上

何时需要会话保持

在讨论这个问题前,我们必须先花点时间弄清楚一些概念:什么是连接(Connection)、什么是会话(Session),以及这二者之间的区别。需要特别强调的是,如果我们仅仅是谈论负载均衡,会话和连接往往具有相同的含义。

从简单的角度来看,如果用户需要登录,那么就可以简单的理解为会话;如果不需要登录,那么就是连接。

对于同一个连接中的数据包,负载均衡会将其进行NAT转换后,转发至后端固定的服务器进行处理。负载均衡系统内部会专门有一张表来记录这些连接的状况,包括:[源IP:端口]、[目的IP:端口]、[服务器IP:端口]、空闲超时时间(Idle Timeout)等等。由于负载均衡内部记录连接状态的这张表需要消耗系统的内存资源,因此这张表不可能无限大,所有传统厂商都会有一定的限制。这张表的大小一般称之为最大并发连接数,也就是系统同时能够容纳的连接数量。负载均衡的当前连接状态表项中,设计了一个空闲超时时间(Idle Timeout)的参数。当该连接在Idle Timeout内无流量通过时,负载均衡会自动删除该连接条目,释放系统资源。

删除连接后,客户端的请求将无法保证继续发往同一个后端服务器,需要遵循负载均衡器的流量分发策略。

在某些要求登录状态的情境下,要求客户端和服务器之间保持一个会话(session)以记录客户端的各种信息。比如在大多数电子商务的应用系统或者需要进行用户身份认证的在线系统中,一个客户与服务器经常经过好几次的交互过程才能完成一笔交易或者是一个请求的完成。由于这几次交互过程是密切相关的,服务器在进行这些交互过程的某一个交互步骤时往往需要了解上一次或上几次的交互过程处理结果,这就要求所有这些相关的交互过程都由一台服务器完成,而不能被负载均衡器分散到不同的服务器上否则可能出现异常情景:

  • 客户端输入了正确的用户名和口令,但却反复跳到登录页面;
  • 用户输入了正确的验证码,但是总提示验证码错误;
  • 客户端放入购物车的物品丢失

因此会话保持机制的意义就在于,确保在合适的情境下,将来自相同客户端的请求转发至后端相同的服务器进行处理。换句话说,就是将客户端与服务器之间建立的多个连接,都发送到相同的服务器进行处理。如果在客户端和服务器之间部署了负载均衡设备,很有可能这多个连接会被转发至不同的服务器进行处理。如果服务器之间没有会话信息的同步机制,会导致其他服务器无法识别用户身份,造成用户在和应用系统发生交互时出现异常。

负载均衡希望将来自客户端的连接、请求均衡的转发至后端的多台服务器,以避免单台服务器负载过高;而会话保持机制却要求将某些请求转发至同一台服务器进行处理。因此,在实际的部署环境中,我们要根据应用环境的特点,选择适当的会话保持机制。

   会话保持类型



会话保持大体可以分为三大类,session sticky,session LBcluster和session server,而这三种会话绑定方式又各有优缺点,适应不同的场景;

1 session sticky

Session sticky,即会话绑定,即将客户端的访问通过某种算法将它调度至固定的服务器上,而这种实现方式主要是由调度器的调度算法来实现的,像在Nginx反向代理功能中就提供了ip_hash(每个请求按访问ip结果分配。这样来自同一个ip的访问将被调度到同一台服务器上,有效解决的动态网页存在的session共享问题。),url_hash(此方法是按照访问url的hash结果来分配请求,使每一个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身是不支持url_hash算法的)以及更加强大的一致性hash算法。这种调度方式是基于四层的会话调度,这种调度粒度很粗。

会话绑定中一个很重要的参数就是连接超时值,负载均衡器会为每一个处于保持状态中的会话设定一个时间值。若一个会话从上一次完成到下次再来之间的间隔时间小于超时值时,负载均衡器将会将新的连接进行会话保持;但如果这个间隔大于该超时值,负载均衡器会将新来的连接认为是新的会话然后进行负载平衡。这种会话话保持实现简单,只需要根据数据包三四层的信息就可以实现,效率比较高。

但此种方式存在的问题就在于,当多个客户端通过代理或地址转换的方式访问服务器时,由于来源地址一样,请求都被分配到同一台服务器上,会导致服务器之间的负载严重失衡。另外一种情况是,同一个客户端产生大量并发,要求分配到多个服务器上处理的同时进行会话保持。这时基于客户端源地址的会话保持方法也会导致负载均衡失效。以上情况出现时,就必须要考虑使用其他的会话保持方式。

2 Session Lbcluster

由于session sticky在调度中不能够很好的实现会话的保持与高可用性,只要其中一台主机宕机,就意味着这台主机维持的所有会话都将丢失,这不仅对用户是一种不好的体验,更是一个站点的损失,于是人们开始思考能否让后端的每个服务器都能够携带所有服务器的会话呢?渐渐的找到了解决方案,那就是实现会话集群,会话集群,顾名思义,那就是将所有维持会话的服务组合成一个集群,维护该站点所有的会话信息,这样一来,我们就不用在担心因为某台主机而使得用户的信息丢失。

这种方式解决了用户会话丢失的问题,用户再也不会出现什么”客户端放入购物车的物品丢失”这类问题了。但是解决了A类问题也会带来B类问题,每个会话服务器既要处理前端的用户请求又要会话同步至其他的主机,如果这是一个量很大的服务站点,那么每一台主机在同步其他主机的会话信息,以及将自己维持的会话发送给其他服务器时将会产生大量IO操作,这就使得每个服务器的压力变得异常大,处理前端的请求的性能大大降低。并且,同步使用的是组播的方式来实现的,大量服务器同时同步各自的会话给其他的主机,这将消耗大量的带宽。

3 Session Server

鉴于会话集群带来的新问题,我们选择一组服务器来专门用户进行会话的管理,后端服务器只需要将自己的会话写入到后端的会话服务器即可,等到用户的请求到来是,只需要与session server中的会话值做比较即可。那么session Server怎样存储这些会话信息呢,于是有了以下几种存储方式:

1) 数据库存放

Session信息存储到数据库表以实现不同应用服务器间Session信息的共享。此种方式适合数据库访问量不大的网站。

优点:实现简单

缺点:由于数据库服务器相对于应用服务器更难扩展且资源更为宝贵,在高并发的Web应用中,最大的性能瓶颈通常出现在数据库服务器。因此如果将 Session存储到数据库表,频繁的数据库操作会影响业务。

2) 文件系统存放

通过文件系统(比如NFS)来实现各台服务器间的Session共享。此种方式适合并发量不大的网站。

优点:各台服务器只需要mount存储Session的磁盘即可,实现较为简单。

缺点:NFS对高并发读写的性能并不高,在硬盘I/O性能和网络带宽上存在较大瓶颈,尤其是对于Session这样的小文件的频繁读写操作。

3) Memcached存放

利用Memcached来保存Session数据,直接通过内存的方式读取。

优点:效率高,在读写速度上会比存放在文件系统时快很多,而且多个服务器共用Session也更加方便,将这些服务器都配置成使用同一组memcached服务器就可以,减少了额外的工作量。

缺点:一旦宕机内存中的数据将会丢失,但对Session数据来说并不是严重的问题。如果网站访问量太大、Session太多的时候memcached会将不常用的部分删除,但是如果用户隔离了一段时间之后继续使用,将会发生读取失败的问题。



接下来用实验来实现session绑定



首先介绍负载均衡,可用三种方式来实现,下面我介绍了常用的三种方法供参考

负载均衡集群(nt)

(1) nginx + tomcat cluster



环境:两台tomcat主机,一台调度器(nginx)

首先三台主机都实现地址解析

[[email protected] text]#vim /etc/hosts
172.18.77.7 node1
172.18.77.77 node2
172.18.77.74 diaodu

然后为了方便可以修改主机名,在tomcat主机上安装包

yum install -y java-1.8.0-openjdk-devel
yum install -y tomcat tomcat-lib tomcat-admin-webapps tomcat-webapps tomcat-docs-webapp
mkdir  -pv  /usr/share/tomcat/webapps/test/{classes,lib,WEB-INF}

创建文件测试页面vim /usr/share/tomcat/webapps/test/index.jsp

<%@ page language="java" %>
    <html>
    <head><title>TomcatA</title></head>
    <body>
        <h1><font color="red">TomcatA.magedu.com</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的测试页面:

<%@ page language="java" %>
    <html>
    <head><title>TomcatB</title></head>
    <body>
        <h1><font color="red">TomcatB.magedu.com</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服务,可先在网页测试是否能访问http://172.18.77.77:8080/test/

然后在调度器上编辑配置文件

vim /etc/nginx/nginx.conf
    upstream tcsrvs {
        server 172.18.77.7:8080;
        server 172.18.77.77:8080;
    }
  location / {
        proxy_pass http://tcsrvs;
        }

最后重启服务在浏览器上测试:http://172.18.77.74/test/

或者用命令访问

[[email protected] ~]#for i in {1..10};do curl -s http://172.18.77.74/myapp/ |grep -i tomcat ;done
                            <head><title>TomcatB</title></head>
                            <h1><font color="blue">TomcatB.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="red">TomcatA.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="blue">TomcatB.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="red">TomcatA.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="blue">TomcatB.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="red">TomcatA.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="blue">TomcatB.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="red">TomcatA.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="blue">TomcatB.magedu.com</font></h1>
                            <head><title>TomcatB</title></head>
                            <h1><font color="red">TomcatA.magedu.com</font></h1>

上述构建nt集群实现负载均衡

构建ht集群实现负载均衡

(2) httpd(调度器) + tomcat cluster



httpd: mod_proxy, mod_proxy_http, mod_proxy_balancer(构建负载均衡模块)

tomcat cluster:http connector

安装httpd将nginx服务停止:

[[email protected] ~]#vim /etc/httpd/conf.d/http-tomcat.conf
<Proxy balancer://tcsrvs>  
    BalancerMember http://172.18.77.7:8080  
    BalancerMember http://172.18.77.77:8080
    ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
    ServerName diaodu
    ProxyVia On
    ProxyRequests Off
    ProxyPreserveHost On
    <Proxy *>
        Require all granted
    </Proxy>
    ProxyPass / balancer://tcsrvs/
    ProxyPassReverse / balancer://tcsrvs/
    <Location />
         Require all granted
    </Location>
</VirtualHost>

其他配置不变:测试 http://172.18.77.74/test/

(3) httpd + tomcat cluster



httpd: mod_proxy, mod_proxy_ajp, mod_proxy_balancer

tomcat cluster:ajp connector

可先将httpd服务关闭

该方法就是基于httpd的ajp模块实现负载均衡,将http改为ajp,将端口号改为8009即可,其他配置不变

[[email protected] ~]#vim /etc/httpd/conf.d/http-tomcat.conf
<Proxy balancer://tcsrvs>  
    BalancerMember ajp://172.18.77.7:8009  
    BalancerMember ajp://172.18.77.77:8009
    ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
    ServerName diaodu
    ProxyVia On
    ProxyRequests Off
    ProxyPreserveHost On
    <Proxy *>
        Require all granted
    </Proxy>
    ProxyPass / balancer://tcsrvs/
    ProxyPassReverse / balancer://tcsrvs/
    <Location />
         Require all granted
    </Location>
</VirtualHost>

测试 http://172.18.77.74/test/

当后端tomcat服务器宕机了,会调度到另一台主机上了

Httpd+Tomcat+memcached实现session server



1 > 环境:

安装memcached包,开启服务;端口:11211

两个tomcat节点:172.18.77.7(tomcatA.magedu.com),172.18.77.77(tomcatB.magedu.com)

两个memcached节点:172.18.77.7, 172.18.77.77

一个负载均衡节点:172.18.77.74

由于本人主机不够多,所以将缓存服务器和tomcat服务器基于同一台了。请见谅!!!

Clients-->172.18.77.74-->(tomcatA, tomcatB)

2 >下载jar包



memcached-session-manager项目地址,http://code.google.com/p/memcached-session-manager/, https://github.com/magro/memcached-session-manager

mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF/{classes,lib}

下载如下jar文件至各tomcat节点的tomcat安装目录下的lib目录中

将下列两个javolution包放在这个目下/usr/share/tomcat/webapps/test/WEB-INF/lib/

javolution-5.4.3.1.jar

msm-javolution-serializer-2.1.1.jar

将下述三个memcached的包放在/usr/share/tomcat/lib/这个目录下

memcached-session-manager-2.1.1.jar

memcached-session-manager-tc7-2.1.1.jar

spymemcached-2.12.3.jar

3 >Tomcat的配置



分别在两个tomcat上的某host上定义一个用于测试的context容器,并在其中创建一个会话管理器,如下所示:

           <Context path="/test" docBase="/usr/local/tomcat/webapps/test" reloadable="true">
              <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
                memcachedNodes="n1:172.18.77.7:11211,n2:172.18.77.77:11211"
                failoverNodes="n1"
                requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
                transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
              />
            </Context>

分别为两个context提供测试页面:

tomcatA:

# vim /usr/share/tomcat/webapps/test/index.jsp
添加如下内容:
<%@ page language="java" %>
<html>
  <head><title>TomcatA</title></head>
  <body>
    <h1><font color="red">TomcatA.magedu.com</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>

tomcatB:

# mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF/{classes,lib}
# vim /usr/shaaer/tomcat/webapps/test/index.jsp
添加如下内容:
<%@ page language="java" %>
<html>
  <head><title>TomcatB</title></head>
  <body>
    <h1><font color="blue">TomcatB.magedu.com</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>

4 > Http的反向代理配置



在172.18.77.74上配置反向代理的负载均衡内容

[[email protected] ~]#vim /etc/httpd/conf.d/http-tomcat.conf
<Proxy balancer://tcsrvs>  
    BalancerMember http://172.18.77.7:8080  
    BalancerMember http://172.18.77.77:8080
    ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
    ServerName diaodu
    ProxyVia On
    ProxyRequests Off
    ProxyPreserveHost On
    <Proxy *>
        Require all granted
    </Proxy>
    ProxyPass / balancer://tcsrvs/
    ProxyPassReverse / balancer://tcsrvs/
    <Location />
         Require all granted
    </Location>
</VirtualHost>

5 >测试:



在浏览器中访问http://172.16.100.6/test,结果如下图所示,其session ID在负载均衡环境中保持不变。

注意:上述配置均在centos 7.3版本上进行的,版本的高低可能安装的javolution包和

memcached包不同,会出现服务启动不了

时间: 2024-10-01 05:21:58

Httpd+Tomcat+memcached实现session server的相关文章

httpd+tomcat+memcached实现session保持

本节我将带大家认识tomcat以及如何基于memcached实现tomcat的会话保持.好了废话不多说,下面我们就开始了. tomcat的介绍 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选.实际上Tomcat 是Apache 服务器的扩展,但它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的.通常在我们的应用过程中,我们让A

Nginx反向代理+Tomcat+memcached实现session server

写在前面 前一篇文章为大家解释说明了会话的类型,今天这篇文章将带领大家一步一步实现一个简单的session server,主要是让大家理解session server的工作过程,当然了对于中小向站点,这个结构也完全够用了.本节主体结构: memcached-session-manager介绍 网络拓扑结构 Nginx反向代理配置 Tomcat配置 memcached配置 测试 错误分析 memcached-session-manager介绍 memcached-session-manager是一

【Tomcat】Tomcat + Memcached 实现session共享

概述 web项目中,Tomcat的访问量总是有限的,这时候就需要用到Tomcat集群,多个Tomcat的时候就要考虑Session共享的问题,这里介绍一种使用Memcached做Session共享的解决方案 环境 操作系统:Linux( centOS 6..5 版) 软件:Tomcat7    Memcached 实现原理 Tomcat + Memcached 实现session共享流程图 配置 安装Tomcat 2个和Memcached 1个,参考[Linux]Tomcat安装及一个服务器配置

tomcat篇之结合apache+tomcat+memcached做session共享

tomcat1:192.168.1.155 tomcat2:192.168.1.11 apache:192.168.1.155 前端代理apache设置,参考前面的tomcat文章(基于mod_proxy和mod_jk模块) 这里不再赘述,直接贴配置文件: cd /etc/httpd/conf.d [[email protected] conf.d]# cat mod_jk.conf LoadModule  jk_module  modules/mod_jk.so JkWorkersFile/e

tomcat实现session集群及tomcat+memcached共享session存储(四)

接博客nginx或httpd实现负载均衡tomcat(三) tomcat实现会话管理原理及实现: tomcat管理会话使用的专用的会话管理组件,tomcat的会话管理器有4种: 1.标准会话管理器(StanderdManager) 2.持久会话管理器(PersistentManager可以基于文件存储(FileStore)或JDBC存储(JDBCStore)) 基于JDBC的话就可以实现高可用tomcat的session集群. 1.DeltaManager会话管理器 2.BackupManage

tomcat cluster和tomcat+memcached实现Session会话保持

Tomcat Cluster: tomcat基于内存复制的集群,tomcat集群各节点通过建立tcp链接来实现session的复制,tomcat启动时,一个cluster对象(默认配置下是SimpleTcpCluster)会启动membership服务和Replication服务(用于建立tcp链接),membership服务记录了集群当前节点的信息,当一台节点接收http请求并产生一个新session时,调用Replication服务建立tcp连接把Session复制到membership列表

nginx+tomcat+memcached实现session共享

一.工作原理及原理图<img class="alignnone wp-image-31" src="http://119.29.25.60/wp-content/uploads/2016/04/图片1.bmp" alt="图片1" width="342" height="254" />工作原理        Tomcat中自带缓存功能.Memcached时一个集中式缓存器,可以利用tomcat和

Tomcat+Memcached实现Session共享

在先前的例子中,我用Tomcat官方提供的Session复制方式实现Tomcat集群Session共享.今天,我用另一种方式Memcached-Session-Manager来实现Session共享.话不多说,上实例. Memcached-Session-Manager将Session序列化到Memcache中,序列化的组件有很多,比如: msm-kryo-serializer.msm-javolution-serializer等,这里使用msm-javolution-serializer,使用

【电商】nginx+tomcat+memcached实现session共享集群

在分布式多tomcat web集群环境下,首先要解决的是session的共享问题,一般的实现思路有: (1) session复制:多tomcat之间进行session的同步,集群中的tomcat存储相同的session信息 (2) 共享session存储:将session集中存储在同一个地方,如redis/memcached,甚至DB.tomcat本身的内存中并不存储session (3) session粘性:其实session粘性并不是session共享的方案,而是多tomcat的集群方案,配