无状态 stateless

  1. class rameshservlet extends HttpServlet{
  2. }

raemshservlet does not have any state means, its not having the instance variable and static variable, any object state depends on the instance variables and static variables.

People get doubt on rameshservlet extends HttpServlet, HttpServlet having state variables ?

HttpServlet is a abstract class and also its having instance and statice variables are private

  1. public abstract class HttpServlet extends GenericServlet implements java.io.Serializable
  2. {
  3. private static final String METHOD_DELETE = "DELETE";
  4. private static final String METHOD_HEAD = "HEAD";
  5. ...
  6. }

rameshservlet cant inherited those static variables because they are private.

rameshservlet is stateless.

Ex:2

  1. class nitservlet extends httpservlet{
  2. private int count = 0;
  3. }

nitservlet having the instance variable, so that nitservlet having the state.

Hope, you understand to make the servlet as a stateless or stateful.


一、定义

无状态服务(stateless service)对单次请求的处理,不依赖其他请求,也就是说,处理一次请求所需的全部信息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库),服务器本身不存储任何信息

有状态服务(stateful service)则相反,它会在自身保存一些数据,先后的请求是有关联的

二、优劣

有状态服务常常用于实现事务(并不是唯一办法,下文有另外的方案)。举一个常见的例子,在商城里购买一件商品。需要经过放入购物车、确认订单、付款等多个步骤。由于HTTP协议本身是无状态的,所以为了实现有状态服务,就需要通过一些额外的方案。比如最常见的session,将用户挑选的商品(购物车),保存到session中,当付款的时候,再从购物车里取出商品信息

有状态服务可以很容易地实现事务,所以也是有价值的。但是经常听到一种说法,即server要设计为无状态的,这主要是从可伸缩性来考虑的。如果server是无状态的,那么对于客户端来说,就可以将请求发送到任意一台server上,然后就可以通过负载均衡等手段,实现水平扩展。如果server是有状态的,那么就无法很容易地实现了,因为客户端需要始终把请求发到同一台server才行,所谓“session迁移”等方案,也就是为了解决这个问题

三、session和cookie

基于session和cookie都可以实现事务,可以认为,session是有状态的,而cookie是无状态的

四、无状态实现事务的方法

并不是一定要用有状态服务才能实现事务,本文提供另外的几种方案作为参考
举一个多次提交的场景作为例子:用户需要提交很多数据,分为2个页面提交

这里就涉及到2次http请求,第一次提交字段1、2、3,第二次提交字段4、5、6

用session很容易实现这个需求,server只需要将第一次提交的数据,保存在session里,然后返回第2个表单作为相应;然后取出第一次提交的数据,和第二次提交的数据汇聚以后,一起存入数据库即可

不用session同样也可以实现,server接收到第一次请求以后,将数据作为隐藏元素,放在第2个表单里返回;这样用户第2次提交的时候,就隐含地再次提交了第一次的数据;server将所有数据存入数据库
用HTML5,则还可以进一步优化,client可以将第一次提交的数据,保存在sessionStorage里
用cookie也是类似的道理,同样可以实现,但是不太好

总的来说,3种替代方案(隐藏表单元素、sessionStorage、cookie)都避免了在server端暂存数据,从而实现了stateless service。本质上,这3种方案的请求里,都包含了所有必须的数据,符合本文一开始的定义

五、将有状态服务转换成无状态服务

根据本文一开始的定义,除了将所有信息都放在请求里之外,还有另外一种方法可以实现无状态服务,即将信息放在一个单独可共享的地方,独立于server存在
比如,同样还是采取session的方式,在服务端保存数据,减少每次client请求传输的数据量(节省流量);但是将session集中存放,比如放在单独的session层里。这种情况下,server同样是无状态的,可以做水平扩展

六、无状态类

引申一下,JAVA里有一种类的设计,可以称为无状态类。这种类的特征是只有方法没有字段,在三层架构(展现层、逻辑层、持久层)里,逻辑层经常可以看到这种类
我觉得无状态类和stateless server在思想上是一样的,这个类本身是没有状态的,所以当外部要调用它的方法时,需要在方法参数中传来所需的所有信息,不依赖该类自身的状态(字段值),在并发环境下,可以避免多线程带来的副作用

七、总结

有状态服务可以比较容易地实现事务,在不需要考虑水平扩展时,是比较好的选择
无状态服务的优势在于可以很方便地水平伸缩,但是在实现事务时,需要做一些额外的动作
可以通过剥离session等方法,将一个有状态服务,转换成无状态服务

参考

  1. servlets-stateless-stateful
  2. 无状态服务
  3. how-do-stateless-servers-work