这是我参与「第五届青训营 」伴学笔记创作活动的第 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: 对延时高的响应, 向另一个下游实例发送相同的请求, 及时得到响应