如何维护应用程序状态
如何维护应用程序状态
当您在阅读关于REST 的文章时,经常得到这样的建议——在客户端保存应用程序状态。但什么是“应用程序状态”?应当如何在客户端保存这些状态?本节描述了保存应用程序状态的最佳实践。
问题描述
您想知道如何管理RESTful
Web 服务的状态,这样就不需要依赖于服务器内存中的会话了。
解决方案
将应用程序状态编码到URI
里,并通过链接在表述中包含这些URI(见第5 章)。让客户端使用这些URI 与资源进行交互。如果状态过大,或出于安全或隐私考虑不能在网络中传输,则可以在持久化存储(如数据库或文件系统)中存储应用程序状态,并将其状态的引用编码在URI 中。
问题讨论
考虑一个简化的汽车保险应用,假定其中涉及两个步骤。第一步,客户端提交一个带有司机和车辆细节信息的请求,服务器返回一个一周内有效的报价。第二步,客户端提交购买保险的请求。在这个例子中,应用程序的状态就是报价。服务器需要知道从第一个步骤返回的报价,基于它才能给出第二个请求中的保单。
应用程序状态是服务器需要在每个客户端的每个请求之间维护的状态。在客户端保持这个状态并不意味着要像ASP.NET 和JavaServer Faces 之类的Web 框架所做的那样,把会话状态序列化到URI 或HTML 表单中。
由于HTTP 是无状态协议,每个请求与之前的请求都是独立的。然而,交互应用程序通常要求客户端执行时遵循特定顺序。这就要求服务器在协议之外暂时存储每个客户端在步骤序列里的当前位置。这里的诀窍是管理状态,这样就可以在可靠性、网络性能和可扩展性之间寻求平衡。
资源表述中的链接是保持应用程序状态的最好地方,如下所示:
# 请求
POST /quotegen HTTP/1.1
Host: www.example.org
Content-Type:
application/x-www-form-urlencoded
fname=...&lname=...&..
# 响应
HTTP/1.1 200 OK
Content-Type: application/xml;charset=UTF-8
<quote
xmlns:atom="http://www.w3.org/2005/Atom">
<driver>
...
</driver>
<vehicle>
...
</vehicle>
<offer>
...
<valid-until>2009-10-02</valid-until>
<atom:link
href="http://www.example.org/quotes/buy?quote=abc1234"
rel="http://www.example.org/rels/quotes/buy"/>
❶
</offer>
</html>
❶ 一个包含应用程序状态的链接
在这个例子中,服务器把报价保存在数据存储里,并将主键编码在URI 中。当客户端使用该URI发起请求购买保险时,服务器可以通过这个主键恢复该应用程序状态。
应当选择形如数据库或文件系统的持久化存储来保存应用程序状态。使用缓存或内存会话这样的非持久化存储会降低Web 服务的可靠性,例如在服务器重启时状态可能会丢失,非持久化存储解决方案也会降低服务器的可扩展性。
如果报价所需的数据量很小,服务器可以将状态编码在URI 中,正如稍后代码所展示的那样。
当在数据库中保存应用程序状态时,使用数据库复制(replication)以便所有服务器实例都可以访问这些状态。如果应用程序状态不是永久的,可能需要在某些地方清理这些状态。
# 请求
GET
/quotegen?fname=...&lname=...&... HTTP/1.1
Host: www.example.org
# 响应
HTTP/1.1 200 OK
Content-Type: application/xml;charset=UTF-8
<quote
xmlns:atom="http://www.w3.org/2005/Atom">
<driver>
...
</driver>
<vehicle>
...
</vehicle>
<offer>
...
<valid-until>2009-08-02</valid-until>
<atom:link
href="http://www.example.org/quotes/buy?fname=...&lname=...&..."
rel="http://www.example.org/quotes/buy"/>
</offer>
</html>
因为客户端需要在每个请求中发回以上这些数据,在链接中编码应用程序状态会降低网络性能。然而这样可以提高可扩展性,因为服务器不需要保存任何数据;也可以提高可靠性,因为服务器不需要使用复制。可以基于特定用例和状态数量,组合以上两种方式来管理应用程序状态,保持网络性能、可扩展性和可靠性之间的平衡。
本文节选自《RESTful Web Services Cookbook中文版 》一书
图书详细信息:http://www.cnblogs.com/broadview/archive/2011/09/27/2193380.html