session 是什么?
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 水平扩展
缺点:
如果 Web-server 重启, 一部分 session 会丢失, 产生业务影响, 例如部分用户重新登录
如果 Web-server 水平扩展, rehash 后 session 重新分布, 也会有一部分用户路由不到正确的 session
session 一般是有有效期的, 所有不足中的两点, 可以认为等同于部分 session 失效, 一般问题不大.
对于四层 hash 还是七层 hash, 四层 hash 比较好: 让专业的软件做专业的事情, 反向代理就负责转发, 尽量不要引入应用层业务属性.
四, 后端统一存储
思路: 将 session 存储在 Web-server 后端的存储层, 数据库或者缓存.
优点:
没有安全隐患
可以水平扩展, 数据库 / 缓存水平切分即可
Web-server 重启或者扩容都不会有 session 丢失
不足: 增加了一次网络调用, 并且需要修改应用代码.
session 读取的频率会很高, 数据库压力会比较大. 如果有 session 高可用需求, cache 可以做高可用, 但大部分情况下 session 可以丢失, 一般也不需要考虑高可用.
五, 总结
保证 session 一致性的架构设计常见方法:
session 同步法: 多台 Web-server 相互同步数据
客户端存储法: 一个用户只存储自己的数据
反向代理 hash 一致性: 四层 hash 和七层 hash 都可以做, 保证一个用户的请求落在一台 Web-server 上
后端统一存储: Web-server 重启和扩容, session 也不会丢失
Web 层, service 层无状态是大规模分布式系统设计原则之一, session 属于状态, 不宜放在 Web 层
来源: http://www.bubuko.com/infodetail-3511105.html