对于REST中无状态(stateless)的一点认识(转)

  在请求中传递SessionID被广泛认为是unRESTful的,而将用户的credentials包含在每一个请求里又是一种很是RESTful的作法。这样一个问题常常会形成困扰。本文就REST的一些概念进行了探讨,解释了REST架构中的状态,无状态(stateless),以及两种状态的区别后端

  

  今天早上在Yahoo的邮件列表里看到一篇很有意思的讨论,标题为RESTful vs. unRESTful: Session IDs and Authentication(51CTO编者注:意为REST对非REST,Session ID与验证)。文中让发起讨论的朋友大惑不解的是这样一个问题:为何在请求中传递SessionID被广泛认为是unRESTful的,而将用户的credentials包含在每一个请求里又是一种很是RESTful的作法。看了他接下来对于REST架构风格中"statelessness"属性的理解后,我以为有必要对这个常常会被人误解词汇以及相关概念作一个简要的整理,但愿可以经过这篇随笔解释清楚什么是状态,为何要实现无状态,以及REST风格架构中的两种状态的区别,最后我会从个人理解出发来回答做者提出的这个问题。浏览器

  首先,一个Web应用程序协议的“状态”在一般指的是为两个相互关联的用户交互操做保留的某种公共信息,它们经常被用来存储工做流或用户状态信息等数据。这些信息能够被指定不一样的做用域如page,request,session或全局做用域,而存储他们的责任也一样能够由Client端或Server端负责。虽然存储状态为企业软件开发带来了诸多便利,可是它也给分布式系统的其余方面带来了许多限制,好比在负载均衡方面,在有状态的模式下,一个用户的请求必须被提交到保存有其相关状态信息的服务器上,不然这些请求可能没法被理解,这也就意味着在此模式下服务器端没法对用户请求进行自由调度。于此相关的另外一个问题是容错性,假若保有用户信息的服务器宕机,那么该用户最近的全部交互操做将没法被透明地移送至备用服务器上,除非该服务器时刻与主服务器同步所有用户的状态信息。此外,因为HTTP自己不是一个有状态的协议,开发人员必须经过模拟实现状态的钝化与激活等。因而为了克服这些不足,无状态(Statelessness)架构风格属性受到了普遍关注。安全

  无状态指的是任意一个Web请求必须彻底与其余请求隔离,当请求端提出请求时,请求自己包含了相应端为相应这一请求所需的所有信息。这一约束的出现改善了分布式系统的可见性、可靠性以及可伸缩性,具体的介绍能够参考Roy T. Fielding博士的论文,这里就不哆嗦了。这些从整个系统角度来看无状态彷佛过于抽象,那么对于用户来讲,怎么感受的有状态与无状态的差异呢。简单的方法是浏览器的后退按钮,若是一个网站指望用户以A->B->C的流程来交互,而在执行至B时回退的话,那么系统颇有可能不是按照其所指望的方式运行,由于用户的状态可能被不可逆地修改了。反过来,搜索引擎(我指的是普通意义上的搜索引擎,而不是根据用户搜索历史个性化了的)是一个无状态架构的范例。任何用户能够在浏览器地址栏中输入http://www.google.com/search?q=RESTful&start=100来得到从第一百条开始的关于RESTful的记录,而且当Google摩洛哥服务器瘫痪时,相关用户请求会被透明地移送至其余服务器。服务器

  一切彷佛很明了,那么是什么致使了那位朋友的误解呢,答案是RESTful架构对于state的两个不一样的解释: 应用状态(Application State)和资源状态(Resource State)。应用状态指的是与某一特定请求相关的状态信息,而资源状态则反映了某一存储在服务器端资源在某一时刻的特定状态,该状态不会由于用户请求而改变,任何用户在同一时刻对该资源的请求都会得到这一状态的表现(Representation)。RESTful架构要求服务器端不保有任何与特定HTTP请求相关的资源,因此应用状态必须由请求方在请求过程当中提供。那么再回到那个邮件列表中的问题,为何传递一个session ID是违背REST架构风格而传递user credentials却不是。我想做者的疑惑源于他没有分清什么是有状态和无状态的架构属性,而认为“传递某种表示状态的信息”到服务器即是“有状态”的表现。其实有状态和无状态与请求自己没有多大关联,重要的是状态信息是由请求方仍是响应方负责保存。在Session ID能够被认为是一个用来标识某一会话状态的Key,将其传递给服务器端意味着这样一个请求:“请帮我取出这个状态信息”,也就是说这个请求假设响应方保有着状态信息。因为与某一特定请求相关的状态属于应用状态,而RESTful架构要求任何此类状态由请求方负责提供,因此传递Session ID被认为是unRESTful的作法。反过来,user credential做为一种应用状态,是被指望由请求方提供的,因此在请求中传递user credentials(姑且忽略安全性问题)是符合RESTful架构规范的。session

  这篇随笔或多或少散发着某种纯粹主义的味道,但我以为有些概念是值得玩味的。任何一种架构风格的出现都有其指望的,对现有方案的改进或指望克服的问题。做为REST来讲,它所指望的是组件的可伸缩性,组件的独立部署,接口统一等特性,而无状态做为实现这组需求的一个特性,我的认为是有必要清楚了解并实际开发过程当中落实的。架构

 

  RESTful 架构中须要分离出 OAuth 服务,将全部的应用认证统一管理,后续的每次请求都须要经过受权服务,再转向到服务器,进行权限管理,这样,就能够将应用的验证状态分离出来,使得后端分布式变为无状态方式,以后的负载或者其余的处理,更加简单,可是,分离出来,架构复杂度提高,维护和开发、测试的成本增长负载均衡

 

原文地址:http://developer.51cto.com/art/200906/129424.htmless

相关文章
相关标签/搜索