一、http协议的无状态性

1、HTTP协议一共有五大特点

 1)支持客户/服务器模式

 2)简单快速

       客户端向服务器端发送请求时,只是简单的填写请求路径和请求方法即可,然后就可以通过浏览器或其他方式将该请求发送就行了。比较常用的请求方法有三种,分别是:GET、HEAD、POST。不同的请求方法使得客户端和服务器端联系的方式各不相同。因为HTTP协议比较简单,所以HTTP服务器的程序规模相对比较小,从而使得通信的速度非常快。

 3)灵活

     Http协议允许客户端和服务器端传输任意类型任意格式的数据对象。这些不同的类型由Content-Type标记。

 4)无连接

      无连接的含义是每次建立的连接只处理一个客户端请求,当服务器处理完客户端的请求之后,并且收到客户的反馈应答后,服务器端立即断开连接。采用这种通信方式可以大大的节省传输时间。

 5)无状态

      Http是无状态的协议。所谓的无状态是指协议对于请求的处理没有记忆功能。无状态意味着如果要再次处理先前的信息,则这些先前的信息必须要重传,这就导致了数据量传输的增加。但是从另一方面来说,当先前的信息服务器不在使用的时候,则服务器的响应将会非常的快。

就是当浏览器发送请求给服务器的时候,服务器响应,但是同一个浏览器再发送请求给服务器的时候,他会响应,但是他不知道你就是刚才那个浏览器,简单地说,就是服务器不会去记得你,所以是无状态协议。

2、http协议的无状态性

     HTTP协议的目的在于支持超文本的传输,更加广义一些就是支持资源的传输,那么在客户端浏览器向HTTP服务器发送请求,继而HTTP服务器将相应的资源发回给客户端这样一个过程中,无论对于客户端还是服务器,都没有必要记录这个过程,因为每一次请求和响应都是相对独立的,就好像你在自动售货机前投下硬币购买商品一样,谁都不会也不需要记住这样一个交易过程。一般而言,一个URL对应着唯一的超文本,而HTTP服务器也绝对公平公正,不管你是张三,还是李四,它都会根据接收到的URL请求返回相同的超文本。正是因为这样的唯一性,使得记录用户的行为状态变得毫无意义,所以,HTTP协议被设计为无状态的连接协议符合它本身的需求。

        然而,随着时间的推移,人们发现静态的HTML着实无聊而乏味,增加动态生成的内容才会令Web应用程序变得更加有用。于是乎,HTML的语法在不断膨胀,其中最重要的是增加了表单(Form);客户端也增加了诸如脚本处理、DOM处理等功能;对于服务器,则相应的出现了CGI(Common Gateway Interface)以处理包含表单提交在内的动态请求。在这种客户端与服务器进行动态交互的Web应用程序出现之后,HTTP无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品。于是,两种用于保持HTTP连接状态的技术就应运而生了,一个是Cookie,而另一个则是Session。

        Cookie是通过客户端保持状态的解决方案。从定义上来说,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。

让我们说得更具体一些:当用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体(Response Body)中的,而是存放于HTTP响应头(Response Header);当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置,对于Windows操作系统而言,我们可以从:[系统盘]:/Documents and Settings/[用户名]/Cookies目录中找到存储的Cookie;自此,客户端再向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。而这次,Cookie信息则存放在HTTP请求头(Request Header)了。
       有了Cookie这样的技术实现,服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。通常,我们可以从很多网站的登录界面中看到“请记住我”这样的选项,如果你勾选了它之后再登录,那么在下一次访问该网站的时候就不需要进行重复而繁琐的登录动作了,而这个功能就是通过Cookie实现的。
  
        与Cookie相对的一个解决方案是Session,它是通过服务器来保持状态的。由于Session这个词汇包含的语义很多,因此需要在这里明确一下Session的含义。首先,我们通常都会把Session翻译成会话,因此我们可以把客户端浏览器与服务器之间一系列交互的动作称为一个Session。从这个语义出发,我们会提到Session持续的时间,会提到在Session过程中进行了什么操作等等;其次,Session指的是服务器端为客户端所开辟的存储空间,在其中保存的信息就是用于保持状态。从这个语义出发,我们则会提到往Session中存放什么内容,如何根据键值从Session中获取匹配的内容等。

        要使用Session,第一步当然是创建Session了。那么Session在何时创建呢?当然还是在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法,而在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。在创建了Session的同时,服务器会为该Session生成唯一的Session id,而这个Session id在随后的请求中会被用来重新获得已经创建的Session;在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有Session id;当客户端再次发送请求的时候,会将这个Session id带上,服务器接受到请求之后就会依据Session id找到相应的Session,从而再次使用之。正式这样一个过程,用户的状态也就得以保持了。
        综上所述,HTTP本身是一个无状态的连接协议,为了支持客户端与服务器之间的交互,我们就需要通过不同的技术为交互存储状态,而这些不同的技术就是Cookie和Session了。
 

二、会话保持

很多场景下,用户的访问网站的会话信息都需要保存,实现会话保持的方式常用三种:

1、session 绑定

      lvs:sh算法,基于源IP绑定

      nginx:ip_hash算法 基于源IP绑定,nginx-sticky-module模块,基于cookie绑定

      haproxy:source算法 基于源ip绑定,cookie,基于cookie绑定

      缺点:反均衡,

2、session 复制

   参与集群的每个节点的Session状态都被复制到集群中的其他所有节点上,无论何时,只要Session发生改变,Session数据都要重新被复制。Tomcat(DeltaManager)、JBoss、was都提供了这样的功能,其中Tomcat采用集群节点多播复制,JBoss采用配对复制机制。
    优点:每个节点都复制一份Session,一个节点出现问题时其它节点可以接替它的工作。

    缺点:节点间进行Session同步会占据不少系统资源,整体性能随着集群节点数的增加而急剧下降,适用于集群节点3-5台。

3、session 服务器

     将所有节点的Session放到一起进行统一管理,每个节点在未参与集群以前都有自己独立的Session体系,参与到集群以后可以让所有节点将各自的Session信息用一套相同的机制保存到一个统一的地方进行存取,这样不管请求被分发到哪个节点都可以访问到其它节点创建的Session。

    缺点:服务器自身HA

session 绑定和复制我们在之前的博客都学习过了,现在来学习基于memcached-session-manager构建tomcat cluster会话服务器

三、memcached session manager

1、简介

    MSM--memcached session manager是一个高可用的Tomcat session共享解决方案,除了可以从本机内存快速读取Session信息(仅针对黏性Session)外,同时可使用memcached存取Session,以实现高可用。

对于非黏性Session,memcached直接存储session。

除memcached外,还可以其他缓存组件如memcachedb, membase等。

1、特性

支持Tomcat6、Tomcat7,Tomcat8

支持黏性、非黏性Session

无单一故障点

可处理tomcat故障转移

可处理memcached故障转移

插件式session序列化

允许异步保存session,以提升响应速度

只有当session有修改时,才会将session写回memcached

JMX管理&监控

3、MSM解决的问题

   假设你有一个Tomcat集群,使用黏性session,如何应对单点故障问题?为了应对更多的并发量和可用性,你可以不断的增加Tomcat节点,但是单点故障仍旧会是个问题:如果使用黏性Session,一个Tomcat故障时,其他Tomcat并不能接管故障Tomcat节点的Session。

解决此问题的思路就是将黏性Session同时保存在Memcached中,如果单个Tomcat发生故障,集群中的其他Tomcat可以从Memcached中得到Session信息。

   对于非黏性Session,MSM  V1.4.0及以后版本已经支持。

4、MSM如何工作

    安装在Tomcat上的MSM使用本机内存保存session,和StandardManager一样。另外,当一个请求结束时,session会被送回Memcached进行备份。当下一次请求开始时,本地Session可用,直接服务,请求结束后,session又被送回Memcached备份。

当集群中的一个Tomcat挂掉,下一次请求会被路由到其他Tomcat上。负责处理此此请求的Tomcat并不清楚Session的信息。此时它会从Memcached查找该Session,更新该Session并将其保存在本机内容。此次请求结束,session被修改,送回Memcached备份。

上边介绍的是处理Tomcat故障转移,MSM又是如何处理Memcached故障转移呢?

如果一个Memcached故障,当前Memcached中的Session会转移到其他Memcached节点,同时,JSESSIONID被修改并送回浏览器。

如果使用黏性Session,应确保loadbalancer中配置生成的JSESSIONID无任何后缀。

SESSIONID的格式:

MSM知道Memcached节点列表,这些节点标识会存储在SESSIONID中,

SESSIONID值类似:602F7397FBE4D9932E59A9D0E52FE178-n1 【其中n1为Memcached节点标识】

四、基于memcached-session-manager构建tomcat cluster会话服务器

1、环境

192.168.100.175 httpd代理服务器 

192.168.100.179 tomcatA 

192.168.100.180 tomcatB

192.168.100.173 memcached1

192.168.100.10  memcaced2  

注意:

       各节点上的软件安装过程就不写出来了,就是用上篇博客的环境改了下memcached不做集群(恢复默认配置文件),再添加2台memcached服务器,有疑问的可以看下上篇博客,

拓扑简单就不画图了,最主要是懒

      集群各节点时间同步

2、tomcat节点配置

(1) 复制jar文件至各tomcat节点的tomcat安装目录下的lib目录中

     从memcached-session-manager项目地址,http://code.google.com/p/memcached-session-manager/ 下载jar文件至各tomcat节点的tomcat安装目录下的lib目录中,其中的${version}要换成你所需要的版本号,tc${6,7,8}要换成与tomcat版本相同的版本号。

memcached-session-manager-${version}.jar

memcached-session-manager-tc${6,7,8}-${version}.jar

msm-javolution-serializer-${version}.jar

javolution-${version}.jar

spymemcached-${version}.jar

注意:上面3个在msm项目地址就可以找到,下面2个要自己找,有需要的我可以共享出来

复制以上文件到/usr/local/tomcat/lib/目录(2个tomcat节点都要哦):

[root@BAIYU_179 ~]# ls msm/
javolution-5.5.1.jar                     msm-javolution-serializer-1.8.2.jar
memcached-session-manager-1.8.2.jar      spymemcached-2.10.2.jar
memcached-session-manager-tc8-1.8.2.jar
[root@BAIYU_179 ~]# cp msm/* /usr/local/tomcat/lib/
[root@BAIYU_179 ~]# scp -rp msm/* 192.168.100.180:/usr/local/tomcat/lib/

(2)在tomcat上的某host上定义一个用于测试的context容器,并在其中创建一个会话管理器

如下所示:

<Context path="/myapp" docBase="myapp" reloadable="true">
       <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
                memcachedNodes="n1:192.168.100.179:11211,n2:192.168.100.180:11211"
                failoverNodes="n1"  requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
                transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.Javolution
    TranscoderFactory" />
             
          </Context>

并在其它tomcat节点上做同样的配置

tomcat7是没问题的,

这里可能下载的文件和tomcat8不兼容,待后续解决