在REST应用程序中,每个请求必须包含服务器需要理解的所有信息,而不是依赖于服务器记住先前的请求。
在服务器上存储会话状态违反了REST体系结构的无状态约束。因此,会话状态必须完全由客户端处理。
会话状态
传统web应用程序使用远程会话。在这种方法中,应用状态完全保存在服务器上。
远程会话样式是客户机-服务器的一个变体,它试图最小化客户端组件的复杂性,或者最大限度地重用客户机组件,而不是服务器组件。每个客户端在服务器上启动一个会话,然后在服务器上调用一系列服务,最后退出会话。应用程序状态完全保留在服务器上。...
虽然这种方法带来了一些优点,但它降低了服务器的可伸缩性:
远程会话样式的优点是更容易集中维护服务器上的接口,在扩展功能时减少对已部署客户端中的不一致性的关注,如果在服务器上使用扩展的会话上下文,则提高效率。缺点是,由于存储的应用程序状态,它降低了服务器的可伸缩性,降低了交互的可见性,因为监视器必须知道服务器的完整状态。
无状态约束
REST体系结构样式定义在一组约束的顶部,其中包括服务器的无国籍状态。根据菲尔丁的说法,其余的无状态约束定义如下:
客户端到服务器的每个请求都必须包含理解请求所需的所有信息,并且不能利用服务器上存储的任何上下文。因此,会话状态完全保留在客户端上。
这个约束导致了能见度,可靠性,和可伸缩性:
可见性得到了改善,因为监控系统不必只看单个请求数据,就可以确定请求的全部性质。可靠性的提高是因为它简化了从部分故障中恢复的任务。可伸缩性得到了改善,因为不需要在请求之间存储状态,可以让服务器组件快速释放资源,并进一步简化实现,因为服务器不必管理跨请求的资源使用情况。
认证和授权
如果客户端请求需要身份验证的受保护资源,则每个请求必须包含所有必要的数据必须经过适当的认证/授权。
HTTP身份验证被认为是无状态的:验证请求所需的所有信息必须在请求中提供,而不是依赖于服务器记住先前的请求。
基于状态的Web服务
在基于状态的Web服务中,Client与Server交互的信息(如:用户登录状态)会保存在Server的Session中。再这样的前提下,Client中的用户请求只能被保存有此用户相关状态信息的服务器所接受和理解,这也就意味着在基于状态的Web系统中的Server无法对用户请求进行负载均衡等自由的调度(一个Client请求只能由一个指定的Server处理)。同时这也会导致另外一个容错性的问题,如果指定的Server在Client的用户发出请求的过程中宕机,那么此用户最近的所有交互操作将无法被转移至别的Server上,即此请求将无效化。
基于无状态的Web服务
在无状态的Web服务中,每一个Web请求都必须是独立的,请求之间是完全分离的。Server没有保存Client的状态信息,所以Client发送的请求必须包含有能够让服务器理解请求的全部信息,包括自己的状态信息。使得一个Client的Web请求能够被任何可用的Server应答,从而将Web系统扩展到大量的Client中。
总结两者的区别
因为无状态原则的特性,让RESTful在分布式系统中得到了广泛的应用,它改善了分布式系统的可见性、可靠性以及可伸缩性,同时有效的降低了Client与Server之间的交互延迟。无状态的请求有利于实现负载均衡,在分布式web系统下,有多个可的Server,每个Server都可以处理Client发送的请求。有状态的请求的状态信息只保存在第一次接收请求的Server上,所以后来同一个Client的请求都只能由这台Server来处理,Server无法自由调度请求。无状态请求则完全没有这个限制。其次,无状态请求有较强的容错性和可伸缩性。如果一台服务器宕机,无状态请求可以透明地交由另一台可用Server来处理,而有状态的请求则会因为存储请求状态信息的Server宕机而承担状态丢失的风险。Restful风格的无状态约束要求Server不保存请求状态,如果确实需要维持用户状态,也应由Client负责。
例如:
使用Cookies通过客户端保持登陆状态:
在REST中,每一个对象都是通过URL来表示,对象用户负责将状态信息打包进每一条信息内,保证对象的处理总是无状态的。在HTTP服务器中,服务器没有保存客户端的状态信息,客户端必须每次都带上自己的状态去请求服务器。客户端以URL形式提交的请求包含了cookies等带状态的数据,这些数据完全指定了所需的登录信息,而不需要其他请求的上下文或内存。
传递User credentials是Restful,而传递SessionID是Un-Restful的,因为session信息保存在服务器端。
无状态请求:Server不保存任何请求状态信息,Client的每一个请求都具有User credentials等所需要的全部信息,所以能被任意可用的Server应答。
有状态请求:Server保存了Client的请求状态,Server会通过Client传递的SessionID在Server中的Session作用域找到之前交互的信息,并以此来实现应答。所以Client只能由某一个Server来应答。