状态与会话

作者:聂勇 欢迎转载,请保留作者信息并说明文章来源!

在客户端与服务端交互的过程中,涉及到用户的隐私和数据安全问题,服务端会进行权限校验,客户端需要提供一些能证明用户 身份的信息来给服务端进行确认。或者是用户做一个操作需要一段时间以及跨多个页面才能完成,在这段时间中,需要将用户已经完成的数据保存起来。购物车就是一个非常好的例子,用户选购不同的商品加入购物车,然后再进行结算,这中间需要比较长的时间,在用户选购的过程中,需要将用户已经选购好的商品信息全部保存起来。

不管是权限校验或购物车,它们产生的信息都在一段时间内有效,我们称之为会话信息。会话信息需要存储起来,这就带来一个问题:是由客户端存储还是服务端来存储呢?这两种不同的存储方式又各自会有怎样的问题?

客户端会话

1、B/S架构的系统

存储会话信息有如下方式:

  • Cookie。有容量限制,最多为4KB。并且会带来一个问题,增加网络带宽的消耗,因为每次发起HTTP请求时,会附带所有的cookie的信息。如果服务端修改了会话信息,在HTTP响应的时候需要将这些修改后的cookie信息发送给客户端。另外,cookie是明文的,在传输的过程中有可能会泄漏,或者用户访问某些挂有木马的网页时会被窃取这些cookie信息。
  • 隐藏字段。也存在的一些问题,一是在不同页面之间跳转时,页面之间需要相互传递数据,这不仅涉及网络带宽,还带来了系统开发和维护的复杂性。
  • HTML5的本地存储。通过Key存储数据,数据可以是JavaScript基本数据类型:Boolean、整型、浮点型、字符串,其实所有的数据类型都是用字符串来存储,所以如果要用整型或布尔型来操作,需要系统自己做转换。本地存储的容量比Cookie大得多,在HTML5的标准中,建议最大为5MB。
从Cookie到HTML5本地存储的发展路线图

2、C/S架构的系统

客户端存储会话信息没有容量的限制,可以存放在本地的内存中、文件系统或数据库中。但是如果服务端需要使用这些会话信息的时候,客户端需要将相关的数据发送给服务端。

服务端会话

不管是B/S架构还是C/S架构的系统,会话信息都可以保存在服务端,只要分配给客户端一个唯一的标识(称之为会话ID),客户端通过会话ID来进行会话信息的获取。

服务端可以将这些会话信息存储在本地内存、缓存系统或数据库中。这样就产生了一些新的问题:服务端各服务端器之间是否需要共享会话数据?如果存储在专门的缓存系统或数据库中,是否会存在单点故障以及性能问题。

状态

因为有会话信息的存在,就产生了两种情况:有状态(stateful)和无状态(stateless)。有状态的功能或模块需要解决一个问题:如何保证用户的请求分发到不同服务器时,系统都可以访问用户的会话信息。无状态是软件开发中一种非常理想的情况:通过增加新的服务器水平扩展来支撑日益增大的用户量和访问量,可以将所有的请求均衡地分发到所有的服务器上,或者根据不同服务器的性能分发不同的请求量。但实际上无状态的系统是几乎不存在的,因为只要提供给用户使用的系统,就会有会话信息的存在。

为解决有状态这个问题,有两种常用的方法:
1、每台服务器管理各自用户的会话信息,将用户每次的请求都分发到同一台服务器(Session Sticky)。
每台服务器独立管理会话

2、集中管理所有的会话信息,请求随机分发(Session Migration)至不同的服务器。
集中管理会话

参考资料