【Distributed System】分布式 Session(Distributed Seesion)

Posted by 西维蜀黍 on 2019-11-10, Last Modified on 2022-12-10

Background

Session 的作用?

Session 是客户端与服务器通讯会话跟踪技术,服务器与客户端保持整个通讯的会话基本信息。

客户端在第一次访问服务端的时候,服务端会响应一个 sessionId 并且将它存入到本地 cookie 中,在之后的访问会将 cookie 中的 sessionId 放入到请求头中去访问服务器,如果通过这个 sessionid 没有找到对应的数据那么服务器会创建一个新的 sessionid 并且响应给客户端。

分布式 Session 存在的问题?

假设第一次访问服务 A 生成一个 sessionid 并且存入 cookie 中,第二次却访问服务 B 客户端会在 cookie 中读取 sessionid 加入到请求头中,如果在服务 B 通过 sessionid 没有找到对应的数据那么它创建一个新的并且将 sessionid 返回给客户端,这样并不能共享我们的 Session 无法达到我们想要的目的。

分布式 session 管理实现方案

分布式 Session 有如下几种实现方式。

1 Session 复制

任何一个服务器上的 session 发生改变(增删改),该节点会把这个 session 的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要 session,以此来保证 Session 同步。

  • 优点:代码上不需要做支持和修改。
  • 缺点:需要对应支持 session 复制的 Web 服务器,会对网络负荷造成一定压力,如果 session 量大的话可能会造成网络堵塞,拖慢服务器性能。
  • 适用场景:只适用于 Web 服务器比较少且 Session 数据量少的情况。
  • 可用方案:开源方案 tomcat-redis-session-manager,暂不支持 Tomcat8。

2 Session 粘滞

将用户的每次请求都通过某种方法强制分发到某一个特定 Web 服务器上。具体来说,用户第一次请求时,负载均衡器将用户的请求转发到了 A 服务器上,那么用户以后的每次请求都会转发到 A 服务器上。

  • 优点:使用简单,没有额外开销。
  • 缺点:一旦某个 Web 服务器重启或宕机,相对应的 Session 数据将会丢失,而且需要依赖负载均衡机制。
  • 适用场景:对稳定性要求不是很高的业务情景。

3 Session 集中管理

在单独的服务器或服务器集群上使用缓存技术,如 Redis 存储 Session 数据,集中管理所有的 Session,所有的 Web 服务器都从这个存储介质中存取对应的 Session,实现 Session 共享。

  • 优点:可靠性高,减少 Web 服务器的资源开销。
  • 缺点:实现上有些复杂,配置较多。
  • 适用场景:Web 服务器较多、要求高可用性的情况。
  • 可用方案:开源方案 Spring Session,也可以自己实现,主要是重写 HttpServletRequestWrapper 中的 getSession 方法。

4 基于 Cookie 管理

这种方式在每次发起请求的时候,都需要将 Session 数据放到 Cookie 中传递给服务端。

  • 优点:不需要依赖额外外部存储,不需要额外配置。
  • 缺点:不安全,易被盗取或篡改;Cookie 数量和长度有限制,需要消耗更多网络带宽。
  • 适用场景:数据不重要、不敏感且数据量小的情况。

微服务架构中的分布式 session

Web 应用持续发展,虽然进行了一定的拆分,把过去单体架构的巨石应用切割成了由若干个模块组成的分布式应用,但随着不断的迭代开发,这些模块应用依然会变成巨石应用,代码维护成本直线上升。

尽管可以再次进行应用拆分,但是随着拆分的应用增多,这些应用的编译、打包、部署和整合也成为了新的难题。在这样的一个环境之下,微服务架构开始受到广泛关注。

微服务架构即将一个应用拆分成一套小而相互关联的微服务,微服务之间通过暴露出来的 API 被其他微服务或系统所调用,在运行时,每个微服务实例通常是一个云虚拟机或一个 Docker。众多微服务综合起来,构成了一个完整的微服务架构应用。

微服务架构中的微服务一般可以分为两类:无状态服务和有状态服务。无状态服务比如应用服务器,它们通常是不保存数据的,方便进行横向扩展;有状态服务需要进行数据存储,比如数据库服务和缓存服务。在 Web 应用中,Session 用来存储用户的状态信息,所以 Session 管理也是有状态服务器的一种。


在分布式架构中,Session 管理方案是将用户 Session 存放在 Web 服务器内存中,然后通过 Web 服务器的复制能力或者负载均衡器的请求分发能力来实现 Session 共享。但是在微服务架构的实践中,企业对大型应用进行微服务改造,让应用向云环境迁移,通常会将应用拆分成十几个甚至数十个微应用,如果仍然使用 Session 复制、粘滞,不但会带来很多的不必要资源开销,还会降低整个企业应用的可用性和安全性。

因此,在微服务架构下,对 Session 的管理应该另辟蹊径,不再将 Session 对象保存在 Web 服务器内存中,而是在应用服务器架构中引入独立的中间存储介质,将企业应用中的 Session 对象进行统一管理。

一个好的 Session 集中管理方案应该具备以下特点:

  • 中间存储介质的读写速度要快。之前的 Session 管理方案将 Session 对象存放在服务器内存中,有着很高的读写速度,进行 Session 集中管理后将会在 Session 读写中引入网络传输,速度会有所降低,所以必须保证中间存储介质的读写速度。
  • ** 中间存储介质要保证高可用。** 进行 Session 集中管理后,整个企业应用的 Session 都会存放在中间存储介质中,如果存储介质是不稳定的,那整个企业应用都将不稳定。
  • 对 Session 的使用者来说,Session 管理方案应该是透明的,
  • Session 管理方案不该和某一 Web 服务器耦合,应该适用于所有常规 Web 服务器。

Reference