有状态服务VS无状态服务

2020-02-07 18:18 By "Powerless" 12618 15 11

【无状态服务】(Stateless Service):

    是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。这类服务在网易蜂巢云平台创建后,借助k8s内部的负载均衡,当访问该服务的请求到达服务一端后,负载均衡会随机找到一个实例来完成该请求的响应(目前为轮询)。这类服务的实例可能会因为一些原因停止或者重新创建(如扩容时),这时,这些停止的实例里的所有信息(除日志和监控数据外)都将丢失(重启容器即会丢失)。因此如果您的容器实例里需要保留重要的信息,并希望随时可以备份以便于以后可以恢复的话,那么建议您创建有状态服务。

    无状态服务对于客户端的单次请求的处理,不依赖于其他请求,处理一次请求的信息都包含在该请求里。典型的无状态服务的例子就是http 协议。例如,要实现一个计算求和的服务,每次请求都将求和的两个值传送给服务端,然后服务端计算求和结果,并返回给客户端,服务端不保存任何信息,这样的服务就属于无状态服务。


【有状态服务】(Stateful Service):

    是指该服务的实例可以将一部分数据随时进行备份,并且在创建一个新的有状态服务时,可以通过备份恢复这些数据,以达到数据持久化的目的。有状态服务只能有一个实例,因此不支持“自动服务容量调节”。一般来说,数据库服务或者需要在本地文件系统存储配置文件或其它永久数据的应用程序可以创建使用有状态服务。要想创建有状态服务,必须满足几个前提:

    1.待创建的服务镜像(image)的Dockerfile中必须定义了存储卷(Volume),因为只有存储卷所在目录里的数据可以被备份

    2.创建服务时,必须指定给该存储卷分配的磁盘空间大小

    3.如果创建服务的同时需要从之前的一个备份里恢复数据,那么还要指明该存储卷用哪个备份恢复。

    有状态服务会存储请求上下文相关的数据信息,先后的请求:是可以有关联的。

    例如,要实现一种计数服务,每次请求都要对之前请求处理的数据结果进行+1 的操作,这就需要在服务端存储维护计数的数据,这样的服务就属于有状态的服务。又例如,在Web 应用中,经常会使用Session 来维系登录用户的上下文信息。虽然http 协议是无状态的,但是借助于Cookie 和Session,可以使http 服务转换为有状态服务。


【区别】

    实例数量:无状态服务可以有一个或多个实例,因此支持两种服务容量调节模式;有状态服务只能有一个实例,不允许创建多个实例,因此也不支持服务容量调节模式。

    存储卷:无状态服务可以有存储卷,也可以没有,即使有也无法备份存储卷里面的数据;有状态服务必须要有存储卷,并且在创建服务时,必须指定给该存储卷分配的磁盘空间大小。

    数据存储:无状态服务运行过程中的所有数据(除日志和监控数据)都存在容器实例里的文件系统中,如果实例停止或者删除,则这些数据都将丢失,无法找回;而对于有状态服务,凡是已经挂载了存储卷的目录下的文件内容都可以随时进行备份,备份的数据可以下载,也可以用于恢复新的服务。但对于没有挂载卷的目录下的数据,仍然是无法备份和保存的,如果实例停止或者删除,这些非挂载卷里的文件内容同样会丢失。

    服务状态数据既可以存储在服务内部,也可以借助其他存储系统,例如数据库或者文件存储。Service Fabric 的Stateful Services 框架中提供了一种Reliable Collection 的数据结构,可以供应用服务存储服务状态数据,由Service Fabric 提供高可用的支持,并且提供分布式分区和可缩放的特性支持。


【如何选择】

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

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

    有状态服务和无状态服务各有优劣,它们在一些情况下是可以转换的,或者有时候可以共用,并非一定要全部否定.

    在一定需要处理请求上下文的情况下又想使用无状态服务,可以将相关的请求信息存储到共享内存中或者数据库中,参考分布式session的实现方式:

        1.基于数据库的Session共享

        2.基于NFS共享文件系统

        3.基于memcached 的session

        4. 基于resin/tomcat web容器本身的session复制机制

        5. 基于TT/Redis 或 jbosscache 进行 session 共享

        6. 基于cookie 进行session共享

    或者在业务实现上,将上下文需要的信息在请求中返回,在客户端中进行存储,只不过,这个方案存在技术风险,需要用一定的手段规避


评 论

蓝晓山 5 2020-07-28 14:37
vm模块
10.11 2 2020-07-25 12:17
GzwCIHOa
10.11 4 2020-06-20 12:09
Zt1BVizF
蓝色妖姬 3 2020-06-15 17:34
hI2u3OSQ
金鑫 5 2020-06-06 12:13
rjttBvEf
辛福 3 2020-05-30 11:56
IuoGCl7k
给自己一个微笑 2 2020-05-23 12:03
yqOdCoVh
10.11 4 2020-05-16 12:06
tpIKyxNF
nick 4 2020-05-02 12:04
MondzTaO
尚晓强 6 2020-04-06 14:33
1231

Others Discussion

  • 分布式服务限流
    Posted on 2020-02-07 18:57
  • 有状态服务VS无状态服务
    Posted on 2020-02-07 18:18
  • 企业级PAAS云平台几个关键问题和挑战
    Posted on 2019-06-12 18:33
  • MySQL 单库后期分库策略
    Posted on 2019-08-19 14:31
  • Redis七大经典问题
    Posted on 2021-05-27 11:14
  • 关于HTTPS的五大误区
    Posted on 2020-02-02 01:10
  • PHP扩展GD安装
    Posted on 2018-10-29 18:29
  • PHP实现精确发布时间
    Posted on 2018-12-06 21:00