一、缘起
什么是 session ?
服务器为每个用户创建一个会话,存储用户的相关信息,以便多次请求能够定位到同一个上下文。
web 开发中, web-server 可以自动为同一个浏览器的访问用户自动创建 session ,提供数据存储功能。最常见的,会把用户的登录信息、用户信息存储在 session 中,以保持登录状态。
什么是 session 一致性问题?
只要用户不重启浏览器,每次 http 短连接请求,理论上服务端都能定位到 session ,保持会话。
当只有一台 web-server 提供服务时,每次 http 短连接请求,都能够正确路由到存储 session 的对应 web-server (废话,因为只有一台 )。
此时的 web-server 是无法保证高可用的,采用“冗余 + 故障转移”的 多台 web-server 来保证高可用时,每次 http 短连接请求就不一定能路由到正确的 session 了 。
如上图,假设用户包含登录信息的 session 都记录在第一台 web-server 上,反向代理如果将请求路由到另一台 web-server 上,可能就找不到相关信息,而导致用户需要重新登录。
在 web-server 高可用时,如何保证 session 路由的一致性,是今天将要讨论的问题。
二、 session 同步法
思路 : 多个 web-server 之间相互同步 session ,这样每个 web-server 之间都包含全部的 session
优点 : web-server 支持的功能, 应用程序不需要修改代码
不足 :
session 的同步需要数据传输, 占 内网带宽 ,有时延
所有 web-server 都包含所有 session 数据,数据量 受内存限制,无法水平扩展
有更多 web-server 时要歇菜
三、客户端存储法
思路 :服务端存储所有用户的 session ,内存占用较大,可以 将 session 存储到浏览器 cookie 中 ,每个端只要存储一个用户的数据了
优点 : 服务端不需要存储
缺点 :
每次 http 请求都携带 session , 占 外网带宽
数据存储在端上,并在网络传输,存在泄漏、篡改、窃取等 安全隐患
session 存储的数据大小受 cookie 限制
“端存储”的方案虽然不常用,但确实是一种思路。
三、反向代理 hash 一致性
思路 : web-server 为了保证高可用,有多台冗余,反向代理层能不能做一些事情,让 同一个用户的请求保证落在一台 web-server 上 呢?
方案一:四层代理 hash
反向代理层使用 用户 ip 来做 hash ,以保证同一个 ip 的请求落在同一个 web-server 上
方案二:七层代理 hash
反向代理使用 http 协议中的 某些业务属性来做 hash ,例如 sid , city_id , user_id 等,能够更加灵活的实施 hash 策略,以保证同一个浏览器用户的请求落在同一个 web-server 上
优点 :
只需要改 nginx 配置, 不需要修改应用代码
负载均衡 ,只要 hash 属性 是均匀的,多台 web-server 的负载是均衡的
可以 支 持 web-server 水平扩展 ( session 同步法是不行的,受内存限制)
不足 :
如果 web-server 重启,一部分 session 会丢失 ,产生业务影响,例如部分用户重新登录
如果 web-server 水平扩展, rehash 后 session 重新分布,也会有一部分用户路由不到正确的 session
session 一般是有有效期的,所有不足中的两点,可以认为等同于部分 session 失效,一般问题不大。
对于四层 hash 还是七层 hash ,个人推荐前者 : 让专业的软件做专业的事情 ,反向代理就负责转发,尽量不要引入应用层业务属性,除非不得不这么做(例如,有时候多机房多活需要按照业务属性路由到不同机房的 web-server )。
四、后端统一存储
思路 : 将 session 存储在 web-server 后端的存储层 ,数据库或者缓存
优点 :
没有安全隐患
可以水平扩展 ,数据库 / 缓存水平切分即可
web-server 重启或者扩容都 不会有 session 丢失
不足 :增加了一次网络调用,并且 需要修改应用代码
对于 db 存储还是 cache ,个人推荐后者 : session 读取的频率会很高,数据库压力会比较大。如果有 session 高可用需求, cache 可以做高可用,但大部分情况下 session 可以丢失,一般也不需要考虑高可用。
五、总结
保证 session 一致性 的架构设计常见方法:
session 同步法 :多台 web-server 相互同步数据
客户端存储法 :一个用户只存储自己的数据
反向代理 hash 一致性 :四层 hash 和七层 hash 都可以做,保证一个用户的请求落在一台 web-server 上
后端统一存储 : web-server 重启和扩容, session 也不会丢失
对于方案 3 和方案 4 ,个人建议推荐后者 :
web 层、 service 层无状态是大规模分布式系统设计原则之一 , session 属于状态,不宜放在 web 层
让专业的软件做专业的事情 , web-server 存 session ?还是让 cache 去做这样的事情吧
希望大伙有收获,思路比结果重要,帮转哟。
来源: http://www.tuicool.com/articles/fQnauiV