微服务架构
本文来源于第五届字节跳动青训营活动,已收录到微服务架构 | 青训营笔记 - 掘金 (juejin.cn) ,主要记录了对微服务架构原理与治理实践的学习
微服务架构原理与治理实践
背景
微服务架构是当前大多数互联网公司的标准架构。
主要学习微服务架构的由来及原理、服务治理功能工作机制。
1.微服务架构介绍
1.1 系统架构演变历史
架构演变的原因
- 互联网的爆炸性发展
- 硬件设施的快速发展
- 需求复杂性的多样化
- 开发人员的急剧增加
- 计算机理论及技术的发展
单体架构 —> 垂直应用架构 —> 分布式架构 —> SOA 架构 —> 微服务架构
单体架构
优势
性能最高
冗余小
劣势
debug 困难
模块相互影响(非核心功能可能导致程序崩溃)
模块分工、依赖管理困难,开发流程几乎无法分工
垂直应用架构
安装业务线垂直划分
- 优势:业务独立开发维护
- 劣势
- 不同业务存在冗余,无法复用
- 每个业务还是单体
分布式架构
抽取出业务无关的公共模块
- 优势:业务无关的独立服务
- 劣势
- 服务模块 bug 可能导致全站瘫痪
- 调用关系复杂
- 不同服务冗余
SOA 架构(Service Oriented Architecture)
面向服务的架构
- 优势:服务注册
- 劣势
- 整个系统设计是中心化的
- 需要从上至下设计
- 重构困难
微服务架构
彻底服务化的架构
- 优势
- 高效的开发迭代效率
- 业务独立设计
- 自下而上设计
- 故障隔离可控
- 劣势
- 治理、运维难度急剧增加
- 观测挑战
- 安全性问题
- 分布式系统本身的复杂性
1.2 微服务架构概览
从组件的维度去分析微服务架构的整体视角
- 服务配置和治理:服务配置、服务治理
- 消息队列 MQ
- 用户服务:用户数据库
- 商品服务:商品数据库
- 订单服务:订单数据库
- 广告服务:数据仓库、Redis
- 链路追踪和监控:链路追踪、服务监控
- 网关
1.3 微服务架构核心要素
- 服务治理:服务注册、服务发现、负载均衡、扩缩容、流量治理、稳定性治理、…
- 可观测性:日志采集、日志分析、监控打点、监控大盘、异常报警、链路追踪、…
- 安全:身份验证、认证授权、访问令牌、审计、传输加密、黑产攻击、…
1.4 总结
- 系统架构的演变历史
- 微服务架构的整体概览
- 微服务架构的核心要素
2.微服务架构原理及特征
2.1 基本概念
服务(service)
一组具有相同逻辑的运行实体。
实例(instance)
一个服务中,每个运行实体即为一个实例。
实例与进程的关系
实例与进程之间没有必然对应关系,一个实例可以对应一个或多个进程(反过来不常见)。
集群(cluster)
通常指服务内部的逻辑划分,包含多个实例。
常见的实例承载形式
进程、VM、k8s pod、…
有状态/无状态服务
服务的实例是否存储了可持久化的数据,例如磁盘文件。
服务间通信
对于单体服务,不同模块通信只是简单的函数调用。
对于微服务,服务间通信意味着网络传输。
2.2 服务注册与发现
问题:在代码层面,如何指定调用一个目标服务的地址(ip:port)?
硬编码 hardcode
1 | // Service A want to call Service B. |
硬编码 hardcode 的问题:当服务存在多个实例时,hardcode 无法调用动态变化的服务地址。
DNS
DNS 的思想就是中间层。
DNS 的问题
- 本地 DNS 存在缓存,导致延时。
- 负载均衡问题。
- 不支持服务实例的探活检查。
- 域名无法配置端口。
服务注册中心 Service Registry
解决思路:新增一个统一的服务注册中心,用于存储服务名到服务实例的映射。与 DNS 类似,也是一个中间层。
服务实例上线及下线过程
当一个实例还有流量时,不能直接下线,当它没有流量时,可以下线。
当一个服务下线几个实例后访问压力过大,可以添加新的实例到服务中。
新启用的实例会先进行健康检查,检查无误后再注册到服务中心。
健康检查是在服务运作期间一直持续进行的。
2.3 流量特征
- 统一网关路口
- 内网通信多数采用 RPC
- 网状调用链路
弱化连接的概念,强调“请求”,即同一个客户端长连接发出的请求,理论上可以到达服务中所有实例。网关 gateway 可以用于身份认证,进而将 token 附在请求上。
2.4 总结
- 微服务架构中的基本组件及术语
- 服务注册及发现中间层
- 平滑无损的服务实例上下线流程
- 微服务架构中的基本流量特征
3.核心服务治理功能
3.1 服务发布
服务发布(deployment),即让一个服务升级运行新的代码的过程。
服务发布的难点
服务不可用
服务抖动
服务回滚
蓝绿部署问题
灰度发布(金丝雀发布)问题
3.2 流量治理
在微服务架构下,可以基于地区、集群、实例、请求等维度,对端到端流量的路由路径进行精确控制(这里就是狭义的对流量进行控制)。
3.3 负载均衡
负载均衡(Load Balance)负责分配请求在每个下游实例上以控制分布情况。
常见的 LB 策略
- Round Robin
- Random
- Ring Hash
- Least Request
- …
3.4 稳定性治理
线上服务难免会出现问题,这和程序本身正确性无关。
- 网络攻击
- 流量突增
- 机房断电
- 光纤断开
- 机器故障
- 网络故障
- 机房空调故障
- …
微服务架构中典型的稳定性治理功能
- 限流
- 熔断
- 过载保护
- 降级
3.5 总结
- 服务发布:蓝绿部署、灰度发布
- 基于地区、集群、实例、请求等维度的流量治理功能
- 几种常见的负载均衡策略
- 微服务架构中的稳定性治理功能
4.服务治理实践
4.1 重试的意义
本地函数调用可能引发的异常
- 参数非法
- OOM(Out Of Memory)
- NPE(Null Pointer Exception)
- 边界 case
- 系统崩溃
- 死循环
- 程序异常退出
本地函数没有重试的意义
远程函数调用可能引发的异常
- 网络抖动
- 下游负载高导致超时
- 下游机器宕机
- 本地机器负载高,调度超时
- 下游熔断、限流
- …
远程函数需要进行重试
重试可以避免掉偶然发生的错误,提高 SLA(Service-Level Agreement)
降低错误率
假设单次请求的错误率为 0.01,那么连续两次的错误的概率为 0.0001。
降低长尾延时
对于偶尔耗时较长的请求,重试请求有机会提前返回。
容忍暂时性错误
某些时候系统会有暂时性异常,例如网络抖动,重试可以尽量规避。
避开下游故障实例
一个服务中可能会有少量实例故障,例如机器故障,重试其他实例可以成功。
4.2 重试的难点
- 幂等性:多次请求可能会造成数据不一致。
- 重试风暴:随着调用深度的增加,重试次数会指数级上涨。
- 超时设置:间隔多少时间后发起重试请求。例如,服务 A 向服务 B 重试 3 次,但服务 B 需要向服务 C 重试 9 次,服务 C 需要向服务 D 重试 27 次,以此类推。
4.3 重试策略
重试只有在大部分请求都成功,只有少部分请求失败时,才有必要。如果大部分请求都失败,重试只会加剧问题严重性。
限制重试比例
设定一个重试比例阈值,例如 1%,重试次数占所有请求次数比例不能超过该阈值。
防止链路重试
链路层面的防重试风暴的核心是限制每层都发生重试,理想情况下是只有最下一层发生重试。可以返回特殊的 status 表明“请求失败,但不进行重试”。
缺点是需要侵入性修改业务代码。
Hedged requests
对于可能超时或延时高的请求,重新向另一个下游实例发送一个相同的请求,并等待先到达的响应。
4.4 重试效果验证
实际验证经过上述重试策略后,在链路上发生的重试放大效应。
4.5 总结
- 重试的意义及难点
- 应对重试风暴的策略
归纳总结
- 微服务架构介绍
- 微服务架构原理及特征
- 核心服务治理功能
- 服务治理实践
参考资料
- 标题: 微服务架构
- 作者: Entropy Tree
- 创建于 : 2023-02-04 23:56:51
- 更新于 : 2023-04-01 07:55:52
- 链接: https://www.entropy-tree.top/2023/02/04/golang-day9/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。