微服务架构原理与治理实践 | 青训营笔记

123 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记

一、微服务架构介绍

1.1 微服务架构概览

优势

  1. 开发效率
  2. 业务独立设计
  3. 自下而上
  4. 故障隔离

劣势

  1. 治理、运维难度
  2. 观测挑战
  3. 安全性
  4. 分布式系统

image.png

1.2 微服务架构核心要素

image.png

二、微服务架构原理及特征

2.1 基本概念

  • 服务(service): 一组具有相同逻辑的运行实体。
  • 实例(instance): 一个服务中,每个运行实体即为一个实例。
  • 实例与进程的关系: 实例与进程之间没有必然对应关系,可以一个实例可以对应一个或多个进程(反之不常见)。
  • 集群(cluster): 通常指服务内部的逻辑划分,包含多个实例。
  • 常见的实例承载形式: 进程、VM、k8spod
  • 有状态/无状态服务服务的实例: 是否存储了可持久化的数据(例如磁盘文件)。
  • 服务间通信: 对于单体服务,不同模块通信只是简单的函数调用。对于微服务,服务间通信意味着网络传输。

image.png

2.2 服务注册与发现

在代码中指定一个目标服务的地址?

  • 这个方法不可行,这样所用的请求都会发送到同一台服务器。

使用DNS?

  • 本地DNS存在缓存,导致延时。
  • 负载均衡问题
  • 不支持服务实例的探活检查
  • 域名无法配置端口

解决思路: 新增一个统一的服务注册中心,用于存储服务名到服务实例的映射image.png 服务实例上线与显现的过程: 下线:先在注册中心将要下线的服务移除,等待服务的数据请求全部处理完毕后,再下线该服务。 上线:添加一个服务,进行健康检查。证明ok后再注册到注册中心。

2.3 流量特征

  • 统一网关入口
  • 内网通信多数采用RPC
  • 网状调用链路
  • rpc调用采用的是二进制传输,http文本传输,所以rpc通信的效率要比http效率高,在内网都用rpc进行服务间的调用。

image.png

三、核心服务治理功能

3.1 服务发布

服务发布(deployment)),即指让一个服务升级运行新的代码的过程。 服务发布的难点 在线服务的升级或修改不能对用户的使用造成影响。不能采用正常的线下debug方式进行处理。而是先要进行服务回滚,让系统正常运行。 image.png 蓝绿部署 image.png 先对绿色进行升级,再将所有流量移到绿色,然后对蓝色升级。 缺点:需要两倍资源,一般在请求量较少的时候进行。 灰度发布 image.png 系统中不断加入新的示例,下线旧的示例,最后完成服务的发布。 缺点:要精确控制流量的切换。代码回滚很难。

3.2 流量治理

在微服务架构下,我们可以基于地区、集群、实例、请求等维度,对端到端流量的路由路径进行精确控制。 image.png

3.3 负载均衡

负载均衡(Load Balance)负责分配请求在每个下游实例上的分布。 image.png

3.4 稳定性治理

线上服务总是会出问题的,这与程序的正确性无关。

  • 网络攻击
  • 流量突增
  • 机房断电
  • 光纤被挖
  • 机器故障
  • 网络故障
  • 机房空调故障

微服务架构中典型的稳定性治理功能 image.png

3.4.1 限流

image.png 打进来5000个qps,serviceB处理不了,限流模块去掉4000个qps。

3.4.2 熔断

image.png 当检测到serviceB连接不上的时候,serviceA不会不断重试,而是拒绝上一步的流量。等待serviceB恢复后再连接。

3.4.3 过载保护

image.png 检测到serviceB的CPU过载,可以拒绝一部分流量。

3.4.4 降级

image.png 保证重要的服务正常服务,等级较低的服务先拒绝。

四、字节跳动服务治理实践

4.1 重试的意义

本地函数的调用 image.png 可能有哪些异常?

  • 参数非法
  • OOM(Out Of Memory)
  • NPE (Null Pointer Exception)
  • 边界case
  • 系统崩溃
  • 死循环
  • 程序异常退出

远程函数调用(有重试的必要) image.png 可能有哪些异常?

  • 网络抖动
  • 下游负载高导致超时
  • 下游机器宕机
  • 本地机器负载高,调度超时
  • 下游熔断、限流

重试可以避免掉偶发的错误,提高SLA(Service-Level Agreement) image.png 意义

  • 降低错误率:假设单次请求的错误慨率为0.01,那么连续两次错误概率则为0.0001。
  • 降低长尾延时:对于偶尔耗时较长的请求,重试请求有机会提前返回。(正常100ms响应的请求有时响应时间会增加到1s)
  • 容忍暂时性错误:某些时候系统会有暂时性异常(例如网络抖动),重试可以尽量规避。
  • 避开下游故障实例:一个服务中可能会有少量实例故障(例如机器故障),重试其他实例可以成功。

4.2 重试的难点

image.png 幂等性:如转账操作的重试带来数据库不一致的问题。 重试风暴 image.png

4.3 重试策略

限制重试比例: 设定一个重试比例阈值(例如1%),重试次数占所有请求比例不超过该阈值。 image.png 防止链路重试: 链路层面的防重试风暴的核心是限制每层都发生重试,理想情况下只有最下一层发生重试。可以返回特殊的status表明“请求失败,但别重试”。 image.png Hedged requests: 对于可能超时(或延时高)的请求,重新向另一个下游实例发送一个相同的请求,并等待先到达的响应。 image.png

4.4 重试效果验证

image.png