V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
spr1ngs
V2EX  ›  程序员

服务最好是无状态的是什么意思

  •  
  •   spr1ngs · 2023-01-20 10:20:36 +08:00 · 5011 次点击
    这是一个创建于 433 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有懂的大哥吗

    29 条回复    2023-01-31 17:01:42 +08:00
    NoirStrike
        1
    NoirStrike  
       2023-01-20 10:21:30 +08:00
    像是 k8s 的概念
    cvbnt
        2
    cvbnt  
       2023-01-20 10:22:31 +08:00 via Android
    serverless ?
    loading
        3
    loading  
       2023-01-20 10:29:13 +08:00   ❤️ 3
    服务一个新的请求不依赖其他请求的信息。
    matepi
        4
    matepi  
       2023-01-20 10:31:59 +08:00   ❤️ 1
    啥都不留下,随时挂随时起
    服务的前 1 次与后 1 次,前 n 次与后 k 次之间,无相关不依赖
    misdake
        5
    misdake  
       2023-01-20 10:32:17 +08:00
    我不是后端但公司有过一点培训,按照印象随便说两句。
    提供的接口的输入参数包含了所有必要的输入,接口执行时不依赖以前的接口调用的输入,内部也不需要保留任何状态。(仍然可以依赖其他数据如其他服务、数据库等,核心在于直接的输入参数全部来自接口传参)
    接口不保留状态,带来的好处是很容易扩容缩容、动态替换接口实现等等,很灵活。代价就是写法改变,传输数据量可能会更大。
    yuezk
        6
    yuezk  
       2023-01-20 10:54:13 +08:00
    @cvbnt #2 stateless
    kkhaike
        7
    kkhaike  
       2023-01-20 10:55:14 +08:00   ❤️ 1
    楼上说的"接口不保留状态"基本就能概括了
    无状态基本是微服务的必备条件,因为负责均衡的关系,
    一个业务的多个请求,是分布在不同节点上完成的,
    如果有状态的话,只能在同一节点上完成
    loading
        8
    loading  
       2023-01-20 10:55:56 +08:00
    至于为什么,可以看看
    《互联网创业核心技术:构建可伸缩的 web 应用》
    https://book.douban.com/subject/26906846/
    dddd1919
        9
    dddd1919  
       2023-01-20 10:56:50 +08:00
    后端服务不直接保存前端的状态信息,比如登录状态 /操作状态等,用来保证在多服务时一个请求不管打到哪台服务上都能返回一致结果,前端操作不受后端服务重启 /部署伸缩等操作影响

    为了达到服务无状态目的,最常用的处理方式就是 session 等状态缓存放到分布式的组件中,比如 redis 或 memcached
    Eathein
        10
    Eathein  
       2023-01-20 10:58:35 +08:00
    这里的状态可以理解为数据。无状态就是不存储数据,比如我的服务只提供算数运算,服务本身不存储数据,所有数据都通过参数传进来,那就是无状态的。如果我的服务提供了登录功能并且存储了 token 之类的数据,那么就是有状态的。那么显然有状态的服务如果集群,挂了一台数据就会丢失一点;无状态的
    Eathein
        11
    Eathein  
       2023-01-20 10:59:36 +08:00
    接上条,无状态的服务集群挂了一台对整体数据没有任何影响
    yuezk
        12
    yuezk  
       2023-01-20 11:08:59 +08:00   ❤️ 3
    先说一下什么是有状态,以用记登录场景为例,通常情况下,当用户登录成功之后,我们会把用户的信息保存在 HTTP session 中。这里的用户信息就是状态,HTTP session 实际上就是一个全局变量。当服务遇到问题重启的时候,变量会被销毁,这些状态就会丢失,用户的登录态就会丢,这显然是有问题的。另外,如果是多个服务实例,当用户登录到一个服务器后就没有办法负载均衡到另外的服务器,因为在其他的服务器上的 HTTP session 里面是没有用户信息的。

    所以,我们需要无状态的服务,用户做完登录后,把 session 信息保存在外部,比如 redis 和数据库,这样,当服务器重启的时候,我们就可以把用户路由到其他的服务器,用户的登录态也不会丢。

    在 K8s 的世界中,服务的重启或者删除重建是很常见的操作,所以要求服务无状态,便于扩展和恢复。

    无状态不光在服务领域,我们平时写类的时候,也会有无状态的类这一说。
    m1a0
        13
    m1a0  
       2023-01-20 11:12:42 +08:00
    理想很丰满, 现实很骨感。
    yuezk
        14
    yuezk  
       2023-01-20 11:18:37 +08:00
    @yuezk #12 除了把 session 保存在 redis 和数据库中,还可以用 JWT 的形式保存在客户端。无论如何,状态是无法避免的,但是我们可以通过把状态转移到其他地方的方式来避免自己保存状态,从而实现无状态。
    Jooooooooo
        15
    Jooooooooo  
       2023-01-20 11:24:37 +08:00
    可以随便扩缩容, 实例可以随便换机器.
    MrHyde
        16
    MrHyde  
       2023-01-20 11:49:37 +08:00   ❤️ 1
    stateless ,说白了,只是简单的处理数据,没有 persistent 数据

    好处就是可以随意扩容,不用考虑数据一致性 /同步等问题
    luoqeng
        17
    luoqeng  
       2023-01-20 12:14:56 +08:00
    WEB 服务可以随意重启,对比网游服务。
    L4Linux
        18
    L4Linux  
       2023-01-20 12:28:39 +08:00 via Android
    数学公式化
    kennir
        19
    kennir  
       2023-01-20 14:06:41 +08:00
    扩容方便,压力大了 k8s 再启一个容器
    RightHand
        20
    RightHand  
       2023-01-20 14:08:50 +08:00 via Android
    简单理解 无 session 无 cookies 随时换服务器
    inreality
        21
    inreality  
       2023-01-20 14:31:34 +08:00
    只处理输入->输出, 不存储任何需要变更状态的数据
    fkdog
        22
    fkdog  
       2023-01-20 14:41:37 +08:00
    一般来说这个状态指的是,计算机在本地节点存储一些业务数据,每个节点存下来的数据都不一样,可能会导致系统异常。

    比如站点访问计数器,你把这个计数变量存成全局变量,那么每个节点都有一个全局变量,各自统计各自的。
    还有就是 tomcat 的 session 也是存在单个节点的内存里,如果请求 cookie jsessionid 分发到了其他节点上,那么可能就会出现用户未登录的情况。
    litchinn
        23
    litchinn  
       2023-01-20 14:44:14 +08:00
    可以理解为更换服务器或容器部署后,对用户 /使用方无感知,反例:请求 1 在服务器 a 上写文件,请求 2 读取,这就是有状态,更换服务器 b 部署后请求 2 无法正确读取文件
    kaneg
        24
    kaneg  
       2023-01-20 18:56:42 +08:00
    无状态的服务可以随时扩容 /缩容,集群中任意一个 /几个 down 机都不影响对外服务的可用性。
    v2lf
        25
    v2lf  
       2023-01-20 19:54:28 +08:00
    每个事务不互相依赖; 之后的事务不依赖之前事务的状态。
    这里事务单纯指操作序列。
    Breacher
        26
    Breacher  
       2023-01-20 23:10:09 +08:00
    假设有一个后端 HTTP API 应用,应用可以有 N 个实例,这些实例是使用同样的应用程序配置、彼此等价的、能够随时互相替代,这 N 个实例作为一个整体对外提供服务,共同处理用户的请求。假设某个时刻有用户 A 发起的请求 request1 由实例 instance1 处理了,用户 A 的后续请求 request2, request3, ... requestN 能够由任意一个实例完成,而不是非得是 instance1 。

    要做到这样,实例们就不能把数据保存在实例进程的内存、本地磁盘或者本地文件,如果非要把数据保存在实例进程的内存、本地磁盘或者本地文件,那么在保存在某个特定实例的数据就无法由其他实例获取到,这个实例也就是有状态了,因为后续所有依赖这个数据的请求都得要来到这一个特定实例而不能是其他实例。最典型的状态数据就是用户的登录态 了,一般把登录态存储在一个所有实例都能访问到的存储组件中,比如 MySQL/Redis ,这样子,就用户登录态功能而已,这个应用就是无状态的,因为所有实例都是去 MySQL/Redis 获取登录态,它们都能获取到。
    irytu
        27
    irytu  
       2023-01-21 01:24:11 +08:00 via iPhone
    无状态比较容易去做 scale out
    Nnq
        28
    Nnq  
       2023-01-21 05:07:55 +08:00
    就是可以想停就停 想开就开 无影响
    vinceall
        29
    vinceall  
       2023-01-31 17:01:42 +08:00
    没有 session ,token 随身带,方便扩容
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1042 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 22:36 · PVG 06:36 · LAX 15:36 · JFK 18:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.