[ 微服务框架 | 青训营笔记]

118 阅读5分钟

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

微服务架构介绍

架构演变历史

image.png

单体架构

优点:① 性能最高 ② 冗余小
劣势:① debug 困难 ② 模块互相影响 ③ 模块分工、开发流程

image.png

垂直应用架构

按照业务线垂直划分

优势: 业务独立开发维护
劣势:① 不同业务存在冗余 ② 每个业务还是单体 image.png

分布式架构

抽出业务无关的公共模块

优势:业务无关的独立服务
劣势:① 服务模块bug可导致全站瘫痪 ② 调用关系复杂 ③ 不同服务冗余 image.png

SOA架构

面向服务

优势:服务注册
劣势:① 整个系统设计是中心化的 ② 需要从上至下 ③ 设计重构困难 image.png

微服务架构

彻底的服务化

优势:① 开发效率 ② 业务独立 ③ 设计设计 ④ 自下而上 ⑤ 故障隔离
劣势:① 治理、运维难度 ② 观测挑战 ③ 安全性 ④ 分布式系统 image.png

微服务架构概览

image.png

微服务架构核心要素

image.png

微服务架构原理及特征

基本概念

服务 (service)

一组具有相同逻辑运行实体

实例 (instance)

一个服务中,每个运行实体即为一个实例

实例与进程的关系

实例与进程之间没有必然对应关系,可以一个实例可以对应一个或多个进程 (反之不常见)

集群 (cluster)

通常指服务内部的逻辑划分,包含多个实例。

常见的实例承载形式

进程、VM、k8s pod

有状态 / 无状态服务

服务的实例是否存储了可持久化的数据(例如磁盘文件)。 image.png

服务间通信

对于单体服务,不同模块通信只是简单的函数调用
对于微服务,服务间通信意味着网络传输image.png

服务注册及发现

问题

在代码层面,如何指定调用一个目标服务的地址 (ip:port) ?

hardcode

// Service A wants to call service B
client := grpcNewClient(“10.23.45.67:8080

缺点:服务有多个实例,没法 hardcode (记住一个服务的所有实例都是运行同一份代码)服务实例 ip port 本身是动态变化的 image.png

DNS

缺点:① 本地 DNS 存在缓存,导致延时 ② 负载均衡问题 ③ 不支持服务实例的探活检查 ④ 域名无法配置端口。 image.png

解决

新增一个统一的服务注册中心,用于存储服务名到服务实例的映射 image.png

服务实例下线及上线过程

下线:先删除注册中心的实例,再删除服务的实例
上线:先增加服务的实例,进行健康检查,通过后再增加注册中心的实例 image.png

image.png

image.png

image.png

image.png

image.png

image.png

流量特征

① 统一网关入口 ② 内网通信多数采用RPC ③ 网状调用链路

image.png

核心服务治理功能

服务发布

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

难点:① 服务不可用 ② 服务抖动 ③ 服务回滚

蓝绿部署

蓝绿两个集群,断其中一个,升级另一个,另一个一样,最后两个都升级了

优点:简单稳定
缺点:需要两倍资源

image.png

image.png

image.png

image.png

image.png

image.png

灰度发布

image.png

流量治理

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

负载均衡

常见的 LB 策略:① Round Robin ② Random ③ Ring Hash ④ Least Request ... image.png

稳定性治理

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

典型的稳定性治理

image.png

字节跳动服务治理实践

重试的意义

本地函数无重试必要 image.png

避免掉偶发的错误:提高 SLA (Service-Level Agreement)
降低错误率:假设单次请求的错误概率为 0.01,那么连续两次错误概率则为 0.0001。
降低长尾延时:对于偶尔耗时较长的请求,重试请求有机会提前返回
容忍暂时性错误:重试可以尽量规避某些时候系统会有暂时性异常 (例如网络抖动),重试可以避免
避开下游故障实例:一个服务中可能会有少量实例故障 (例如机器故障) ,重试其他实例可以成功。

重试的难点

幂等性

多次请求可能会造成数据不一致

重试风暴

随着调用深度的增加,重试次数会指数级上涨 image.png

超时设置

假设一个调用正常是 1s 的超时时间,如果允许一次重试,那么第一次请求经过多少时间时,才开始重试呢?

重试策略

限制重试比例

设定一个重试比例阈值 (例如 1%) ,重试次数占所有请求比例不超过该阈值 image.png

防止链路重试

链路层面的防重试风暴的核心是限制每层都发生重试,理想情况下只有最下一层发生重试可以返回特殊的 status 表明“请求失败,但别重试”。 image.png

Hedged requests

对于可能超时(或延时高)的请求,重新向另一个下游实例发送一个相同的请求,并等待先到达的响应 image.png

重试效果验证

实际验证经过上述重试策略后,在链路上发生的重试放大效应 image.png