当浏览器发起一个新的HTTP请求时,WEB服务端会主动建立一个session.并分配一个sessionID做为服务端识别客户端的一个标识,session对象会保存在服务端.此时session对象处于NEW STATE状态,若是调用mysql
session.isNew()则返回true.当服务器处理完相应的请求时候,会将sessionID同reponse响应消息 一块儿传回客户端浏览器,并将其存到该客户端浏览器的cookie中。当客户端再发送其它http请求的时候.会将sessionID连同request消息一块儿发送给服务端。服务端再根据传过来的sessionID将此次request与保存在服务端的session对象联系起来.此时的session对象已不是NEWSTATE状态.这样循环屡次.直到session对象超时或销毁.web
注:当客户端浏览器禁用cookie时,sessionID将不能保存在cookie中,通常此种状况,会使用url重写,将sessionID做为请求参数来进行客户端和浏览器的信息传输交互redis
- cookie cookie是在客户端保存一些少许数据的解决方案.而session是在服务端保存少许数据的方案. 若是cookie不设定时间的话就表视它的生命周期为浏览器会话的期间,只要关闭浏览器,cookie就消失了,这种cookie被称为会话cookie.其通常不保存在硬盘上.而是保存在内存中。若是设置了过时时间.那么浏览器会把cookie保存到硬盘中,再次打浏览器时会依然有效.直到它的有效期超时;
注:会话cookie能够在一个浏览器间的不一样的tab页中共享。随浏览器主进程的关闭而失效 存储在硬盘中的cookie能够在不一样浏览器进程间共享。
分布式系统session共享问题的由来
目前大多数大型web应用都采用了分布式服务集群的部署方式,所谓集群,就是让一组计算机服务器协同工做,解决大并发,高可用,水平扩展的问题。可是在服务集群中,session共享每每是一个比较头疼的问题。由于session是在服务器端保存的,若是用户跳转到其余物理服务器的话,session就会丢失,通常状况下,session对象在后端是不可跨物理服务器而存在。因而就有了分布式系统的session共享问题。 目前公司有不少的应用都是集群布置环境,可是,有不少项目运维在配置f5做负载均衡时,做了访问地址ip hash算法来分担流量,该算法根据访问客户端的IP地址进行归类并和集群中的真实的服务器数取模,获得一个固定值,来分配真实的服务器,这样的确能够分担部分的流量,但并无起到failover的功能,即这台服务器挂机后,该客户端的请求信息仍然会发送到该服务器上,而且,若是服务器集群中,真实的服务器有硬件性能上的差别,在这种分配策略上也作不到所谓的“能者多劳”。因此,要作到真正的HA,这种算法是不合适的。算法
因此,为了提升程序的HA及提供failover,在应用端若是是集群布置,而且在应用的开发过程当中,若是在session中保存了相关的内容,则最好要提供分布式的session解决方案。
经常使用的集群Session共享的方式
- 客户端Cookie保存方案,将原来保存在session中的内容以加密的方式保存在客户端cookie中。
- 优势:减轻服务器端的压力,每次session信息被写回客服端,而后经浏览器再次提交到服务器。即便两次请求即便在集群中的不一样服务器上完成,因为session信息都是随请求信息一块儿提交,也能够到达session共享。
- 缺点:
- 传递cookie时,http信息头的长度限制使咱们只可以在cookie中存入少许的用户信息;
- 须要额外地作session信息加密的工做;
- 若是采用这种方式,每次访问网站二级域名时都会在http信息头中带有这些以cookie形式存储的值信息,会占用必定的带宽;
- 信息存储是在客户端进行,用户彻底能够禁用cookie或删除cookie,不是很可靠
- 服务器间Session同步方案,将session对象在集群中的全部物理机上做同步 服务器间session同步策略,不一样的容器有不一样的解决方案。通常经常使用如下2种
- 使用主-从服务器的架构,当用户在主服务器上登陆后,经过脚本或者守护进程的方式,将session信息传递到各个从服务器中,这样,用户访问其它的从服务器时,就能够读到session信息。 缺点:好比速度慢、不稳定等,另外,若是session信息传递是主->从单向的,会有一些风险,好比主服务器down了,其它服务器没法得到session信息
- Session 对象的集群中的广播机制。 一台主机中产生session中,将此session对象在集群网络中进行广播同步,各集群中的主机收到广播后,再同步到本地的session内存域中。 缺点:若是session内容中有大型对象时,不适合传输。集群范围中网络中对存在大量的广播消息,占用带宽,会有延时.
- 使用集中统一管理Session方案 即将集群中各主机产生的session对象都存储到一个中心存储结构中,目前比较流行的存储结构是:redis集群,Memcache,mysql数据库等。这种集中存储的结构,能斛决上面方案中的一些弊断。但也有一些应用上问题。好比选择mysql做存储结构中,mysql数据库能够用做存储的session对象,但在并发量高时,对数据库的读写要求较高,还须要另外提升session失效的相关算法。Redis集群,memcache主要是之内存为存储介质,有先天的读写优点,而且都能提供失效机制,特别适合用来做session的存储结构。因此,这一种比较好的解决方案。 目前这两种方案都有容器插件的方式部署在容器中有解决方案,但有其相应的缺点:
- 插件的版本更新不及时。
- 对容器不透明,不一样容器要适配不一样的插件。
- 插件自己的稳定性没法控制。
- 运维在配置集群时,还要特别注意相关插件的配置。增长了维护的难度。
相应的优势就是:对程序透明,开发程序时候,不用考虑集群,仍是单机环境。布置简单,没有额外的工做量。
Spring Session的使用方式
第一步:引入依赖,根据须要配置相应的存储 <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>1.3.1.RELEASE</version> <type>pom</type> <exclusions> <exclusion> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> </exclusion> <exclusion> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </exclusion> </exclusions> </dependency> 第二步:web应该配置filter过滤器。 <filter> <filter-name>springSession</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSession</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 第三步:配置相应的SPRING BEAN <bean id="springSession" class="org.springframework.session.web.http.SessionRepositoryFilter" c:sessionRepository-ref="redisOperationsSessionRepository" p:httpSessionStrategy-ref="cookieHttpSessionStrategy" /> <bean id="defaultCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer" p:cookiePath="/" /> <bean id="cookieHttpSessionStrategy" class="org.springframework.session.web.http.CookieHttpSessionStrategy" p:cookieSerializer-ref="defaultCookieSerializer" /> <bean name="redisOperationsSessionRepository" class="org.springframework.session.data.redis.RedisOperationsSessionRepository" c:redisConnectionFactory-ref="connectionFactory" p:defaultMaxInactiveInterval="${session.timeout}" />