读书笔记:生产微服务

Posted by Shoukai Huang on January 30, 2020

作者Susan Fowler从她在Uber成功实施微服务的经验出发,结合其他各大公司工程师的意见和建议,制订了一组生产就绪微服务的标准。 作者在《生产微服务》中不仅对这组标准的各项细节展开了深入的讨论,还提供了一个检查清单,用于帮助读者了解自己的微服务生态系统是否符合生产就绪标准。

第1章 微服务简介

微服务生态系统

第一层:硬件层:服务器、数据库、OS、配置管理、主机级别日志、主机级别监控 第二层:通讯层:网络、DNS、RPC、端点、消息传递、服务发现、服务注册、负载均衡; 第三层:应用平台层:内部自助开发工具、开发环境、CI/CD、微服务级别日志、微服务级别监控 第四层:微服务层:微服务、微服务相关配置

组织的挑战

反康威定律

康威定律:公司的沟通方式和组织结构决定了系统的架构 反康威定律:产品的架构决定了公司的组织结构; 一个不可避免的组织问题:微服务必须由单独的团队来开发(导致大量单独的团队),但是他们不是孤单的,他们必须通过无缝的沟通来完成整个产品功能。 微服务团队和基础设施团队之间也有一些沟通的问题需要解决。 组织运维团队会很困难,每个微服务团队需要由单独的开发团队和运维团队来负责,开发的过程中同时负责运维

技术蔓延

每个微服务由单独团队开发,团队中每个开发人员使用自己的开发工具、编程语言、软件包 每个团队使用自己的部署方式、自己的监控指标、自己运行脚本; 微服务带来太多的自由:开发者随意选择开发语言、开发库;

更多失效的可能性

系统变复杂,控制力变弱,接受更多的失效

资源竞争

硬件、基础设施竞争 应用平台资源竞争 项目经理、团队竞争

第2章 生产就绪

微服务标准化的挑战

可用性:标准化的目标

可用性服务等级协定(SLA)

生产就绪标准

稳定性:

  • 稳定的开发周期
  • 稳定的开发流程
  • 稳定的更新换代流程

可靠性

  • 可靠的部署流程
  • 对依赖项可能出现的故障准备应对措施
  • 可靠的路由和服务发现

伸缩性

  • 定义好质和量两方面的增长规划
  • 定位资源瓶颈和需求
  • 准确的容量规划
  • 可伸缩的流量处理能力
  • 依赖性的伸缩
  • 可伸缩的数据存储

容错和灾备

  • 识别潜在的故障场景,并做好应对措施
  • 识别并解决单点故障问题
  • 应用故障探测和补救措施
  • 通过代码测试、负载测试和混沌测试验证系统的弹性
  • 管理好业务流量
  • 快速处理故障

高性能

  • 恰当的可用性SLA
  • 恰当的任务处理方式
  • 对资源的合理利用

监控

  • 适当的日志和堆栈跟踪信息
  • 设计良好且易于理解的仪表盘,可以准确地反映服务的健康状况
  • 有效且具有可操作的告警操作手册
  • 开发人员轮班待命

文档化

  • 详细的、最新的、集中式的文档,它包含了微服务所有的相关信息
  • 在开发人员、团队、整个生态系统层面了解微服务

实现生产就绪标准

接纳生产就绪标准后,下一步就是指定每个标准的具体要求。 开发人员、团队主管、管理层或者运维(系统、DevOps)人员可以实现这些要求

第3章 稳定性和可靠性

微服务稳定性和可靠性的原则

  1. 它有一个标准化的开发周期
  2. 它的代码需要经过初步检查、单一测试、集成测试以及端到端的测试
  3. 它的测试、打包、构建和发布流程是自动化的
  4. 它有标准的部署管道,包括:staging、canary和生产阶段
  5. 它的客户端是已知的
  6. 它的依赖项是已知的,而且是有备份的,还有可选的回退方案以及缓存,以及出现依赖性失效
  7. 它有稳定可靠的路由和服务发现机制

开发周期

部署管道

稳定可靠的部署管道的几个阶段

staging

staging阶段测试:

  • 触发模拟的(或录制的)业务流量
  • 手动发送请求
  • 自动化测试、单元测试、集成测试及组合

full staging

partial staging

full staging和partial staging环境的对比

  full staging partial staging
生产环境的完全镜像
单点的端口
访问生产服务
读取生产数据库
写入生产数据库
要求自动回滚

canary

  • 处理生产流量,是生产环境的一部分
  • 有对生产环境的所有权限
  • 监控可以区分canary
  • 在完成一个完整的业务流量周期之前,新发布的版本不应该离开canary环境

生产

生产环境处理真实的流量 每一个即将进入生产环境的构建版本都应该是稳定且可靠的

让稳定可靠的部署成为强制措施

生产环境出现严重错误,开发人员会试图跳过部署流程,或许可以挽回损失,或者带来更大的损失 热修复补丁是反模式

服务依赖

理解服务之间的依赖关系,并为依赖失效做好应对准备,是非常重要的 不可靠的依赖采用防御性缓存来有效保护你的微服务

路由和服务发现

健康检查

服务和端点的解除

解除端点也是微服务生态不稳定因素之一。依赖服务解除端点,当前服务不可用;

第4章 伸缩性和高性能

关于微服务伸缩性和高性能的原则

一个生产就绪的微服务是可伸缩且高性能的:

  1. 明确的质的增长规模和量的增长规模
  2. 高效地使用硬件资源
  3. 已识别出资源的瓶颈和需求
  4. 容量规划自动化,并通过调度作业来执行
  5. 依赖项也会随之伸缩
  6. 可以随着客户端的伸缩而伸缩
  7. 业务流量模式有章可循
  8. 在发生故障时业务流量可以被重新路由
  9. 使用支持伸缩性和高性能的编程语言来实现
  10. 以高性能的方式处理任务
  11. 以可伸缩和高性能的方式存储数据

了解增长规模

质的增长:反映的是微服务在整个生态系统中所起的作用,以及它将影响到的业务度量指标 量的增长:反映的是微服务能够处理的业务流量大小 描述微服务增长规模的指标:RPS(每秒请求数)QPS(每秒查询数)

资源的有效利用

CPU、内存、数据存储和网络资源 可以使用Apache Mesos等资源隔离技术对微服务进行隔离

资源感知

资源需求:CPU、内存 资源瓶颈:数据库连接数、CPU、内存

容量规划

硬件资源昂贵;容量规划是一项困难的人工活,会引入新的失效风险。

依赖项的伸缩

微服务不是独立的,依赖性的伸缩问题是实现微服务生态系统伸缩性和高性能的关键所在。

流量管理

使用增长规模来预测流量的增长 了解流量模式,并为之做好准备 处理流量的增长,包括流量峰值

任务处理

编程语言的限制

高效地处理请求任务

可伸缩的数据存储

微服务生态系统的数据库选择

选择一个满足微服务需求的特定数据库时,需要考虑以下问题

  1. 微服务每秒传输的事务数是多少
  2. 微服务需要存储的是什么类型的数据
  3. 微服务需要怎样的schema?它的变更频率是怎样的
  4. 微服务要求的是强一致性还是最终一致性
  5. 微服务是读密集型还是写密集型,还是两者兼顾
  6. 需要对数据库进行横向或者纵向扩展吗
  7. 微服务架构在数据库方面面临的挑战

第5章 容错和灾备

用于构建具有容错能力微服务的原则

一个具备容错和灾备能力的生产就绪的微服务: 没有故障点 所有可能的故障场景都已被识别出来 已经通过代码测试、负载测试和混沌测试保证了它的弹性 自动化的故障检测和挽救措施 微服务开发团队和整个组织具有标准化的事故和中断处理流程

避免单点故障

故障场景

常见的生态系统故障:

  • 不充分的系统和服务架构评审
  • 不完善的代码审查
  • 糟糕的开发流程
  • 不稳的的部署过程

常见的硬件故障场景:

  • 主机故障
  • 机架故障
  • 数据中心故障
  • 云服务故障
  • 服务器配置故障
  • 资源隔离或抽象技术故障
  • 糟糕的配置管理
  • 配置变更引起的故障
  • 主机级别的监控故障
  • 主机级别的日志故障
  • 网路故障
  • 停机运维
  • 缺乏基础设施冗余

常见的通信层和应用平台层故障:

  • 网路故障
  • DNS错误
  • RPC故障
  • 对请求或响应不恰当的处理
  • 消息系统故障
  • 服务发现和服务注册故障
  • 不恰当的负载均衡
  • 开发工具和开发环境故障
  • 测试、打包、构建和发布故障
  • 部署管道故障
  • 微服务级别日志的故障
  • 微服务级别监控的故障

常见的依赖项故障场景:

  • 下游微服务(依赖项)的故障
  • 内部服务中断
  • 外部(第三方)服务中断
  • 内部软件包故障
  • 外部(第三方)软件包故障
  • 依赖项未能达到它的SLA指标
  • API端点弃用
  • API端点移除
  • 微服务弃用
  • 微服务移除
  • 接口或端点弃用
  • 对下游服务调用超时
  • 对外部依赖项调用超时

常见的微服务故障场景:

  • 不完善的代码审查
  • 糟糕的架构设计
  • 缺乏适当的单元测试和集成测试
  • 糟糕的部署
  • 缺乏恰当的监控
  • 不恰当的异常处理
  • 数据库故障
  • 伸缩性极限

弹性测试

代码测试

  • lint测试
  • 单元测试
  • 集成测试
  • 端到端测试

负载测试

  • 负载测试使用特定的流量负载,这个负载使用RPS、QPS或TPS来表示,并通过质量增长规模和数量增长规模计算得出
  • 部署管道的每个阶段都会运行负载测试
  • 负载测试会涉及所有的依赖项
  • 负载测试是完全自动化的,会定期运行,并被记录下来

混沌测试

开源解决方案Simian Army 示例:

  • 禁用依赖项的API端点
  • 停止所有发送给依赖项的请求
  • 在生态系统的组件间引入延迟,以便模拟网络故障:在客户端和依赖项之间,在微服务和数据库之间,在微服务和分布式任务处理系统之间,等等
  • 停止所有发送到数据中心或区域的流量
  • 随机地关闭主机

故障检测和修复

事故和中断

事故和中断的分类: 严重程度(0至4,0级最重,4级最轻) 影响范围(高,中,低) 处理事故的5个步骤

第6章 监控

用于微服务监控的原则

生产就绪的微服务的监控的4个工具:

  • 日志
  • 仪表盘
  • 告警
  • 轮班待命机制

一个得到恰当监控的生产就绪的微服务:

  • 它的关键性度量指标在主机级别、基础设施级别和微服务级别得到识别和监控
  • 它有能够反映微服务过去状态的日志
  • 它的仪表盘包含了所有的关键性度量指标,而且很容易读懂
  • 它的告警具有可操作性,并且定义了阈值
  • 有一个专门的轮班待命机制负责监控微服务,并对事故和中断做出响应
  • 有一个清晰的、良好定义的标准待命流程,用于处理事故和中断

关键性度量指标

第7章 文档化和理解

微服务文档和理解的原则

一个生产就绪的微服务具有良好的文档并且为人所理解:

  1. 它有详尽的文档
  2. 它的文档会定期更新
  3. 它的文档包含如下内容:微服务描述、架构图、待命人员的信息、重要信息的链接、开发上手指南、微服务请求消息流、端点的信息、依赖项的信息、运行手册、以及常见问题答疑
  4. 它为开发人员、团队和组织所理解
  5. 它符合生产就绪标准并且满足相关要求
  6. 它的架构经过了反复的评审

微服务文档

描述、架构图、轮班待命信息、链接、开发上手指南、请求消息流、端点和依赖项、运行手册、问答章节、 生产就绪微服务的文档需要包含的内容:

  1. 关于微服务以及微服务在整个生态系统中所扮演角色的描述
  2. 一个能够详细描述微服务架构及其客户端和依赖项的架构图
  3. 微服务开发团队的待命信息
  4. 代码库链接、仪表盘链接、RFC文档链接、架构评审文档链接,以及其他任何有用的相关信息的链接
  5. 开发上手指南,包含开发流程、部署管道,以及任何能够帮助开发人员开发上手的有用信息
  6. 微服务请求流程、SLA指标、生产就绪状态、API端点、客户端和依赖项的详细信息
  7. 运行手册,包含一般性的事故处理流程和用于诊断、缓解、解决告警问题的分步操作指南,以及如何排查和调试问题
  8. 问答章节

理解微服务

架构评审、生产就绪审计、生产就绪路线图、生产就绪自动化、评估你的微服务、微服务文档、微服务理解、

附录:评估列表

开发周期

是否有一个可以存放所有代码的中心代码仓库? 开发人员所在的开发环境是否准确反映了产品状态(例如,是否准确的反映了实际情况)? 是否有代码检查、单元测试、集成测试和端到端的测试? 是否有代码审查流程和策略? 是否具有自动化的测试、打包、构建和发布流程?

部署管道

微服务生态系统是否有一个标准化的部署管道? 部署管道里是否有full staging或partial staging阶段? staging环境对生产环境有怎样的访问权限? 部署管道里是否有canary阶段? canary阶段是否有足够的时间来捕捉所有的缺陷? canary阶段是否准确地模拟了生产环境的业务流量? canary和生产环境的服务端口是一样的吗? 生产环境的部署是一步到位还是循序渐进的? 对于紧急情况,是否存在直接跳过staging和canary阶段的情况?

服务依赖

微服务的依赖项都有哪些? 微服务的客户端都有哪些? 微服务如何缓解依赖失效所带来的影响? 对于每个依赖项,是否都有备份、替代服务、回退方案或防御性缓存?

路由和服务发现

微服务的健康检测可靠吗? 健康检测是否准确地反映微服务的健康状态? 健康检测是否运行在独立的通道上? 是否使用了回路断路器来防止不健康的微服务发出请求? 是否使用了回路断路器来防止生产环境的业务流量被发送到不健康的主机或服务上?

服务和端点的解除

是否有解除微服务的相关流程? 是否有解除微服务API端点的相关流程?

增长规模

微服务的质的增长规模是怎样的? 微服务的量的增长规模是怎样的?

资源的有效利用

微服务是运行在专门的硬件上还是共享的硬件上? 是否使用了资源隔离技术?

资源感知

微服务的资源需求是怎样的(CPU、内存等)? 每个微服务实例能够处理多少流量? 每个微服务实例需要多少CPU? 每个微服务实例需要多少内存? 微服务还需要其他的资源吗? 微服务的资源瓶颈在哪里? 微服务是否需要被横向或纵向扩展,或者两者兼顾?

容量规划

容量规划是否基于调度就行? 新硬件多久能够到位? 申请硬件的频度是怎样的? 是否根据优先级为微服务分配硬件? 容量规划是自动化还是手工操作的?

依赖项的伸缩

微服务的依赖项有哪些? 这些依赖项是否具备了伸缩性和高性能? 依赖项能否随着微服务就行伸缩? 依赖项的所有者是否做好随微服务就行伸缩的准备?

流量管理

是否很好地了解微服务的流量模式? 是否根据流量模式来安排服务的变更? 流量模式的急剧变化(特别是流量爆发)是否被小心的处理了? 在服务失效以后,流量是否能够被恰当地重新路由到其他数据中心?

任务处理

微服务所使用的编程语言是否具备伸缩性和高性能? 微服务在处理请求时是否存在伸缩性和性能方面的限制? 微服务在处理任务时是否存在伸缩性和性能方面的限制? 微服务团队的开发人员是否了解他们的服务是如何处理任务的,处理任务的效率是怎样的,以及当任务和请求数量增加时他们的服务将会如何应对?

可伸缩的数据存储

微服务是否以可伸缩和高性能的方式处理数据? 微服务需要存储什么类型的数据? 微服务的数据需要怎样的schema? 每秒需要处理多少事务? 微服务需要更高的读写性能吗? 微服务是读密集、写密集还是两者兼顾? 微服务的数据库可以横向或纵向扩展吗?它是可复制或可分区的吗? 微服务使用的专门的还是共享的数据库? 微服务是如何存储和处理测试数据的?

避免故障点

是否存在单点故障? 是否存在多点故障? 故障点是否能够被移除,或者需要对它们进行缓解?

故障场景

是否所有可能的故障场景都已被识别出来? 有哪些横跨整个生态系统的常见故障? 硬件层有哪些故障会影响到这个微服务? 通信层和应用平台有哪些故障会影响到这个微服务? 哪些依赖项故障会影响到这个微服务? 哪些内部故障会拖垮这个微服务?

弹性测试

这个微服务是否通过了适当的lint测试、单元测试、集成测试和端到端的测试? 这个微服务是否经过合格的负载测试? 是否通过混沌测试对所有可能的故障场景进行了测试?

故障检测和修复

在组织里是否有标准化的事故处理流程? 这个微服务的故障是如何影响业务的? 是否对故障进行了清晰的分级? 当发生事故时,团队是否遵循了事故处理的5个步骤?

关键性度量指标

这个微服务有哪些关键性的度量指标? 有哪些主机级别和基础设施级别的度量指标? 有哪些微服务级别的度量指标? 这些关键性度量指标都被监控起来了吗?

日志

这个微服务需要把哪些信息记录到日志里? 这个微服务是否记录了重要的请求信息? 日志是否准确反映了微服务在各个时间点的状态? 这个日志方案是否具有伸缩性和高性价比?

仪表盘

这个微服务是否有仪表盘? 仪表盘是否简单易懂?是否所有的关键性度量指标都展示在了仪表盘上了? 是否能够从仪表盘上看出这个微服务是否运行正常?

告警

是否每个度量指标都设有告警? 是否所有告警都设置了合适的阈值? 告警阈值设置是否恰当,以便在发生中断之前触发告警? 告警是否具有可操作性? 运行手册是否包含了用于诊断、缓解和解决问题的排查步骤?

轮班待命

是否有一个专门的轮班待命机制用于微服务的监控? 每次待命轮班是否有至少两个开发人员参与? 这个待命流程是否在整个工程组织内进行了标准化?

微服务文档

微服务的文档是否被集中存放在一个公开的、人们容易访问到的地方? 文档是否方便搜索? 微服务发生重要变更时,文档是否也得到相应的更新? 文档是否包含了微服务的描述? 文档是包含了架构图? 文档是否包含了待命信息? 文档是否包含了重要信息的链接? 文档是否包含了开发上手指南? 文档是否包含了微服务请求信息流、端点和依赖项的信息? 文档是否包含了运行手册? 文档是否包含了问答章节?

微服务理解

团队里的每个开发人员是否都能回答与他们的微服务的生产就绪相关的问题? 微服务是否遵循了一系列原则和标准? 对于新的微服务,是否有RFC流程? 已有的微服务是否经常得到评审和审计? 是否每个微服务团队都举行架构评审? 是否有生产就绪的审计流程? 是否有生产就绪路线图用于把微服务带向生产就绪的状态? 生产就绪标准是否推动了组织的OKR? 生产就绪流程是自动化的吗?