play 无状态的体系结构

来由

HTTP 协议本身就被设计成无状态的,采用请求/响应的模式

不同的请求之间并不存在相互关系

但是这种架构模式在开发某些 Web 应用的时候不是很方便,有些应用要求用户进行认证登录之后才能进行某些操作

同样的 URL,认证和未认证用户看到的内容是不同的,而且用户认证成功之后,他应该在一段时间内保持这种认证状态,否则的话,用户每次都需要输入用户名和密码才能访问受限的内容

对于这种情况,很多 Web 开发框架提供了会话的支持,允许应用保存一些与会话相关的数据

Java Servlet 规范中的 javax.servlet.http.HttpSession 就是一种会话的接口,应用的服务器会负责维护每个会话相关的数据

这些数据可以通过一个会话 ID 来进行标识.这个标识会利用浏览器的 cookie 机制保存在浏览器端,也可以作为请求 URL 的参数来传递

服务器端通过此标识来识别每个会话,在处理相应的请求的时候,就可以根据会话 ID 来获取保存在服务器端上的会话数据

问题

会话机制的问题是会影响应用的可伸缩性

如果一个应用使用多台服务器的话,就需要额外的机制来保证同一用户在不同机器上面的会话是同步的

而无状态的实现则不存在这个问题,对于某一个请求,由不同机器来处理的结果都是相同的

play

Play 框架的设计架构就是无状态的

它没有提供服务器端的机制用来维护跨多个请求的数据,如果确实需要保存这样的数据的话,可以考虑下面几种方案:

保存在 Session 或 Flash 作用域中

Play 框架中仍然有会话的机制,但是并没有提供在服务器端保存会话数据的能力

会话数据是保存在浏览器的 cookie 中的,由浏览器在每次请求的时候自动发送.

通过这种方式来达到维护会话数据的目的.由于会话数据是保存在 cookie 中,其大小是有限制的,一般不能超过 4K 字节,而且只能保存字符串类型的数据

Flash 作用域和会话一样,也是通过 cookie 来保存的

所不同的是,Flash 作用域中的数据只在下次请求中是有效的.

保存在持久化的数据存储中

保存在持久化的数据存储中,比如数据库中,或者 memcached 中

如果需要在多个请求中使用同一个领域对象的话,可以把这个对象的 ID 保存在 Session 或 Flash 作用域中,而在控制器动作方法中使用此 ID 来从数据库中查询相应的对象

  保存在暂时性数据存储中,如缓存中.Play 框架内置了缓存的支持,通过调用类 play.cache.Cache 就可以对缓存进行操作.与使用持久化存储类似,缓存中的键的值可以保存在 Session 或 Flash 作用域中.

  对于熟悉了 Java Servlet 规范的开发人员来说,需要一些时间来适应 Play 框架的这种无状态的体系结构.不过这种结构对于应用的可伸缩性来说,确实是非常有好处的.