精华内容
下载资源
问答
  • 无状态服务(stateless service)
    千次阅读
    2020-12-17 16:17:19

    感觉文章不错,拿来的信息。涉及到图的地方已经没有了,凑合看吧,因为原文里的图片链接都失效了,防止原文链接再失效,直接贴到这里存档

    简介: 一、定义 无状态服务(stateless service)对单次请求的处理,不依赖其他请求,也就是说,处理一次请求所需的全部信息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库),服务器本身不存储任何信息 有状态服务(stateful service)则相反,它会在自身保存一些数据,先后的请求是有关联的 二、优劣 有状态服务常常用于实现事务(并不是唯一办法,下文有另外的方案)。举一

    一、定义

    无状态服务(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等方法,将一个有状态服务,转换成无状态服务

    更多相关内容
  • 一、Http 协议无状态的含义 1.1有状态协议 常见的许多七层协议实际上是有状态的,例如SMTP协议,它的第一条消息必须是HELO,用来握手,在HELO发送之前其他任何命令都是不能发送的;接下来一般要进行AUTH阶段,用来验证...

    一、Http 协议无状态的含义

    1.1有状态协议

    常见的许多七层协议实际上是有状态的,例如SMTP协议,它的第一条消息必须是HELO,用来握手,在HELO发送之前其他任何命令都是不能发送的;接下来一般要进行AUTH阶段,用来验证用户名和密码;接下来可以发送邮件数据;最后,通过QUT命令退出。可以看到,在整个传输层上,通信的双方是必须要时刻记住当前连接的状态的,因为不同的状态下能接受的命令是不同的;另外,之前的命令传输的某些数据也必须要记住,可能会对后面的命令产生影响。这种就叫做有状态的协议。

    1.2 http为什么说http协议是无状态协议

    相反,为什么说HTTP是无状态的协议呢?因为它的每个请求都是完全独立的,每个请求包含了处理这个请求所需的完整的数据,发送请求不涉及到状态变更即使在HTTP/1.1上,同一个连接允许传输多个HTTP请求的情况下,如果第一个请求出错了,后面的请求一般也能够继续处理(当然,如果导致协议解析失败、消息分片错误之类的自然是要除外的)。可以看出,这种协议的结构是要比有状态的协议更简单的,一般来说实现起来也更简单,不需要使用状态机,一个循环就行了。

    1.3为什么不改进http协议使之有状态

    最初的http协议只是用来浏览静态文件的,无状态协议已经足够,这样实现的负担也很轻(相对来说,实现有状态的代价是很高的,要维护状态,根据状态来操作。)。随着web的发展,它需要变得有状态,但是不是就要修改http协议使之有状态呢?是不需要的。因为我们经常长时间逗留在某一个网页,然后才进入到另一个网页,如果在这两个页面之间维持状态,代价是很高的。其次,历史让http无状态,但是现在对http提出了新的要求,按照软件领域的通常做法是,保留历史经验,在http协议上再加上一层实现我们的目的(“再加上一层,你可以做任何事”)。所以引入了其他机制来实现这种有状态的连接。

    1.4无状态协议的优缺点

    和许多人想象的不同,会话(Session)支持其实并不是一个缺点,反而是无状态协议的优点,因为对于有状态协议来说,如果将会话状态与连接绑定在一起,那么如果连接意外断开,整个会话就会丢失,重新连接之后一般需要从头开始(当然这也可以通过吸收无状态协议的某些特点进行改进);而HTTP这样的无状态协议,使用元数据(如Cookies头)来维护会话,使得会话与连接本身独立起来,这样即使连接断开了,会话状态也不会受到严重伤害,保持会话也不需要保持连接本身。另外,无状态的优点还在于对中间件友好,中间件无需完全理解通信双方的交互过程,只需要能正确分片消息即可,而且中间件可以很方便地将消息在不同的连接上传输而不影响正确性,这就方便了负载均衡等组件的设计。

    无状态协议的主要缺点在于,单个请求需要的所有信息都必须要包含在请求中一次发送到服务端,这导致单个消息的结构需要比较复杂,必须能够支持大量元数据,因此HTTP消息的解析要比其他许多协议都要复杂得多。同时,这也导致了相同的数据在多个请求上往往需要反复传输,例如同一个连接上的每个请求都需要传输Host、 Authentication、 Cookies、 Server等往往是完全重复的元数据,一定程度上降低了协议的效率。

    1.5 HTTP协议是无状态协议,这句话本身到底对不对?

    实际上,并不全对。HTTP/1.1中有一个 HTTP/1.1 Expect: 100-Continue的功能,它是这么工作的:

    • 1.在发送大量数据的时候,考虑到服务端有可能直接拒收数据,客户端发出请求头并附带 Expect:100-continue HTTP的HTTP头,不发送请求体,先等待服务器响应
    • 2.服务器收到 Expect:100-Continue 的请求,如果允许上传,发送100 continue 的HTTP响应(同一个请求可以有任意个1xx的响应,均不是最后的 Response,只起到提示性作用);如果不允许,例如不允许上传数据,或者数据大小超出限制,直接返回4xx/5xx的错误
    • 3.客户端收到100 Continue的响应之后,继续上传数据
      可以看出,这实际上很明显是一个有状态协议的套路,它需要先进行一次握手,然后再真正发送数据。不过,HTTP协议也规定,如果服务端不进行100 Continue的响应,建议客户端在等待较短的时间之后仍然上传数据,以达成与不支持 Expect:100- Continue功能的服务器的兼容,这样可以算是“能有状态则有状态,否则回到无状态的路上”,这样说HTTP1.x 是无状态的协议也是没错的。

    至于HTTP/2,它应该算是一个有状态的协议了(有握手和 GOAWAY消息,有类似于TCP的流控),所以以后说“HTTP是无状态的协议”就不太对了,最好说HTTP1.x 是无状态的协议

    二、如何解决无状态问题

    HTTP协议是无状态的,无状态意味着,服务器无法给不同的客户端响应不同的信息。这样一些交互业务就无法支撑了。 Cookie应运而生。

    2.1 Cookie

    cookie的传递会经过下边这4步:

    1. Client 发送 HTTP 请求给 Server
    2. Server响应,并附带Set-Cookie的头部信息
    3. Client保存 Cookie, 之后请求 Server 会附带Cookie的头部信息
    4. Server从 Cookie 知道 Client是谁了,返回相应的响应

    Cookie的英文翻译是甜品,使用 Cookie可以自动填写用户名、记住密码等,是给用户的一点甜头。

    Server拿到 Cookie后,通过什么信息才能判断是哪个Client呢? 服务器的 SessionID

    2.2 Session

    如果把用户名、密码等重要隐私都存到客户端的Cookie中,还是有泄密风险。为了更安全,把机密信息保存到服务器上,这就是 Session Session是服务器上维护的客户档案,可以理解为服务器端数据库中有一张user表,里面存放了客户端的用户信息。SessionID就是这张表的主键ID
    Session信息存到服务器,必然占用内存。用户多了以后,开销必然增大。为了提高效率,需要做分布式,做负载均衡。因为认证的信息保存在内存中,用户访问哪台服务器,下次还得访问相同这台服务器才能拿到授权信息,这就限制了负载均衡的能力。而且 SeesionID存在 Cookie,还是有暴露的风险,比如SCRF(Cross-Site Request Forgery,跨站请求伪造)

    如何解决这些问题呢? 基于 Token令牌鉴权。

    2.3 Token

    首先, Token不需要再存储用户信息,节约了内存。其次,由于不存储信息,客户端访问不同的服务器也能进行鉴权,增强了扩展能力。然后, Token可以采用不同的加密方式进行签名,提高了安全性。
    Token就是一段字符串, Token传递的过程跟 Cookie类似,只是传递对象变成了 Token。用户使用用户名、密码请求服务器后,服务器就生成 Token,在响应中返给客户端,客户端再次请求时附带上 Token, 服务器就用这个 Token进行认证鉴权。

    Token虽然很好的解决了 Session的问题,但仍然不够完美。服务器在认证 Token的时候,仍然需要去数据库查询认证信息做校验。为了不查库,直接认证,JWT出现了。

    2.4JWT

    JWT的英文全称是 JSON Web Token。JWT把所有信息都存在自己身上了,包括用户名密码、加密信息等,且以JSON对象存储的。
    JWT长相是xxxxx.yyyyy.zzzzz,极具艺术感。包括三部分内容

    • Header包括 token类型和加密算法(HMAC SHA256 RSA)
    { "alg": "HS256", "typ": "JWT" }
    
    • Payload
      传入内容
    {"sub":1234567890","name":"John Doe, "admin": true}
    
    • Signature
      签名, 把 header 和 payload 用 base64 编码后 “.” 拼接, 加盐 secret(服务器私钥)
     HMACSHA256(base64UrLEncode(header)+"." + base64UrlEncode(payload),secret);
    

    最终的 token就是这样一个字符串

     eyJhbGci0iJIUzI11Ni9
     	.eyJzdWIi0iIxMjMONTY30DkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
     	.yK0B4jkGWu7twu8Ts9zju01E10_CPedLJkoJFCan5J4;
    

    给 Token穿个外套

     Authorization: Bearer;
    

    这就是我们在请求 Header里面看到的内容格式了。

    展开全文
  • 分布式系统中的“无状态”和“有状态”详解

    千次阅读 多人点赞 2020-04-22 02:56:50
    本文主要讲一些让系统更简单,更容易维护的东西——「易伸缩」,首当其冲的主题就是「stateless」,也叫「无状态」。 服务的“状态” 无状态的服务 客户端的每次请求必须具备自描述信息,通过这些信息识别客户端身份...

    「数据一致性」和「高可用」其实本质是一个通过提升复杂度让整体更完善的方式。

    本文主要讲一些让系统更简单,更容易维护的东西——「易伸缩」,首当其冲的主题就是「stateless」,也叫「无状态」。

    服务的“状态”

    无状态的服务

    客户端的每次请求必须具备自描述信息,通过这些信息识别客户端身份。服务端不保存任何客户端请求者信息。

    无状态的好处?

    • 客户端请求不依赖服务端的信息,任何多次请求不需要必须访问到同一台服务
    • 服务端的集群和状态对客户端透明 =-服务端可以任意的迁移和伸缩 =-减小服务端存储压力

    什么是有状态?

    有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如 tomcat 中的 session。

    例如登录:用户登录后,我们把登录者的信息保存在服务端 session 中,并且给用户一个 cookie 值,记录对应的 session。然后下次请求,用户携带 cookie 值来,我们就能识别到对应 session,从而找到用户的信息。

    有状态的缺点是什么?

    • 服务端保存大量数据,增加服务端压力
    • 服务端保存用户状态,无法进行水平扩展
    • 客户端请求依赖服务端,多次请求必须访问同一台服务器

    状态化的判断是指两个来自相同发起者的请求在服务器端是否具备上下文关系。

    如果是状态化请求,那么服务器端一般都要保存请求的相关信息,每个请求可以默认地使用以前的请求信息。

    而无状态的请求,服务器端的处理信息必须全部来自于请求所携带的信息以及可以被所有请求所使用的公共信息。

    无状态的服务器程序,最著名的就是WEB服务器。

    状态化的服务器有更广阔的应用范围,比如MSN、网络游戏等服务器。他在服务端维护每个连接的状态信息,服务端在接收到每个连接的发送的请求时,可以从本地存储的信息来重现上下文关系。

    纯函数式编程,就是无状态的。有状态,也叫有副作用。
    无状态的服务易伸缩: 很容易的通过给后端添加服务器和前端的负载均衡实现横向的扩展。
    当系统中存在着大量「有状态」的业务处理过程时,伸缩扩展就会变得复杂起来。

    「有状态」和「无状态」

    N.Wirth曾经在它1984年出版的书中将程序的定义经典的概括为:程序=数据结构+算法。(这个概括也是这本书的书名)

    程序做的事情本质就是“数据的移动和组合”,以此来达到我们所期望的结果。而如何移动、如何组合是由“算法”来定的。

    通过程序处理所得到的“成果”其实和你平时生活中完成的任何事情所得到的“成果”是一样的。任何一个“成果”都是你通过一系列的“行动”将最开始的“原料”进行加工、转化,最终得到你所期望的“成果”。

    1233356-1effb6cbe9e629da.png

    比如,你将常温的水,通过“倒入水壶”、“通电加热”等工作后变成了100度的水,就是这样一个过程。

    正如烧水的例子,大多数时候得到一个“成果”往往需要好几道“行动”才能完成。

    1233356-77f75582cfeda0df.png

    这个时候如果想降低这几道“行动”总的成本(如:时间)该怎么办呢?

    自然就是提炼出反复要做的事情,让其只做一次。而这个事情在程序中,就是将一部分“数据”放到一个「暂存区」(一般就是本地内存),以提供给相关的“行动”共用。

    1233356-6647627157e4f7e9.png
    image

    但是如此一来,就导致了需要增加一道关系,以表示每一个“行动”与哪一个「暂存区」关联。因为在程序里,“行动”可能是「多线程」的。

    这时,这个“行动”就变成「有状态」的了。

    1233356-5b0729eda75a0a78.png

    题外话:共用同一个「暂存区」的多个“行动”所处的环境经常被称作「上下文」。

    我们再来深入聊聊「有状态」。

    「暂存区」里存的是「数据」,所以可以理解为“有数据”就等价于“有状态”。

    「数据」在程序中的作用范围分为「局部」和「全局」(对应局部变量和全局变量),因此「状态」其实也可以分为两种,一种是局部的「会话状态」,一种是全局的「资源状态」

    题外话:因为有些服务端不单单负责运算,还会提供其自身范围内的「数据」出去,这些「数据」属于服务端完整的一部分,被称作「资源」。所以,理论上「资源」可以被每个「会话」来使用,因此是全局的状态。

    与「有状态」相反的是「无状态」,「无状态」意味着每次“加工”的所需的“原料”全部由外界提供,服务端内部不做任何的「暂存区」。并且请求可以提交到服务端的任意副本节点上,处理结果都是完全一样的

    有一类方法天生是「无状态」,就是负责表达移动和组合的“算法”。因为它的本质就是:

    1. 接收“原料”(入参)

    2. “加工”并返回“成果”(出参)

    为什么网上主流的观点都在说要将方法多做成「无状态」的呢?

    因为我们更习惯于编写「有状态」的代码,但是「有状态」不利于系统的易伸缩性和可维护性。

    在分布式系统中,「有状态」意味着一个用户的请求必须被提交到保存有其相关状态信息的服务器上,否则这些请求可能无法被理解,导致服务器端无法对用户请求进行自由调度(例如双11的时候临时加再多的机器都没用)。

    同时也导致了容错性不好,倘若保有用户信息的服务器宕机,那么该用户最近的所有交互操作将无法被透明地移送至备用服务器上,除非该服务器时刻与主服务器同步全部用户的状态信息。

    但是如果想获得更好的伸缩性,就需要尽量将「有状态」的处理机制改造成「无状态」的处理机制。

    「无状态」化处理

    将「有状态」的处理过程改造成「无状态」的,思路比较简单,内容不多。

    首先,状态信息前置,丰富入参,将处理需要的数据尽可能都通过上游的客户端放到入参中传过来。

    1233356-73acdd6f9561bbcb.png

    当然,这个方案的弊端也很明显:网络数据包的大小会更大一些

    另外,客户端与服务端的交互中如果涉及到多次交互,则需要来回传递后续服务端处理中所需的数据,以避免需要在服务端暂存。

    1233356-2f7e73c3952779f3.png

    ▲橙色请求,绿色响应

    这些改造的目的都是为了尽量少出现类似下面的代码。

     func(){
         return i++; 
    }
    

    而是变成:

     func(i){
         return i+1; 
    }
    

    要更好的做好这个「无状态」化的工作,依赖于你在架构设计或者项目设计中的合理分层。

    尽量将会话状态相关的处理上浮到最前面的层,因为只有最前面的层才与系统使用者接触,如此一来,其它的下层就可以将「无状态」作为一个普遍性的标准去做。

    与此同时,由于会话状态集中在最前面的层,所以哪怕真的状态丢失了,重建状态的成本相对也小很多。

    比如三层架构的话,保证BLL和DAL都不要有状态,代码的可维护性大大提高。

    如果是分布式系统的话,保证那些被服务化的程序都不要有状态。除了能提高可维护性,也大大有利于做灰度发布、A/B测试。

    题外话:在这里,提到做分层的目的是为了说明,只有将IO密集型程序和CPU密集型程序分离,才是通往「无状态」真正的出路。一旦分离后,CPU密集型的程序自然就是「无状态」了。

    如此也能更好的做「弹性扩容」。因为常见的需要「弹性扩容」的场景一般指的就是CPU负荷过大的时候。

    最后,如果前面的都不合适,可以将共享存储作为降级预案来运用,如远程缓存、数据库等。然后当状态丢失的时候可以从这些共享存储中恢复。

    所以,最理想的状态存放点。要么在最前端,要么在最底层的存储层。

    1233356-a7daf52bdd3da474.png

    任何事物都是有两面性的,正如前面提到的,我们并不是要所有的业务处理都改造成「无状态」,而只是挑其中的一部分。最终还是看“价值”,看“性价比”。

    比如,将一个以“状态”为核心的即时聊天工具的所有处理过程都改造成「无状态」的,就有点得不偿失了。

    CAP理论

    CAP理论的意思是说,一个分布式系统无法同时满足三个条件 : 一致性、可用性、分区容忍性。

    CAP分别代表:

    C:consistency,数据在多个副本中能保持一致的状态。
    A:Availability,整个系统在任何时刻都能提供可用的服务
    P:Partition tolerance,分区容错性,在出现分区的情况下依然能提供服务。

    CAP 猜想就是说在C,A,P之间最多只能存在两个。

    Lynch在2002年发表论文证明了这个猜想,将它上升到定理的层面。

    一致性,数据要保证一致,保证准确性
    可用性,我们的服务要保证24小时可用
    分区容忍性,访问量太大了,要扩容,体现为系统的可伸缩性了,部署多个实例或副本

    但是呢,扩容了,保证了可用性,数据一致性怎么保证?
    副本这么多,同步机制太难做好了。

    互联网公司一般会选择保证AP,保证高可用,但是一致性呢,该怎么办?CAP理论并不完全适用于指导实际的工程开发,所以对于一致性,一般会这样去考虑:

    强一致性,必须保证一致性,任意时刻都能读到最新值。
    弱一致性,写入新值后,在副本上可能读出来,也可能读不出来。
    最终一致性,在某个时间后,能够读到最新的值。

    有个经典有趣的问题:拜占庭将军问题。

    拜占庭将军问题 (Byzantine Generals Problem),其故事背景是这样的:拜占庭位于现在土耳其的伊斯坦布尔,是东罗马帝国的首都。由于当时拜占庭罗马帝国国土辽阔,为了防御目的,因此每个军队都分隔很远,将军与将军之间只能靠信差传消息。 在战争的时候,拜占庭军队内所有将军必需达成一致的共识,决定是否有赢的机会才去攻打敌人的阵营。但是,军队可能有叛徒和敌军间谍,这些叛徒将军们会扰乱或左右决策的过程。这时候,在已知有成员谋反的情况下,其余忠诚的将军在不受叛徒的影响下如何达成一致的协议,这就是拜占庭将军问题。

    从单机服务到集群化

    构建单机服务非常简单,但如果单机服务可靠性或性能不足,就需要多机器共同承担某项服务。集群化包含以下三种情况:

    1. 无状态主备集群

    仅有一台主机完成任务,且没有本地状态,其余从机机器待命,一旦主机宕机,从机选主成为主机。

    1. 有状态主备集群

    仅有一台主机完成任务,有本地状态,其余从机机器待命,一旦主机宕机,从机选主成为主机。

    1. 无状态的主从集群

    所有机器没有本地状态,理论上机器可以无限叠加,共同向外界提供同一服务。解决方案就是dubbo+zookeeper。

    4.有状态的主从集群

    所有机器都有本地状态,共同向外界提供同一服务。一旦某台机器宕机,需要主机协调其他从机代理其本地状态的任务。Paxos、raft和ZAB等一众分布式一致性算法的终极目标就是解决该问题。

    参考资料

    https://www.infoq.cn/article/2015/12/scaling-stateful-services/
    https://www.cnblogs.com/Zachary-Fan/p/stateless.html
    http://blog.sina.com.cn/s/blog_7d1968e20102xaej.html
    https://coolshell.cn/articles/10910.html
    https://www.jianshu.com/p/b0c8c9fb4763


    Kotlin 开发者社区

    1233356-4cc10b922a41aa80

    国内第一Kotlin 开发者社区公众号,主要分享、交流 Kotlin 编程语言、Spring Boot、Android、React.js/Node.js、函数式编程、编程思想等相关主题。

    越是喧嚣的世界,越需要宁静的思考。

    展开全文
  • 有状态和无状态的区别

    千次阅读 2018-07-27 14:05:33
    基本概念:  有状态就是有数据存储功能。...无状态对象(Stateless Bean),就是没有实例变量的对象 .不能保存数据,是不变类,是线程安全的。 代码更好理解: Java代码   public class Statef...

    基本概念: 

    有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。

    无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象 .不能保存数据,是不变类,是线程安全的。

    代码更好理解:

    Java代码

      
    public   class  StatefulBean {   
      
         public   int  state;   
         // 由于多线程环境下,user是引用对象,是非线程安全的   
         public  User user;   
      
         public   int  getState() {   
             return  state;   
        }   
      
         public   void  setState( int  state) {   
             this .state = state;   
        }   
      
         public  User getUser() {   
             return  user;   
        }   
      
         public   void  setUser(User user) {   
             this .user = user;   
        }   
    }   
      
      
    public   class  StatelessBeanService {   
      
         // 虽然有billDao属性,但billDao是没有状态信息的,是Stateless Bean.   
        BillDao billDao;   
      
         public  BillDao getBillDao() {   
             return  billDao;   
        }   
      
         public   void  setBillDao(BillDao billDao) {   
             this .billDao = billDao;   
        }   
      
         public  List<User> findUser(String Id) {   
    return   null ;   
        }   
    }  
    


    单例模式中的有状态和无状态: 
    单例类可以是有状态的(stateful),一个有状态的单例对象一般也是可变(mutable)单例对象 。 有状态的可变的单例对象常常当做状态库(repositary)使用。比如一个单例对象TaskCache(Spring中配为singleton)可以 持有一个AtomicLong类型的属性,用来给一个系统提供一个数值惟一的序列号码,作为任务通迅管理的ID生成器。同时,一个单例类也可以持有一个聚 集,从而允许存储多个状态,如示例中的ExpiringMap缓存任务列表。
    代码示例:

    Java代码

    import  java.util.concurrent.atomic.AtomicLong;   
      
    import  org.apache.mina.util.ExpiringMap;   
      
      
    public   class  TaskCache {   
      
         // 请求超时   
         private   short  requestTimeout;   
      
         // 这个缓存Map是线程安全,并且有定时超时功能   
         private  ExpiringMap<String, Object> tasksMap =  new  ExpiringMap<String, Object>();   
      
         // 线程安全的原子类,示例有状态的单例类   
         private   static  AtomicLong seqNo =  new  AtomicLong( 1 );   
      
         // 示例有状态的单例类   
         public  Long nextSeqNo() {   
             return  seqNo.getAndIncrement();   
        }   
      
         public   void  setRequestTimeout( short  requestTimeout) {   
             this .requestTimeout = requestTimeout;   
        }   
      
         // 启动过期检测   
         public   void  startExpiring() {   
            tasksMap.getExpirer().setTimeToLive(requestTimeout);   
            tasksMap.getExpirer().startExpiringIfNotStarted();   
        }   
      
         // 停止过期检测   
         public   void  stopExpiring() {   
            tasksMap.getExpirer().stopExpiring();   
        }   
      
         // 取任务列表.   
         public  Object getTasks(String key) {   
             return  tasksMap.get(key);   
        }   
      
         // 去除任务列表.   
         public  Object removeTasks(String key) {   
             return  tasksMap.remove(key);   
        }   
      
         // 添加任务列表.   
         public   void  addTasks(String key, Object value) {   
            tasksMap.put(key, value);   
        }   
    }  



    单例类也可以是没有状态的(stateless) ,仅用做提供工具性函数的对象。既然是为了提供工具性函数,也就没有必要创建多个实例,因此使用单例模式很合适。平常的单例类都是没有状态的,这里就不示例了。一个没有状态的单例类也就是不变(Immutable)单例类。关于不变模式,请参考 http://www.javaeye.com/topic/959751 

    EJB中的有状态与无状态: 

    1.Stateful session bean的每个用户都有自己的一个实例,所以两者对stateful session bean的操作不会影响对方。另外注意:如果后面需要操作某个用户的实例,你必须在客户端缓存Bean的Stub对象(JSP通常的做法是用Session缓存),这样在后面每次调用中,容器才知道要提供相同的bean实例。

    2.Stateless Session Bean不负责记录使用者状态,Stateless Session Bean一旦实例化就被加进会话池中,各个用户都可以共用。如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响。

    3.从内存方面来看,Stateful Session Bean与Stateless Session Bean比较,Stateful Session Bean会消耗J2EE Server 较多的内存,然而Stateful Session Bean的优势却在于他可以维持使用者的状态。

    Spring中的有状态(Stateful)和无状态(Stateless) 

    1.通过上面的分析,相信大家已经对有状态和无状态有了一定的理解。无状态的Bean适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。有状态的Bean,多线程环境下不安全,那么适合用Prototype原型模式。Prototype: 每次对bean的请求都会创建一个新的bean实例。

    2.默认情况下,从Spring bean工厂所取得的实例为singleton(scope属性为singleton),容器只存在一个共享的bean实例。

    3.理解了两者的关系,那么scope选择的原则就很容易了:有状态的bean都使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

    4.如Service层、Dao层用默认singleton就行,虽然Service类也有dao这样的属性,但dao这些类都是没有状态信息的,也就是 相当于不变(immutable)类,所以不影响。Struts2中的Action因为会有User、BizEntity这样的实例对象,是有状态信息 的,在多线程环境下是不安全的,所以Struts2默认的实现是Prototype模式。在Spring中,Struts2的Action中,scope 要配成prototype作用域。

    Servlet、Struts中的有状态和无状态: 

    1.Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web 容器负责的。一个Servlet类在Application中只有一个实例存在,也就是有多个线程在使用这个实例。这是单例模式的应用。无状态的单例是线 程安全的,但我们如果在Servlet里用了实例变量,那么就变成有状态了,是非线程安全的。如下面的用法就是不安全的,因为user,out都是有状态 信息的。

    Java代码

      
    public   class  UnSafeServlet HttpServlet{   
           
        User user;   
        PrintWriter out;   
           
         public   void  doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{   
             //do something...   
        }   
    }  


    Out,Request,Response,Session,Config,Page,PageContext是线程安全的,Application在整个系统内被使用,所以不是线程安全的.

    2.Struts1也是基于单例模式实现,也就是只有一个Action实例供多线程使用。默认的模式是前台页面数据通过actionForm传入,在 action中的excute方法接收,这样action是无状态的,所以一般情况下Strunts1是线程安全的。如果Action中用了实例变量,那 么就变成有状态了,同样是非线程安全的。像下面这样就是线程不安全的。

    Java代码

      
    public   class  UnSafeAction1  extends  Action {   
      
         // 因为Struts1是单例实现,有状态情况下,对象引用是非线程安全的   
        User user;   
      
         public   void  execute() {   
             // do something...   
        }   
      
         public  User getUser() {   
             return  user;   
        }   
      
         public   void  setUser(User user) {   
             this .user = user;   
        }   
    }    

    3.Struts2默认的实现是Prototype模式。也就是每个请求都新生成一个Action实例,所以不存在线程安全问题。需要注意的是,如果由Spring管理action的生命周期, scope要配成prototype作用域。

    4.如何解决Servlet和Struts1的线程安全问题,当我们能比较好的理解有状态和无状态的原理,自然很容易得出结论:不要使用有状态的bean,也就是不要用实例变量 。如果用,就要用prototype模式。Struts1 user guide里有: Only Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables, not instance variables , in your Action class.

    总结: 
    Stateless无状态用单例Singleton模式,Stateful有状态就用原型Prototype模式。 
    Stateful 有状态是多线程编码的天敌,所以在开发中尽量用Stateless无状态,无状态是不变(immutable)模式的应用,有很多优点:不用管线程和同步的问题 ,如果值是不可变的,程序不用担心多个线程改变共享状态,所以可以避免线程竞争的bugs. 因为没有竞争,就不用用locks等机制,所以无状态的不变机制,也可以避免产生死锁现象。

    展开全文
  • 有状态服务和无状态服务

    千次阅读 2020-08-25 12:51:43
    服务一般分为有状态服务(Stateful Service)和无状态服务(Stateless Service)。它们的区别是,当请求发起后,服务在服务端运行时是否需要关联上下文。 有状态服务,服务端需要保存请求的信息,并且其它请求还可以...
  • ipv6 有状态和无状态什么意思

    千次阅读 2021-05-15 23:58:17
    这是IPv6协议的一个突出特点:支持网络节点...在有状态地址自动配置的方式下,主要采用动态主机配置协议(DHCP),需要配备专门的DHCP二、无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实...
  • 这个是定义,从宏观上说的,实际上把无状态说成请求独立,无关联也对~下面具体的说说。 无状态在常见web应用项目中如何理解:http请求本身不具有任何上次请求会话的数据缓存。如果在不考虑cookie和session情况下,...
  • Kubernetes 无状态服务和有状态服务

    千次阅读 2020-01-25 15:50:27
    无状态服务 是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。 多个实例可以共享相同的持久化数据。例如:nginx实例,tomcat实例等 相关的k8s资源有:...
  • Spring 有状态bean 无状态bean

    千次阅读 2018-08-16 09:56:15
    因为无状态会话Bean是不保存会话状态的,所以无论哪个客户端调用了某个无状态会话Bean,都没有差别,也就是说任何一个无状态会话Bean的实例都可以为客户端程序提供服务。而且无状态会话Bean同客户端的关系是1:n。也...
  • k8s有状态与无状态的区别

    千次阅读 2021-11-29 14:26:10
    无状态服务:deployment Deployment被设计用来管理无状态服务的pod,每个pod完全一致.什么意思呢? 无状态服务内的多个Pod创建的顺序是没有顺序的. 无状态服务内的多个Pod的名称是随机的.pod被重新启动调度后,它的...
  • 一种是IPv6的无状态(stateless)自动配置,这是IPv6协议的一个突出特点:支持网络节点的地址自动配置。 1. 有状态地址自动配置 在有状态地址自动配置的方式下,DHCPv6服务器分配一个完整的IPv6地址给主机,并提供DNS...
  • 说这个命题之前,我先解释一下编程里,有状态和无状态都什么意思 有状态 有状态就是有数据存储功能,线程不安全 无状态 无状态就是一次操作,不能保存数据。线程安全 下面我们先看看Srping中的Bean来辅助理解...
  • 无状态进程或应用可以理解为孤立的。关于它的既往事务,我们一无所知,没有任何参考。每项事务处理似乎都是从头开始。无状态应用只提供一项服务或功能, 无状态事务的典型示例是执行在线搜索,寻找您想要的答案。您...
  • TCP有状态协议与HTTP无状态协议

    千次阅读 2021-02-03 16:35:33
    http协议是无状态协议,即下一次的http请求与上一次的http请求没有任何关系,没有任何上下文关系,即不记录上下文。但是TCP是有状态的协议,TCP下一次传输的报文段和上一次传输的报文段是有关系的,最终要按照报文段...
  • 什么是有状态登录和无状态登录

    千次阅读 2019-05-14 21:55:29
    1、有状态登录 那缺点是什么? • 服务端保存大量数据,增加服务端压力 • 服务端保存用户状态,无法进行水平扩展 ...• 客户端请求依赖服务端,多次请求必须访问同一...2、无状态登录 服务器不保存用户的登录信...
  • 在面试中被问到HTTP协议是有状态还是无状态的,当场就有点懵,因为不会就没答出来。还是得总结一下啵! 一、HTTP协议的状态 HTTP是一种无状态协议,即服务器不保留与客户交易时的任何状态。 也就是说,上一次的...
  • 无状态应用

    千次阅读 2020-01-07 16:07:27
    无状态应用: Stateless Application 是指并不会在会话中保存下次会话中去要的客户端数据。 每一个会话都像首次执行一样,不会依赖之前的数据进行响应。 有状态的应用: Stateful Application 是指会在会话中保存...
  • 有状态服务 & 无状态服务

    万次阅读 多人点赞 2018-10-26 16:38:42
    无状态服务:就是没有特殊状态的服务,各个请求对于服务器来说统一无差别处理,请求自身携带了所有服务端所需要的所有参数(服务端自身不存储跟请求相关的任何数据,不包括数据库存储信息) 有状态服务:与之相反,...
  • http无状态协议如何保存用户状态

    千次阅读 2019-08-05 22:39:23
    http无状态协议如何保存用户状态http无状态协议如何保存用户状态? http无状态协议如何保存用户状态? HTTP 是一种不保存状态,即无状态(stateless)协议。HTTP 协议自 身不对请求和响应之间的通信状态进行保存。也...
  • 深入研究自动分配IPv6地址的Stateless(无状态)与Stateful(有状态)方式 目录 ▪ 一. Link-Local Address的生成方式 ▪ 二. Global Address的生成方式 ▪ 三. RA报文中3个关键的Flag ▪ 四. 流程示意图 ▪ 五. ...
  • 目录 1. 区别 2. 例子 ... 实例2:用Keras实现有状态LSTM——电量消费预测 3. 实例3:用Keras实现有状态LSTM序列预测 普通多层神经网络 stateless LSTM 单层Stateful LSTM 双层stacked ...
  • react--无状态组件和有状态组件

    千次阅读 2019-06-23 07:54:51
    react--无状态组件和有状态组件
  • http无状态协议

    千次阅读 2020-04-14 10:13:47
    无状态是指,当浏览器给服务器发送请求的时候,服务器响应客户端请求。 但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道他就是刚才的那个浏览器。 简单的说,就是服务器不会去记得你,所以就是http...
  • 要明白,这句话的含义是指在说明,http协议作为技术背景的web应用程序请求——应答模式是无状态的,这个事实基本不会发生改变,也不会因为加入cookies、session机制而变成有状态的。要明白,这种前后因果关系:...
  • 单点登陆和无状态登陆

    万次阅读 2019-08-24 13:36:24
    今天我们来说说什么是单点登陆和无状态登陆。 传统的项目都是使用session来验证登陆,但是在分布式项目中使用session是不行的。因为每个服务都是一个独立的项目,那么我们将服务拆分,肯定会有一个登陆的模块。...
  • 应用的无状态和有状态!

    千次阅读 2019-11-14 15:39:06
    应用的无状态和有状态! 什么是有状态和无状态 ? 场景: 当用户登录时,将session或者token传给应用服务器管理,应用服务器里持有用户的上下文信息,这时应用服务器是有状态的 . 同样用户登陆时,我们将session或token...
  • 有状态组件和无状态组件的区别

    千次阅读 2020-03-06 20:09:10
    有状态组件就是一个类,无状态组件是一个函数; 区别: 1.(是否拥有state)有状态组件可以使用状态:state,无状态组件不能使用state;只有继承component这个组件它才能拥有state进行一些数据的存储和管理,仍然...
  • 有状态和无状态服务是两种不同的服务架构,两者的不同之处在于对于服务状态的处理。服务状态是服务请求所需 的数据,它可以是一个变量或者一个数据结构。无状态服务不会记录服务状态,不同请求之间也是没有任何关系...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,757,132
精华内容 702,852
关键字:

无状态

友情链接: practice.rar