服务状态与容量预估
6 min read

服务状态与容量预估

1. 有状态服务与无状态服务

1.1 从系统数据层面看状态

  • 时间状态: 操作顺序有一定的限制,同一个状态的数据不能出现在2个时间点(重复请求)。

    • 如有个数据新增 ,更新,删除这3个顺序的请求,在下游业务也需要同样的顺序操作。

    • 对于单状态的数据,如计数器,不能出现重复添加,也就是这个数据只有第一次出现的时间状态是对的,后来的数据在时间状态上是不允许的,对于这种场景,往往通过把这个"点"状的数据,换成"线"数据,比如换把计数器记录成操作历史,这个点的状态由这些历史数据聚合而成,"线”数据容易做幂等操作。

  • 位置状态: 数据落地点(分片sharding、副本duplication)的状态

    • 数据拆分后的应用,同一个数据就有了状态,他只能落在指定的节点上。

    • 对于复制集架构,数据是存在多个副本的,也就是说数据落在的位置在集群上需要有一定的数量保证,以满足一定的共识基础,比如要写半数以上节点,也就是说这个数据是存在2个状态的,对于已经写成功的节点是成功状态,对于未写成功的节点是未成功/处理中的状态。如何协调这些状态,往往要引入一些共识协议(Paxos,Raft)。

1.2 从业务架构层面看状态

业务状态机: 用于表述用户在交易、履约等业务过程的实际业务运转状态。

  • 业务过程节点具备枚举特性,不会出现中间态场景

  • 对于节点与节点中间的扭转要求具备原子性,非原子性扭转会被定义为异常状态。

c84981b1-c99a-4ea6-acaf-fe862409bb87

服务执行状态机: 系统模块(或离线任务)间数据真实的交互形式

190022a2-794c-422f-b8c2-1445497d1611

接入层状态: 用于表述用户会话以及在线状态等通信状态

1.3 一些状态理论与思想推导实验

WX20220823-085121@2x

  • 假设1: 业务状态机复杂度只与行业本质与业务发展阶段相关
  • 假设2: 服务执行状态机是对业务状态机的具体实现

  • 推论1: 服务执行状态机的复杂度与服务模块数量呈正比,复杂度与模块数量呈反比
  • 推论2: 业务状态机固定的情况下,模块复杂度与模块数量呈反比
  • 推论3: 适当膨胀的模块能增强业务的复用性,降低研发成本;
  • 推论4: 模块膨胀会增加服务执行状态机的复杂度,增加运维成本;
  • 推论5: 业务架构的本质就是通过合理设计服务执行状态机,以解决二者间的矛盾
    • 业务架构通过业务系统边界定位,来界定复用与职能边界;
    • 技术架构通过搭建准入、准出、健康度评估等流程建设,并伴随提供相应的服务治理工具、平台来降低整体系统运维复杂度;

2. 系统容量预估

2.1 容量预估的第一步,是界定预估目标

预估投入产出比: 业务状态交互决定预估边界,交互稳定性需要上下游同时界定;

  • 预估的目标是稳定性, 因此需要借助稳定性为基础做团队的横向工作
  • 预估容量的终极目的是为了保障稳定性,因此稳定性指标需要成为预估者的绝对目标(OKR/KPI);

2.2 物理资源与服务指标

  • 导致服务工作指标变更的根因是外部依赖资源变更或者机器资源达到瓶颈
  • 服务工作指标发生变更时,可能导致代码逻辑变更,进而进一步影响机器资源外部依赖资源指标,因此在排障时需要按照时序抓住根因,进而更好分析系统瓶颈
  • 服务工作指标(MQ Consumer、RPC Server)
    • 流量(QPS)
    • 耗时(RT)
    • 错误数(ERR)
    • 饱和率
    • 并发数 (parallel)
  • 外部依赖资源(MQ Producer、RPC Client)
    • 流量(QPS)
    • 耗时(RT)
    • 错误数(ERR)
    • 饱和率
  • 机器资源
    • CPU (cpu.idle)
    • MEMORY
      • Thread
      • Heap
      • Non-Heap
    • Disk
      • Usage
      • IO-util
    • Network

2.3 容量理论与思想推导实验

  • 假设1: 流量 x 耗时 = 并发数
  • 假设2: 在程序逻辑不变的情况下,CPU占用(cpu.idle)与流量呈线性关系;
  • 假设3: 在程序逻辑不变的情况下,无状态服务内存、磁盘占用与流量几乎无关;
  • 假设4: 在程序逻辑不变的情况下,有状态服务内: 内存、磁盘占用与流量或并发数呈正相关;
  • 假设5: 程序逻辑会随着业务状态机的发展而改变。
  • 假设6: 当并发数、线程数、内存对象创建速度等内置过程指标达到阈值时,会触发程序逻辑的变更(如队列等待、GC、限流等)
  • 假设7: 当外部依赖服务耗时产生变更时,会触发程序逻辑的变更(如连接池池等待、GC、降级等)

  • 推论1: 对于无状态服务,可以在并发数确定的情况下按耗时预估理论吞吐量(原理1)
  • 推论2: 由于内置过程指标的限制,系统实际最大吞吐量小于等于理论吞吐量(原理6)
  • 推论3: 服务在一段时间内稳定,有且仅当该期间内流量小于最大吞吐量
  • 推论4: 当程序逻辑发生变更时,如果实际吐量能力下降,会导致进一步的错误(原理2)
    • 当内置过程达到阈值时,我们希望程序按照更大吞吐量的情况下来进行报错(即考虑限流)
    • 当外部依赖达到阈值时,我们希望程序按照更大吞吐量的情况下来进行报错(即考虑降级)
  • 推论5: 合理使用线程模型能增加系统理论并发数,进而增加理论吞吐流量