1.无状态的价值无状态服务器意味着什么?对对象来说,它们结合了状态(数据)和行为。一个真正无状态的对象是没有成员变量的。然而,这不是人们在分布式企业应用中所指的无状态。分布式企业应用中的无状态服务器是指在各次请求之间不保存状态的对象。这样的对象也是可以有成员变量,但当你调用无状态服务器上的方法时,这些成员变量的值是没有意义的。举例,如返回一个web页面告诉你一本书的所有信息。可以通过访问一个url而发出请求,在url中你提供一个ISBN号,服务器用它产生http应答。在交互过程中,服务器对象在生成html页面之前可能记住了从数据库中得到的这本书的ISBN号,数目,单价等信息。服务器对象还可能通过业务逻辑来决定显示什么风格的页面给用户。一旦服务器对象完成工作,这些记住的信息也没什么用了。接收到下一个ISBN号就重新开始了。现在设想下,你需要记录由一个特定客户ip地址所访问的所有ISBN号,记录可以保存在服务器对象维护的一张表中。然后,这张表必须在各次请求之间保持它的值,这就成了有状态服务器对象。问题主要出在服务器的资源上。在等待用户去考虑一个web页面时,任何有状态的服务器对象都需要保存它的状态。而无状态服务器对象则可以处理来自其他会话的请求。举个例子:有100个人需要查询书籍,处理一本书的请求需要1秒钟,每个人隔10s请求一次,而且所有的请求都分布的很平均。如果我们使用有状态服务器对象来处理用户请求,就必须给每个用户分配一个服务器对象,即100个对象。但是在90%的时间里,这些对象都呆在那里不知道干什么。如果我们不做ISBN号记录而只使用无状态服务器对象来处理请求,就只需要10个服务器对象满负荷工作。结论就是:如果在请求之间不需要保存状态,就不用关心是哪个对象来处理某一次请求;如果状态需要保存,就必须找到同一对象来处理。无状态使得我们可以缓存这些对象,用很少的对象就可以处理很多的用户。空闲状态的用户越多,无状态服务器就越有用。可以想象,无状态服务器对一个高流量的网站来说非常有用。由于http是无状态的协议,因此使用无状态更加适用。所以,把应该把所有的东西都做成无状态对吗?当可以这样做的时候,答案是肯定的。问题在于很多与客户端的交互本身就是有状态的。例如购物车,购物车的信息必须在用户的整个会话中保存。实质上这是一个有状态的业务事务,也就说明会话必须是有状态的。2.会话状态购物车的内容就是会话状态,意味着车中的数据只与特定的会话有关。这种状态存在于业务事务中,与其他的会话及它们的业务事务是分开的。会话状态也区别于我们称之为记录数据的信息,记录数据是长期保存在数据库中的持久化数据,它对所有的会话都可见。会话状态需要提交成为数据库中的记录。会话状态最大的问题出现在处理隔离性的时候。不能把会话中的所有数据都看成会话状态。会话可以临时缓存实际上并不需要在各次请求间保持的数据,以便提高服务性能。由于丢失这些缓存的数据也不会影响程序的正确性,这样的数据有别于会话状态,会话状态必须在各次请求间记录以保证程序的正确执行。3.存储会话状态的方法1.客户会话状态在客户端保存数据,有几种可选的方法:在web应用中可以将数据编码在url中,使用cookie,串行化数据使其成为web表单中的某个隐藏域,或者把数据放在胖客户端的对象结构中。2.服务器会话状态在各次请求之间把数据放在内存里。通常也可以把数据以序列化对象的方式更长久的存放起来。对象可以存放在应用服务器的文件系统中,或者存放在某种共享的数据源中。可以是一张数据表,它以会话标识为关键字,以已序列化对象为值。3.数据库会话状态也是在服务器端存储的方式,但这种方式把会话数据分解成多个表和域,并把它保存在数据库汇总。上述几种方法的选择有很多值得考虑的地方。首先,考虑客户端和服务器之间所需的带宽。使用客户会话状态意味着在每次请求时必须将会话数据通过网络传输。有些数据需要传输,因为它必须在表现层可见。但使用客户会话状态意味着每次请求必须传送服务器索要用到的会话数据,即使客户端根本不用这些数据来显示。所有这些说明除非会话状态真的很少,否则不要使用客户会话状态这种方式。还应注意安全性和完整性。必须认识到恶意的用户会修改会话状态,除非对数据进行加密。会话数据必须进行隔离。大多数情况下,在一个会话中进行的动作不应该影响其他会话中的动作。实际上,会话数据的部分含义是它对会话外的任何事务都是不可见的。采用数据库会话状态时,这是个棘手的问题,因为必须花力气将会话数据与存放在数据库中的记录数据相隔离。如果系统中有很多用户,应该考虑使用集群来提高吞吐率。这种情况下还需要考虑是否需要会话迁移。会话迁移允许一次会话从一台服务器转移到另外一台服务器,从而可以由一台服务器处理一个请求,其他服务器处理其他请求。预期相反的方式是服务器亲和,它要求某次特定会话的所有请求只能由一台服务器处理。会话迁移能更好的均衡服务器,特别是会话很长的情况下。然后用服务器会话状态很难支持会话迁移,因为只有处理会话的那个服务器才能容易的找到会话的状态。也有办法处理这个问题---这类方法将模糊数据库会话状态与服务器会话状态之间的界限。服务器亲和会带来意想不到的问题。在尽量保证服务器亲和时,服务器集群并不能总是判断出每个请求所在的会话。因此,集群系统不得不提高亲和力,把来自同一个客户端的所有请求交给一台应用服务器。通常是客户端的ip,绑定到一个特定的服务器上。当发现大量的负载集中在某台服务器的时候,就知道情况变糟糕。当服务器决定使用会话状态时,需要把它转化成一种便于快速访问的形式。如果使用服务器会话状态,很容易直接访问到会话状态。如果使用客户会话状态,就需要黄钻换到你想到的格式。如果使用数据库会话状态,就要到数据库中去取信息。在一个零售系统中,每个会话也许没有那么多数据,但肯定有很多处于空闲状态的用户,因此,数据库会话能发挥很好的性能。在一个租约系统中,则会有不停读写数据库的可能,这是服务器会话性能较好。在许多系统中,最令人担心的是用户经常会取消一次会话,而且再也不会用它。在b2c的应用中经常遇到一个尴尬的问题:用户常常不会直接取消会话,而是消失的无影无踪。这时采用客户会话最合适,因为你可以很容易的忘掉那个用户。在其他方式中,必须能够发现那些被取消的会话并将它们清除掉,或者采用某种支持会话超时的系统。好的服务器会话状态实现自动支持会话超时。与用户取消会话一样,需要考虑系统失效:客户机可能崩溃,服务器可能死掉,网络连接可能突然断掉。数据库会话能很好的应付这3种情况。服务器会话状态可不可以取决于会话数据是否放到了持久的存储介质上。客户会话在客户机崩溃时无能为力,但能应付其他两种情况。还有开发代价。通常服务器会话状态是最容易使用的,特别是不需要将会话数据存储到持久介质上。数据库会话和客户会话状态则通常需要对数据进行解析和转换。
https://juejin.im/post/5c5074ea6fb9a049f23d2a96