这是我参与「第五届青训营」伴学笔记创作活动的第9天。今天的内容是关于微服务的理论基础,包含微服务框架的特点和功能实现思路。
1 微服务架构介绍
1.1 系统架构演变历史
单体架构 -> 垂直应用架构 -> 分布式架构 -> SOA架构 -> 微服务架构
| 架构 | 优点 | 缺点 |
|---|---|---|
| 单体架构 | 性能最高、冗余小 | debug困难、模块相互影响、模块分工导和开发流程复杂 |
| 垂直应用架构 | 业务独立开发维护 | 不同业务存在冗余、每个业务还是单体架构 |
| 分布式架构 | 抽出业务无关的独立服务 | 服务bug可导致全站瘫痪、调用关系复杂、不同服务冗余 |
| SOA架构 | 服务注册 | 整个系统设计是中心化的、需要从上到下设计、重构困难 |
| 微服务架构 | 开发效率、业务独立设计、自下而上、故障隔离 | 治理运维难、观测挑战、安全性、分布式系统 |
1.2 微服务架构概览
分为网关、服务配置和治理、链路追踪和监控三部分。
1.3 微服务架构核心要素
- 服务治理:包含服务注册、服务发现、负载均衡、扩缩容、流量治理、稳定性治理等
- 可观测性:包含日志采集、日志分析、监控打点、监控大盘、异常警告、链路追踪等
- 安全:包括身份验证、验证授权、访问令牌、审计、传输加密、黑产攻击等
2 微服务架构原理及特征
2.1 基本概念
- 服务 service:一组具有相同逻辑(代码一致)的运行实体
- 实例 instance:一个服务中的每个运行实体
- 实例与进程的关系:没有必然对应关系,一般一对一或者一对多
- 集群 cluster:通常指逻辑内部的服务划分,包含多个实例
- 常见的实例承载形式:进程、VM、k8s pod
- 有状态/无状态服务:服务的实例是否存储了可持久化数据(如磁盘数据)
服务间通信
- 微服务之间通过网络进行通信
- 常见的通信协议包括 HTTP、RPC
2.2 服务注册及发现
背景:微服务中IP地址会变化,且一个集群中大概率对应了多个实例。
使用DNS的问题:本地DNS存在缓存导致延迟、负载均衡问题、不支持服务实例的探活检查、域名无法配置端口。
解决思路:新增统一的注册服务中心,用于存储服务名到服务实例的映射。(可理解为hashmap)
- 旧服务实例下线前,从服务注册中心删除该实例,下线流量
- 新服务实例上线后,在服务注册中心注册该实例,上线流量
2.3 流量特征
- 统一网关入口
- 外网通信多数采用 HTTP,内网通信多数采用 RPC(Thrift, gRPC)
- 网状调用链路
3 核心服务治理功能
3.1 服务发布
定义:让一个服务升级运行新的代码的过程
难点:直接停止会导致服务不可用(比如抖音崩了会上热搜的doge)、部分不可用导致服务抖动、服务回滚
蓝绿部署:将服务分成两个部分,分别先后发布;简单、稳定;但需要两倍资源
灰度发布(金丝雀发布):先发布少部分实例,接着逐步增加发布比例;不需要增加资源;回滚难度大,基础设施要求高
3.2 流量治理
流量控制:在微服务架构中,可以从各个维度对端到端的流量在链路上进行精确控制
控制维度:地区、实例、集群、请求
3.3 负载均衡
- Round Robin
- Random
- Ring Hash
- Least Request
3.4 稳定性治理
线上服务出问题很多时候与程序是否正确无关,比如:网络攻击、流量突增、机房断电、光纤被挖、机器故障、网络故障、机房空调故障……
- 限流:限制服务处理的最大 QPS,拒绝过多请求
- 熔断:中断请求路径,增加冷却时间从而让故障实例尝试恢复(唯一的发起方 reject)
- 过载保护:在负载高的实例中,主动拒绝一部分请求,防止实例被打挂
- 降级:服务处理能力不足时,拒绝低级别的请求,只响应线上高优请求
4 字节跳动服务治理实践
4.1 重试的意义
本地调用下:通常没有必要
远程函数调用:排除网络问题(网络抖动、下游负载高、下游宕机),避免偶发错误
重试的意义:降低错误率、降低长尾延时、容忍暂时错误、避开下游故障实例
4.2 重试的难点
幂等性
重试风暴:链路上每一个部分都在重试,会导致链路末端节点的重试次数按照指数级上升
超时设置
4.3 重试策略
限制重试比例:失败比例小的时候才有必要重试
防止链路重试:防止重试风暴
Hedged Requests:重试时给另一个下游实例同时发送请求,哪个先回复使用哪个
4.4 重试效果验证
字节跳动重试组件能够极大限制重试发生的链路放大效应