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

83 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天

今日笔记内容: 微服务架构原理与治理实践

微服务架构介绍

架构演进的必要性

  • 互联网的发展
  • 海量用户和数据
  • 快速迭代的需求

架构演变的历史

  • 单体架构
  • 垂直应用架构
  • 分布式架构
  • SOA架构
  • 微服务架构

微服务架构将整个系统按功能点拆分为不同的服务, 服务之间相互隔离, 共用在相同的基础设施上

微服务架构的核心要素

  • 服务治理
    • 服务注册
    • 服务发现
    • 负载均衡
    • 缩括容
    • 流量治理
    • 稳定性治理
    • ...
  • 可观测性
    • 日志采集
    • 日志分析
    • 监控打点
    • 监控大盘
    • 异常报警
    • 链路追踪
    • ...
  • 安全性
    • 身份验证
    • 认证授权
    • 访问令牌
    • 审计
    • 传输加密
    • 黑产攻击
    • ...

微服务架构原理及特征

  • 服务: 一组具有相同逻辑的运行实体
  • 实例: 每个服务的运行状态, 一个服务可以对应一到多个进程
  • 集群: 服务内部的逻辑划分, 包含多个不同的实例
  • 实例的运行方式: 进程, VM, k8s pod
  • 服务是否有状态: 实例是否依赖/存储了可持久化的数据

以HDFS为例, 可以将NameNode看作一个服务, DataNode为一个服务, 多个DataNode为服务的不同实例

服务间通信: 与单体服务不同的是, 微服务架构中, 服务间的通信建立在网络传输的基础上, 通信的类别大致可分为

  • HTTP
  • 各种rpc
  • 其他专有通信协议(如数据库连接)

服务的注册与发现

如何指定要调用目标服务的地址(ip+port)?

  • 硬编码
  • DNS DNS存在缓存, 地址更新不及时. 无法负载均衡, 不支持实例探活. 域名无法配置端口
  • 中心化的服务注册 : 负责服务的
    • 注册, 探活, 发现
    • 负载均衡
    • 上下线, 滚动升级
      • 先将实例从注册中心移除
      • 实例没有流量进入后, 关闭实例
      • 大规模流量来临, 新启动实例, 注册中心监控实例启动完成
      • 将新服务记录到地址中, 响应客户端请求

系统的流量特征: ![[Pasted image 20230205112651.png]]

  • 统一网关入口
  • 内部通信使用RPC
  • 网状调用链路

核心服务治理功能

服务发布

一个服务升级运行新的代码的过程

服务发布的关键: 平滑的发布, 不影响线上业务

  • 服务不可用
  • 服务抖动
  • 服务回滚

解决方案

  • 蓝绿部署:
    • 将所有服务划分为蓝绿两个逻辑集群, 先升级蓝集群, 再升级绿集群
    • 需要两倍资源
  • 灰度(金丝雀)发布
    • 新增一个节点, 每次升级完一个节点后, 将流量切到新节点, 再继续升级老节点
    • 问题: 新老节点同时服务, 逻辑需要兼容. 节点频繁变换, 流量变动大. 回滚复杂

流量治理

基于地区, 集群, 实例, 请求等维度, 对端到端路由路径进行精密控制

负载均衡

每个实例所处理的请求尽量充分利用实例处理的能力

  • Round Robin
  • Random
  • Ring Hash
  • Least Request

稳定性治理

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

解决方案

  • 限流 : 超过当前qps的请求直接拒绝
  • 熔断 : 下游服务无法响应, 则直接拒绝当前请求, 等待一定时间后重试
  • 过载保护 : 超过当前cpu处理能力的请求直接拒绝
  • 降级 : 降级, 高负载情况下, 只服务高优先级服务

字节跳动服务治理实践

重试的最佳实践

本地函数调用可能出现的问题

  • 参数非法
  • OOM
  • NPE(空指针异常)
  • 边界case
  • 系统崩溃
  • 死循环
  • 程序异常退出

不需要重试(每次重试结果变化大概率不变, 错误依然会产生)

远程函数调用

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

重试可以避免掉偶发的错误, 提供SLA(Service-Level Agreement)

  • 降低错误率: 错误概率为p, 连续两次错误概率为p*p
  • 延长长尾延时: 重试有机会提前返回
  • 容忍暂时性错误: 网络抖动等异常
  • 避开下游故障实例: 机器故障, 切换到其他实例

重试的问题

  • 幂等性: 有状态的服务多次重试可能会导致接口结果不一致
  • 重试风暴: 每个服务默认重试请求三次, 调用链非常长的情况下底层Service的调用次数是指数级的
  • 超时设置:

解决

  • 限制重试比例
  • 防止链路重试
  • Hedged request: 对延时高的响应, 向另一个下游实例发送相同的请求, 及时得到响应