「数据一致性」和「高可用」其实本质是一个通过提升复杂度让整体更完善的方式。本文主要讲一些让系统更简单,更容易维护的东西——「易伸缩」,首当其冲的主题就是「stateless」,也叫「无状态」。
1. 服务的有状态和无状态
1.1 无状态服务
客户端的每次请求必须具备自描述信息,通过这些信息识别客户端身份。服务端不保存任何客户端请求者信息。
无状态的好处
- 客户端请求不依赖服务端的信息,任何多次请求不需要必须访问到同一台服务
- 服务端的集群和状态对客户端透明 = 服务端可以任意的迁移和伸缩 = 减小服务端存储压力
1.2 有状态服务
有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如 tomcat 中的 session。
例如 登录:用户登录后,我们把登录者的信息保存在服务端 session 中,并且给用户一个 cookie 值,记录对应的 session。然后下次请求,用户携带 cookie 值来,我们就能识别到对应 session,从而找到用户的信息。
有状态的缺点
- 服务端保存大量数据,增加服务端压力
- 服务端保存用户状态,无法进行水平扩展
- 客户端请求依赖服务端,多次请求必须访问同一台服务器
状态化的判断是指两个来自相同发起者的请求在服务器端是否具备上下文关系。
- 如果是状态化请求,那么服务器端一般都要保存请求的相关信息,每个请求可以默认地使用以前的请求信息。
- 而无状态的请求,服务器端的处理信息必须全部来自于请求所携带的信息以及可以被所有请求所使用的公共信息。
有状态和去状态对比
无状态的服务器程序,最著名的就是WEB服务器。
状态化的服务器有更广阔的应用范围,比如MSN、网络游戏等服务器。他在服务端维护每个连接的状态信息,服务端在接收到每个连接的发送的请求时,可以从本地存储的信息来重现上下文关系。
纯函数式编程,就是无状态的。有状态,也叫有副作用。
无状态的服务易伸缩: 很容易的通过给后端添加服务器和前端的负载均衡实现横向的扩展。当系统中存在着大量「有状态」的业务处理过程时,伸缩扩展就会变得复杂起来。
2. 对象的有状态和无状态
2.1 什么是有状态和无状态
-
有状态 就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
-
无状态 就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象.不能保存数据,是不变类,是线程安全的。
通过代码加深理解
2.2 有状态对象(Stateful Bean)
/**
* @contract: 公众号:Java半颗糖
* @desc: 有状态bean,有state,user等属性,并且user有存偖功能,是可变的。
* @link:
*/
@Getter
@Setter
public class StatefulBean {
public int state;
// 由于多线程环境下,user是引用对象,是非线程安全的
public TestParam param;
}
2.3 无状态对象(Stateless Bean)
/**
* @contract: 公众号:Java半颗糖
* @desc: 无状态bean,不能存偖数据。因为没有任何属性,所以是不可变的。只有一系统的方法操作
* @link:
*/
public class StatelessBeanService {
// 虽然有 orderService 属性,但borderService 是没有状态信息的,是Stateless Bean.
OrderService orderService;
public List<TestParam> findUser(String Id) {
return null;
}
}
3. Spring 中有状态和无状态
通过上面的分析,相信大家已经对有状态和无状态有了一定的理解。
- 无状态的Bean 适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。
- 有状态的Bean 多线程环境下不安全,那么适合用Prototype原型模式。Prototype: 每次对bean的请求都会创建一个新的bean实例。
默认情况下,从Spring bean工厂所取得的实例为singleton(scope属性为singleton),容器只存在一个共享的bean实例。
理解了两者的关系,那么scope选择的原则就很容易了:有状态的bean都使用prototype作用域,而对无状态的bean则应该使用singleton作用域。
如Service层、Dao层用默认singleton就行,虽然Service类也有dao这样的属性,但dao这些类都是没有状态信息的,也就是相当于不变(immutable)类,所以不影响。
Struts2 中的Action因为会有User、BizEntity这样的实例对象,是有状态信息的,在多线程环境下是不安全的,所以Struts2默认的实现是Prototype模式。在Spring中,Struts2的Action中,scope要配成prototype作用域。
4. 有状态协议和无状态协议
无状态协议:在下一次链接不记住这一次链接的信息。
- HTTP,UDP都是无状态协议
- TCP,FTP是有状态协议
4.1 Http 无状态
标准的http协议是无状态的,无连接的
- 标准的http协议指的是不包括cookies, session,application的http协议,他们都不属于标准协议,虽然各种网络应用提供商,实现语言、web容器等,都默认支持它
- 无连接指的是什么
- 每一个访问都是无连接,服务器挨个处理访问队列里的访问,处理完一个就关闭连接,这事儿就完了,然后处理下一个新的
- 无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接
对于【无状态】,我看到很多隔着一层磨砂玻璃一样的模糊说法(官方或者教程里的说法)
- 协议对于事务处理没有记忆能力【事物处理】【记忆能力】
- 对同一个url请求没有上下文关系【上下文关系】
- 每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况【无直接联系】【受直接影响】
- 服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器【状态】
相关文章