1.6、分布式之弹性:服务状态

一、简介

​ 状态处理在微服务架构中很关键的设计,应用被微服务化后,如果一个功能对应于一个服务的话很难对大流量进行抗压,所以单一功能可能是由一组相同的服务共同抗压的。这种架构设计需要解决的就是上下文状态的处理,或者几个服务组合的业务逻辑状态。

​ 这种状态称之为服务状态,如果做到无状态服务,该服务对于运维执行水平扩容的时候,不必担心出现逻辑混乱的情况。

​ 例如,一个用户请求一个活动页,流量请求到M-A服务,并且完成了task,M-A服务记录下该状态,由于流量太大一个服务低挡不住,运维进行了扩容,新扩容一个相同服务M-B,此时该用户再次请求活动页准备领奖,因为负载均衡策略这次请求到了M-B,但是用户却发现task没有完成。

如果该活动页是无状态的,就不会出现这种第一次请求与第二次请求不一样的情况。

二、无状态服务

在函数式编程中很重要的设计思想就是无状态的,函数只根据输入描述逻辑与算法,不保存数据,不修改输入数据,根据逻辑返回对应数值。无状态服务的设计也可以依据该规则,

  • 只根据请求参数,返回对应的数据,服务本身不保存数据,
  • 不记录上下文
  • 不保存依赖服务的组合结果。

想法很美好,但是在服务设计中不可能不存在状态。就像活动页上,每个用户对应的任务状态,任务进度,甚至是每天的任务形式都可能不一样。为了设计为设计为无状态服务,就需要将这些状态依赖外部储存做持久化处理。服务根据userid获取对应的状态信息。

其实就是将服务状态转移到外部存储,使服务变成无状态。外部存储可以是Mysql、Redis或者想Etcd这种强一致性的存储。

这种设计带来的缺点就是需要依赖外部存储,增加网络开销(网络开销对于一些业务场景来说也可以通过缓存来解决,但是因为缓存带来的的缺点也是缓存可能在多台机器上,造成资源的浪费),增加处理时长。但是带来的优势对于运维管理来说扩展性非常容易,随意做扩充或减少节点,因为服务是无状态的,基本上不会产生异常。

总结来看,无状态服务设计是微服务架构中的最佳实践,微服务架构本身相对于单体应用提升了系统的复杂性,无状态服务可以有效降低系统复杂度。由于无状态服务设计很依赖外部存储,所以对应的分布式存储服务业应运而生。

三、有状态服务

上面提到无状态服务是微服务架构中的最佳实践,为什么还需要介绍有状态服务?并不是说有状态服务不好,或者一点优势都没有,针对一些业务场景其实有状态服务设计也是有优势的。

有状态服务设计,对于一个用户的请求每次会落在相同的机器上,也就是粘滞会话(Sticky Sessions)。不需要考虑与其他节点同步的问题,实现简单。因此优势如下:

  • 数据状态保存在本地,不需要依赖外部存储
  • 因为数据保存在本地所以拥有很强的一致性和可用性。

无状态服务主要是把状态转移到第三方存储服务中,所有节点之间存在服务状态同步的问题。但是有状态服务就是将不同的用户数据在本地做数据分片。

Sticky Sessions也存在响应的问题,比如通过一致性hash来保证每次请求到相同机器上,这种方案可以做到水平扩容,但是可能导致访问的不均匀。

在有状态服务有扩展的真实场景中,Twitter的工程师有一个分享,感兴趣可以观看下“Building Scalable Stateful Services” by Caitie McCaffrey

相应的对于有状态服务来说,数据迁移也是一个很大的挑战,迁移有状态服务就需要迁移对应的数据。并且如果有状态服务其中一个节点挂掉,需要同步其他节点的状态数据到新节点后,才能将新节点投入运营。所以有状态服务虽然前期实现很容易,但是增加后期维护管理中。在微服务化的系统中,大量的服务如果都是有状态的,那运维管理成本可能会累死人。

四、总结

无状态服务根据输入给出唯一的输出,方便扩容维护,降低系统复杂度。是微服务架构设计中最佳实践,但是需要依赖外部存储,但是现在分布式数据库发展迅速,已经在生产环境中普遍应用,所以我们设计服务的时候,尽量保证服务是无状态的。