21-登录功能功能架构设计七(集群/分布式基于Session的登录)
xiangliheart
xiangliheart
发布于 2022-04-15 / 13 阅读 / 0 评论 / 0 点赞

21-登录功能功能架构设计七(集群/分布式基于Session的登录)

集群/分布式架构基于Session的登录设计

Session是进行会话控制、用户追踪的重要手段。在单体架构中使用Session十分简便快捷,是登录权限控制的重要手段。但是,在集群架构、分布式架构中却会面临Session不一致的问题,可以通过Session 同步、Session共享的方式来解决这个问题。

4.8.1 Session的工作原理

客户端的接口请求大体分为两类,一类需要用户登录后才可以访问,另一类不需要登录即可访问。对于第一类接口请求就需要服务端

具有会话保持的能力,而Session就是一种常用的会话保持技术,

Session会话保持原理如图4-29所示。

(1)   客户端登录,提交用户名和密码。

(2)   服务端保存生成Session,并且将Session存储在内存中。

(3)   服务端将session_id返回给客户端。

(4)   客户端自动将session_id存储到Cookie中。

(5)   客户端的所有后续请求均会携带Cookie。

(6)   后端通过Cookie中的session_id获取Session信息,进而校验用户状态是否依然保持,并延长用户状态保持的有效期。

图4-29 Session会话保持原理

传统的Session方式的优点是实现简单,开发成本低,然而缺点也比较突出,可以总结为以下6点。

(1)   基于服务器内存,难以水平扩展和集群化。

(2)   高并发、用户使用量大时会导致Session大量占用内存,降低服务器性能。

(3)   Cookie可能被禁用或被用户删除。

(4)   Cookie安全性不够高,可以被截取和篡改。

(5)   Cookie存储空间很小,长度和数量都有限制。

(6)   Web浏览器的Cookie可以自动管理,原生端要自己实现

Cookie管理。

Session模式比较适用于单体架构开发,用户量小、访问量小的内部系统使用,实现简单。下面将重点针对集群架构/分布式架构下的

Session进行讲解。

如果读者对Cookie不了解,则可以先阅读以下基础知识内容。

1.  Cookie的概念

Cookie是一段不超过4kB的小型文本数据(不同浏览器有所区别,一般为4095~4097B),保存在浏览器中,经常用于存储用户相关信息、Token、SessionID等。不同浏览器对于每个域能存储的Cookie数量限制也不相同。例如,IE6浏览器每个域能存储30个Cookie,Chrome浏览器每个域能存储53个Cookie,而Safari浏览器则没有数量限制。

2.  Cookie的组成和格式

如上所示,一个Cookie由六部分组成:名称、值、域、失效时间、路径和安全标志。

(1)     名称(name):一个唯一确定的Cookie的名称,不区分大小写。

(2)     值(value):数据字符串,最好加密存储。

(3)     域(domain):Cookie对于哪个域是有效的,如果没有设置,则默认为设置Cookie的那个域。

(4)     失效时间(expires):设定Cookie在什么时间失效,失效后即被删除。expires代表具体失效时间,Max-Age代表在多少秒之后

Cookie失效,Max-Age的优先级大于expires。当Max-Age=-1时,代表永不失效。

(5)     路径(path):代表访问哪些域的路径会自动携带Cookie数据发送给服务端,“/”表示没有限制。

(6)     安全标志(secure):设置之后只有在使用SSL连接

(HTTPS)时才会自动携带Cookie数据发送给服务端。

3.如果存储的Cookie数量已经达到上限,继续存储会怎样?

Safari浏览器没有Cookie数量限制,因此不存在这个问题。

IE和Opera浏览器使用LRU(Least Recently Use,最近最少使用)

算法,当Cookie达到上限后,自动删除最旧、使用最少的Cookie,从而给新Cookie留出空间。

Firefox浏览器保留最后设置的Cookie数据,随机删除Cookie数据,官方并没有明确说明删除算法。

4.8.2 集群/分布式架构下的Session设计

在集群架构和分布式架构下使用Session会引发哪些问题,这些问题是如何产生的,怎样才能够解决这些问题呢?

1.在集群负载架构下Session会引发什么问题?

如图4-30所示,随着订单服务压力的上升,决定将原来的1个节点扩充为2个节点,以集群的方式对外提供服务,使用Nginx做反向代理

(Nginx默认使用轮询策略)。

(1)     用户登录时访问了订单服务A,登录成功后Session信息保存在A服务器的内存中。

(2)     当用户查询自己的订单信息时,通过Nginx的轮询策略,请求转发给了订单服务B,但是B服务器中并没有存储用户的Session信息,所以认为用户还没有登录,直接跳转到登录页面。

图4-30 集群模式下的Session不同步

2.在分布式架构下是否也具有相同的问题?

如图4-31所示,在分布式架构下,用户登录时访问了用户微服务,登录成功后Session信息保存在用户微服务的内存中。当用户查询自己的订单信息时,会请求订单微服务,但是此服务的内存中并没有存储

用户的Session信息,所以认为用户还没有登录,直接跳转到登录页面。可见,无论是在集群负载构架还是在分布式架构下,都面临着相同的问题。

图4-31 分布式模式下的Session不同步

这就是典型的Session迁移和Session共享问题,如果需要进行会话保持,就要保证每个服务器都能够获取用户的Session信息。解决方案主要有4种:Session同步、负载控制、共享存储和抽象

Session服务。

(1)     Session同步。

如图4-32所示,在集群架构下,用户登录成功后,订单服务A存储 Session,并将Session同步给订单服务B和C,因此任意服务器上产生新的Session数据,都要通知给其他全部节点。如果有N个服务器,就要通知给N-1个节点。当服务节点非常多时,用户登录请求一旦增加,就会引发消息风暴,系统性能急剧下降,并且必须考虑Session同步过程中可能发生的各种网络问题。

因此,这种方案只适用于用户数量较少,2~3台的小型集群架构使用,多于3台时出现问题的概率就会急剧上升。

图4-32 集群模式下的Session同步

(2)     负载控制。

集群架构只需要修改Nginx的分发策略,让同一个客户端的请求全部转发到同一个服务器即可,主要使用哈希策略,如IP哈希策略或其他基于用户标识的哈希策略。

IP哈希策略的目的是将相同IP来源的用户请求始终只转发到同一台服务器上。例如,用户首次访问系统时请求转发给了服务A,那么后续所有请求,只要客户端IP不变则全部转发到服务A中。这样就不需要进行Session同步,也可以与客户端保持会话。

但是,这种方案会导致比较严重的流量倾斜问题,可能存在大量的请求发往服务A,而只有少量请求发往服务B,从而导致服务A的性能急剧下降,而服务B却十分空闲。

如图4-33所示,来源于客户端10.1.2.3的请求,全部被转发至订单服务A中。

图4-33 集群模式下Session同步方案

另外,这种方案只适用于集群架构,而不适用于分布式架构。如果修改了网关的转发策略,让相同IP的请求始终转发给同一个微服务,由于每个服务端节点不具备全部的功能,从而无法达到要求。如图4-34所示,用户第一次查询订单的请求被转发到用户微服务,第二次查询订单的请求也被转发到用户微服务,而用户微服务并不具备查询订单的能力,因此无法提供服务。

图4-34 分布式模式下的Session共享问题

(3)     共享存储。

在集群架构下,用户登录时服务端可以将Session信息不存储到本机内存中,而是存储到关系型数据库(MySQL、Oracle等)或NoSQL 数据库(Redis、Memcached等)中。当用户进行业务访问时,各个服务端节点就可以从这些共享存储设备中获取Session信息,从而完成会话保持,如图4-35所示。

图4-35 集群模式下的Session共享策略

在分布式架构下,用户登录时访问用户微服务,并将Session信息存储到共享设备中,当访问其他微服务时,就可以从共享设备中读取,也可以完成会话保持,如图4-36所示。

图4-36 分布式模式下的Session共享策略

(4)     抽象Session服务。

可以将Session共享存储设备替换为Session服务,由此服务统一提供Session的创建、保存、查询、对比服务。使用Session服务的好处是可以开发很多附加功能,如Session的可视化管理、Session的监控统计等。同时,支持单体架构、集群架构、微服务架构,如图4-37所示。

图4-37 抽象Session共享服务策略

方案选型使用原则:对于小型系统,推荐采用方案(1)和

(2);对于大型系统,推荐采用方案(3)和(4)。


评论