SpringSession系列-分布式 session 实现方案及 SpringSession 功能分析

上一篇文章 SpringSession:集成SpringBoot 中介绍了如何在SpringBoot中来集成 SpringSession,整个过程很是简单,同时也简单分析了下SpringSession的做用原理。继上一篇实践以后,本文主要来分析 SpringSession 的原理。html

一、从 session 的一致性方案提及

关于 sessioncookie 的一些知识,你们能够参考下我以前写的一篇文章:聊一聊session和cookiehtml5

Session做为服务器端使用的一种记录客户端状态的机制,其对客户端是透明的;可是Session 的正常运做仍然须要客户端浏览器的支持。咱们都知道,HTTP协议是无状态的,Session不能依据HTTP链接来判断是否为同一客户,所以服务器须要向客户端浏览器发送一个识别标志(sessionId),这个识别标志经过是经过Cookie机制来完成。git

1.一、session 一致性问题的由来

当用户首次访问咱们的Servlet时,应用服务器端会给用户建立一个独立的Session,而且存储在内存中。这种状况在单应用服务器场景下是能够知足的(这里不讨论其一个弊端,就是内存占用给服务器带来的压力的问题)。在集群场景下,这种机制就会到来问题:github

1.1.一、单机场景

由于是一台应用服务器,用户的每次请求都是由这台机器来处理,因此不会有session共享问题。redis

1.1.二、集群场景

假设如今集群中有三台机器,(从上到下:A->B->C)。当前用户首次发起访问时,请求被分配到 A 机器处理,Session数据被写入 A 机器的内存中;当再次发起访问 时,请求被分配的 B 处理,但此时 B 内存中并无当前用户的任何数据,这样就出现了session不一致的状况了。spring

1.二、Session 一致性问题的方案

对于当前服务化、单元化应用盛行的时代,简单的内存型的 Session 已经不可以知足咱们的要求了。那么咱们就须要寻求一种方案来替换目前单机内存存储实现的方案。数据库

1.2.1 基于 IP-HASH 的实现机制

在 1.1.2 中由于咱们没法知道请求会被分配到哪台机器来处理,因此会致使session不一致的问题出现。若是咱们能够解决让每一个用户的请求可以固定的打到某一台机器上,那么上面提到的问题其实也就不存在了。IP-HASH 就是这样一种方案。经过对请求的客户端 IP 进行 HASH 计算,并将计算结果映射到具体一台机器,这样就能够将请求固定分配到某一台机器上,从而有效的避免session一致性问题的出现。浏览器

这种方案的好处在于:缓存

  • 不须要修改任何应用代码,0 侵入。
  • 安全性高,不依赖其余三方缓存框架带来的风险
  • 成本低

可是问题也很明显,这种方式其实是规避了session一致性问题的出现,并不是是针对session一致性问题给出的解决方案。主要问题:安全

  • 基于应用内存,会给应用服务器带来必定的压力
  • 服务重启会致使session数据丢失
  • 不利于水平扩展,水平扩展也可能丢失session
  • 存在单点负载高的状况,就是多数请求通过HASH计算以后打到同一台机器,而其余机器处于空闲状态。

1.2.2 session 复制

这种方式的实现原理是应用服务器建立session以后经过组播的方式将session发送到组播地址内的其余应用服务器上。这种方式相较于IP-HASH 的方式要靠谱一点:

  • 一样不须要更改任何业务代码
  • 可以适应多种负载策略
  • 机器重启或者宕机以后不怕丢失,由于有冗余备份

可是这种方式也有比较大的问题:

  • 首先就是服务器之间同步session会占用必定的网络资源,同时session在不一样的机器之间进行同步存在延迟。
  • 仍是基于内存存储,局限于机器内存容量影响,水平扩展能力差
  • 服务器内存由于须要存储其余机器上的session数据,对内存的消耗会随着集群的规模变大而变大,可能会致使机器频繁触发GC

1.2.3 借助三方缓存框架实现 session 集中管理

上面两种方式都是有服务器本身来管理session的,主要问题仍是在于对于性能和内存的影响。而这种方式的原理是将session托管给三方软件(如redis)来统一管理。这种方式能够有效的解决性能、内存占用以及水平扩展等问题。可是由于引入了三方软件,在实现复杂度、运维成本等方面会有所增长。

目前所接触到的分布式session的实现方案,大多都是基于这种方式来实现的;SpringSession 也不例外。

二、SpringSession 功能结构分析

前面对分布式场景下的 Session一致性问题进行了说明,并对解决Session一致性的问题的几种策略进行的分析(有点糙,网上这些知识有不少)。在了解这些背景以后,咱们来看下 SpringSession 的实现原理。

2.1 简介

Spring Session 提供了用于管理用户会话信息的API和实现,在不依赖特定于应用程序容器的解决方案的状况下,使得支持群集会话变得更加简单。它还提供了透明的集成:

  • 容许以应用程序容器(Tomcat等)中立的方式替换 HttpSesseion,支持在 headers中提供 session IDs来使用 RESTful API
  • 提供在接收 WebSocket 消息时保持HTTP 会话存活的能力
  • 容许以应用程序容器中立的方式替换 Spring WebFluxWebSession

以上来自官网文档翻译 Spring Session

2.2 模块

Spring Session 主要包括 4 个模块:

  • spring-session-core :提供了 Spring Session 核心功能和API
  • spring-session-data-redis:以 redis 做为存储机制的 SessionRepository 实现
  • spring-session-hazelcast:以 Hazelcast 做为存储机制的 SessionRepository 实现
  • spring-session-jdbc:以关系型数据库做为存储机制的 SessionRepository 实现

整体来讲就是 核心API+存储实现;工程模块截图以下:

2.3 功能结构

SpringSession总体上能够分为三块:

  • 对于Web层的处理,这里包括对于请求的重写,自定义的filter加入到filter chain,cookie处理,http header处理等
  • 公共基础封装,好比存储类的顶层抽象接口定义,自定配置,事件处理等。
  • 存储部分,这部分其实是对公共基础封装接口的实现,提供了丰富的存储实现,包括redis,内存存储,jdbc等。

2.4 多 session 支持

对于经常使用的分布式session,在实现上通常会依赖于 cookie。可是在 springsession 中提供了基于header来传递jessionID的策略实现。同时在 2.0.4 版本以前,对于同一个浏览器同一个网站,springsession 支持多个session问题,可是在此版本以后抛弃了对于对 session 的支持。关于更多关于多session支持能够查看 SpringSession 的官方文档

小结

本文对分布式 session 的几种实现策略进行了简单的介绍。对于分布式 session 而言,如何解决一致性问题是关键,目前我见过的绝大多数方案均是以 【借助三方缓存框架实现 session 集中管理】 这种来实现的,包括本系列文章中所要介绍的 SpringSession。

除分布式session一致性方式解决方案的介绍以外,做为SpringSession 的第二篇文章,在这里简单分析了下Springsession的功能模块,以便后续展开对源码的分析。

相关文章
相关标签/搜索