13-微服务架构原理与治理实践 | 青训营

89 阅读6分钟

13-微服务框架原理与治理实践

[TOC]

13.1 微服务架构介绍

13.1.1 系统架构演变历史

需要演进的原因

历史

①单体架构

把所有逻辑放在一个软件下面

优点:效率高,性能高,冗余小

缺点:debug困难;模块相互影响;模块分工复杂、开发流程

屏幕截图 2023-08-21 164136.png

②垂直应用架构

按照业务线垂直划分,每个业务线又是一个单体架构。

优势:业务独立开发维护

缺点:不同业务存在冗余;每个业务还是单体

屏幕截图 2023-08-21 164057.png

③分布式架构

抽出业务无关的公共模块

优势:业务无关的独立服务;公共服务的去冗余

缺点:服务模块bug可导致全站瘫痪;调用关系复杂;不同服务冗余

屏幕截图 2023-08-21 164443.png

④SOA架构

面向服务

优势:服务注册

缺点:整个系统设计是中心化的;需要从上到下设计;重构困难

屏幕截图 2023-08-21 164634.png

⑤微服务架构

彻底的服务化

优势:开发效率高;业务独立设计;自下而上;故障隔离

缺点:治理、运维难;观测挑战;安全性;分布式系统

屏幕截图 2023-08-21 164800.png

13.1.2 微服务架构概览

①网关
②服务配置和治理
③链路追踪和监控

屏幕截图 2023-08-21 165115.png

13.1.3 微服务架构核心要素

  • 服务治理
  • 可观测性
  • 安全:身份验证、服务之间调用的认证授权...

13.2 微服务架构原理及特征

13.2.1 基本概念

  • 服务
    • 一组具有相同逻辑运行实体 = 一个服务就是运行同一段代码的多个实例
    • 相同逻辑:一个服务的代码是一样的,必须运行相同的代码
    • 运行实体:实例
  • 实例:一个服务中,每个运行实体就是一个实例
  • 实例与进程的关系:没有必然对应关系,可以一实例对一/多进程,反之不常见
  • 集群cluster:通常指服务内部的逻辑划分,包含多个实例
  • 常见的实例承载形式:进程,VM,k8s pod
  • 有状态/无状态服务:服务的实例是否存储了可持久化的数据(如磁盘文件)。如存储式的服务-有状态,代理式的服务-无状态
  • 服务包含集群,集群包含实例

屏幕截图 2023-08-21 170025.png

  • 服务间通信
    • 对于单体服务:不同模块通信只是简单的函数调用
    • 对于微服务:服务间通信意味着网络传输
    • 服务之间通信通常包含一些协议如HTTP,gRPC...

屏幕截图 2023-08-21 170511.png

13.2.2 服务注册与发现

// service A wants to call service B
client := grpc.NewClient("10.23.45.67:8080")

问题:①ip地址是变化的,不能写死 ②一个服务有多个实例,这样只指定一个实例是不行的

屏幕截图 2023-08-21 170833.png

解决:用域名DNS

新问题:

①本地DNS是存在缓存的,会导致延时;

②负载均衡问题:返回具体哪一个ip,大多数时间会选择第一个

③不支持服务实例的探活检查;

④域名无法配置端口

屏幕截图 2023-08-21 170945.png

解决:服务注册中心,用于存储服务名到服务实例的映射

服务实例上线及下线过程:

​ 服务B的第三个实例有问题,需要下线——问题是服务A有流量过来

下线

​ ①在服务注册中心,把第三个实例的记录删掉

​ ②删掉几秒后,服务A不会再调用第三个实例,那么就没有流量

​ ③删除B的第三个实例,是安全的——下线

上线

​ ①先在B中把实例加好,并进行health check

​ ②实例注册到服务中心里

​ ③服务A发现第三个实例,流量又可以恢复了

屏幕截图 2023-08-21 193457.png

13.2.3 流量特征

两种流量 HTTP和RPC,一般而言,终端进来的流量是HTTP,后来进到里面后变成RPC

统一网关入口

内网通信多数采用RPC

网状调用链路

屏幕截图 2023-08-21 193728.png

13.3 核心服务治理功能

13.3.1 服务发布

服务发布:让一个服务升级运行新的代码的过程。

相关笔记:服务发布全流程

①服务发布的难点
  • 服务不可用。服务A使用服务B,B要更新不可用了,A瘫痪
  • 服务抖动。流量短暂不可用
  • 服务回滚。旧代码没问题,升级的新代码有问题,那么不管问题大小都先倒回旧代码,使损失最小。
②蓝绿部署

把服务B分成绿色和蓝色的集群。

先断掉绿色集群,然后升级;升级完毕后,将蓝色集群服务流量导入到绿色集群,然后断掉蓝色集群进行升级。由此达成无错的升级

优点:简单,稳定

缺点:但需要两倍的资源,要求一半的实例要求处理所有的流量

屏幕截图 2023-08-21 195017.png

③灰度发布(金丝雀发布)

达到提前探险的效果。

节省发布资源但有代价:

​ 整个发布以实例为维度去切流量——难度大

​ 回滚的难度大

屏幕截图 2023-08-21 195323.png

13.3.2 流量治理

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

①地区

​ beijing,shanghai

②集群

​ serviceA,稳定集群

③实例

​ serviceB,老机器处理性能不如新机器

④请求

​ serviceC,普通流量走正常集群;内部请求去特征测试实例

屏幕截图 2023-08-21 195641.png

13.2.3 负载均衡

负载均衡,load balance负责分配请求在每个下游实例上的分布。

常见策略:Round Robin...

13.2.4 稳定性治理

线上服务总会出问题,这与程序的正确性无关。

外界因素:网络攻击,流量激增,机房断电,光线被挖,机器故障,网络故障,机房空调故障....

客观因素无法避免,那么在系统层面努力维护。

稳定性治理功能:

  • 限流
  • 熔断
  • 过载保护
  • 降级

屏幕截图 2023-08-21 200343.png

13.4 字节跳动服务治理实践

13.4.1 重试的意义

本地函数调用:会有各种异常,不能保证调用一定成功。这里没有重试的必要

远程函数调用:网络抖动等异常。这里有重试的必要,重试可以避免掉偶发的错误

降低错误率

降低长尾延时:对于偶尔耗时较长的请求,重试请求有机会提前返回

容忍暂时性错误

避开下游故障实例:重试其他实例

13.4.2 重试的难点

重试是默认不用的。所以不要无脑重试

  • 幂等性
  • 重试风暴:微服务的调用链路是很深的

屏幕截图 2023-08-21 201226.png

  • 超时设置

13.4.3 重试策略

①限制重试比例

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

​ 大部分成功的情况下才有必要重试;若大部分失败那么重试都失败,没有意义。

②防止链路重试

​ 核心是限制每层都发生重试,理想情况下只有最下一层发生重试。

​ 可以返回特殊的status表名“请求失败,但别重试”。

③hedged requests,对冲请求

​ 对于可能超时的请求,重新向另一个下游实例发送一个相同的请求,并等待先到达的响应。

屏幕截图 2023-08-21 201815.png

13.4.4 重试效果验证

验证经过上述重试策略后,在链路上发生的重试放大效应。

屏幕截图 2023-08-21 202037.png