服务的无状态性,即:
-服务端不保存任何客户端请求者信息
- 客户端的每次请求必须具备自描述信息,通过这些信息识别客户端身份
带来的好处是什么呢?
• 客户端请求不依赖服务端的信息,任何多次请求不需要必须访问到同一台服务
-服务端的集群和状态对客户端透明
-服务端可以任意的迁移和伸缩
-减小服务端存储压力
什么是有状态?
有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如 tomcat 中的 session。
例如登录:用户登录后,我们把登录者的信息保存在服务端 session 中,并且给用户一个 cookie 值,记录对应的 session。然后下次请求,用户携带 cookie 值来,我们就能识别到对应 session,从而找到用户的信息。
缺点是什么?
• 服务端保存大量数据,增加服务端压力
• 服务端保存用户状态,无法进行水平扩展
• 客户端请求依赖服务端,多次请求必须访问同一台服务器
状态化的判断是指两个来自相同发起者的请求在服务器端是否具备上下文关系。
如果是状态化请求,那么服务器端一般都要保存请求的相关信息,每个请求可以默认地使用以前的请求信息。
而无状态请求则不行,服务器端所能够处理的过程,他的处理信息必须全部来自于请求所携带的信息以及其他服务器端自身所保存的、并且可以被所有请求所使用的公共信息。
无状态的服务器程序,最著名的就是WEB服务器。
状态化的服务器有更广阔的应用范围,比如MSN、网络游戏等服务器。他在服务端维护每个连接的状态信息,服务端在接收到每个连接的发送的请求时,可以从本地存储的信息来重现上下文关系。
REST架构设计是目前非常火热的概念,已经成为构建web服务时应该遵循的事实标准。REST约束中有一条很重要的规则是“无状态”,但“无状态”是个很抽象的概念,对刚刚接触的人来讲,很难深刻形象的理解。今天在网上看了一篇文章,对于“无状态”的解释感觉很容易让人理解,特把文章中相关内容整理了下。
- "状态"的概念是什么
一个Web应用程序协议的“状态”通常指的是为两个相互关联的用户交互操作保留的某种公共信息,它们常常被用来存储工作流或用户状态信息等数据。这些信息可以被指定不同的作用域如page,request,session或全局作用域,而存储他们的责任也同样可以由Client端或Server端负责。
服务调用过程中有两种“状态”:应用状态(Application State)和资源状态(Resource State)。
应用状态指的是与某一特定请求相关的状态信息,
资源状态则反映了某一存储在服务器端资源在某一时刻的特定状态,该状态不会因为用户请求而改变,任何用户在同一时刻对该资源的请求都会获得这一状态的表现(Representation)。
RESTful架构要求服务器端不保有任何与特定HTTP请求相关的资源,所以应用状态必须由请求方在请求过程中提供。
例如session ID可以被认为是一个用来标识某一会话状态的Key,将其传递给服务器端意味着这样一个请求:“请帮我取出这个状态信息”,也就是说这个请求假设响应方保有着状态信息。
由于与某一特定请求相关的状态属于应用状态,而RESTful架构要求任何此类状态由请求方负责提供,所以传递Session ID被认为是unRESTful的做法。
而用户的身份凭证信息作为一种应用状态,是被期望由请求方提供的,所以在请求中传递用户的身份凭证信息是符合RESTful架构规范的。 - 为什么要使用无状态的架构
虽然存储状态为企业软件开发带来了诸多便利,但是它也给分布式系统的其他方面带来了许多限制,比如在负载均衡方面,在有状态的模式下,一个用户的请求必须被提交到保存有其相关状态信息的服务器上,否则这些请求可能无法被理解,这也就意味着在此模式下服务器端无法对用户请求进行自由调度。于此相关的另一个问题是容错性,倘若保有用户信息的服务器宕机,那么该用户最近的所有交互操作将无法被透明地移送至备用服务器上,除非该服务器时刻与主服务器同步全部用户的状态信息。此外,由于HTTP本身不是一个有状态的协议,开发人员必须通过模拟实现状态的钝化与激活等。于是为了克服这些不足,无状态(Statelessness)架构风格属性受到了广泛关注。 - 无状态即各自维护自身的状态,如会话信息都在客户端,服务端并不保存状态信息,那么我们可以说服务端是无状态的,这个的好处是显而易见的,无状态的部分可以很方便的被替换掉(或集群、横向扩展)而不用状态重建(或同步),大大提高了可申缩性(scalability);通常J2EE的session被认是不好的设计,大部份J2EE中间件在集群时都需要进行session同步,而Play!并非基于J2EE体系设计的,则没有该烦恼!
对服务器程序来说,有两个基本假设十分重要,究竟服务器是基于状态请求还是无状态请求。状态化的判断是指两个来自相同发起者的请求在服务器端是否具备上下文关系。
如果是状态化请求,那么服务器端一般都要保存请求的相关信息,每个请求可以默认地使用以前的请求信息。
而无状态请求则不行,服务器端所能够处理的过程,他的处理信息必须全部来自于请求所携带的信息以及其他服务器端自身所保存的、并且可以被所有请求所使用的公共信息。
无状态的服务器程序,最著名的就是WEB服务器。每次HTTP请求和以前都没有啥关系,只是获取目标URI。得到目标内容之后,这次连接就被杀死,没有任何痕迹。在后来的发展进程中,逐渐在无状态化的过程中,加入状态化的信息,比如COOKIE。服务端在响应客户端的请求的时候,会向客户端推送一个COOKIE,这个COOKIE记录服务端上面的一些信息。客户端在后续的请求中,可以携带这个COOKIE,服务端可以根据这个COOKIE判断这个请求的上下文关系。COOKIE的存在,是无状态化向状态化的一个过渡手段,他通过外部扩展手段,COOKIE来维护上下文关系。
状态化的服务器有更广阔的应用范围,比如MSN、网络游戏等服务器。他在服务端维护每个连接的状态信息,服务端在接收到每个连接的发送的请求时,可以从本地存储的信息来重现上下文关系。这样,客户端可以很容易使用缺省的信息,服务端也可以很容易地进行状态管理。比如说,当一个用户登录后,服务端可以根据用户名获取他的生日等先前的注册信息;而且在后续的处理中,服务端也很容易找到这个用户的历史信息。
状态化服务器在功能实现方面具有更加强大的优势,但由于他需要维护大量的信息和状态,在性能方面要稍逊于无状态服务器。无状态服务器在处理简单服务方面有优势,但复杂功能方面有很多弊端,比如,用无状态服务器来实现即时通讯服务器,将会是场恶梦。
这些年,在金融软件行业发展,对这些行业软件的开发倍感古怪。原来是一家资讯公司,虽然是行业垄断地位,但是他们的技术架构倒没有什么特别之处,只能说很一般。最近在一家交易软件公司,也是行业垄断地位,技术架构极其古怪,倒值得说道和探讨。
交易软件的所有架构的理论基础是基于无状态假设,主要分为3个层次:
1、虚拟网络。这是最底层的基于架构,在原有的TCP/IP网络上构建了一个虚拟的TCP/UDP网络,这个概念和VPN很像。但也有很多不同。比如虚拟网络上的节点和节点所接入的实体是按数字化的标识来区别。
2、业务中心。在虚拟网络上,建立一个业务逻辑中心,管理所有的业务逻辑单元。这个中心本身不处理业务逻辑,而是一个业务逻辑的管理器。
3、业务单元。这个组件是专门实现各个业务逻辑的单元。业务单元本身是建立在业务中心的基础上。本身具有一定的独立性,但主要功能还是被绑定在业务中心上。业务中心相当于他的容器。
这3个层次之间消息传输都是无状态的,当客户端从虚拟网络上发起一个请求之后,这个请求在整个传输过程中,都被认为是携带了完整的信息。这样的处理有个好处,允许传输层次进行负载均衡,自由路由,为虚拟网络的建设提供了很大的弹性。
在业务中心和业务单元之间也是这样的。他们之间的关系借鉴了MQ的架构。每个消息都是一个完整的、独立的处理单位。这种架构由于耦合性低,所以实现难度比较低,错误发生的概率也改善很多。但从另外一方面来说,要获取信息的难度却加大了。比如一个业务逻辑想知道哪些客户端在线,几乎是不可能的事情。
由于客户端之间的状态是不可知的。所以主动推送需要十分复杂的过程才能实现。不能简单地做到主动推送,轮询就成为主要的手段。当轮询被频繁地使用之后,系统的实时性就无法保证了。
当然,我在这里不是为了对状态化和无状态化的服务器要分个三六九等,实际上他们都有自己适用的范围。但各个觉得,只要状态化的服务器的技术风险能够被克服,应该具备更广阔的前景,应该是个未来的发展方向。从交易软件的架构,我还是认为他是个比较成功的应用,毕竟是得到事实的检验。但在具体过程中遇到的很多问题,还是和他的无状态假设有关。感觉这种架构是将错误发生的时间和地点给延后了,而不是消灭。
在这种系统中,状态化依然是最好的架构,但是难度是同样巨大。