微服务架构原理与治理实践|青训营笔记

410 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第14篇笔记.

微服务架构介绍

系统架构需要演进。
单体-》
垂直应用(按照业务线垂直划分-》
分布式(抽出与业务无关的公共模块-》
SOA(面向服务,服务注册中心-》
微服务(彻底的服务化,由下而上,故障隔离,开发效率高

核心因素

  • 服务治理
  • 可观测性
  • 安全性

微服务架构原理及特征

服务:一组具有相同逻辑运行实体 。一个服务的所有实例必须运行相同代码 实例:服务中每个运行实体即为一个实例
集群:服务内部的逻辑划分,每个集群包含多个实例
实例与进程的关系:一个实例可以对应一个或多个进程。实例和进程之间没有必然的对应关系
常见的实例承载形式:进程、VM、K8S pod
有状态/无状态服务:服务中是否存储了可持久化数据

服务间的通信

单体服务的不同模块通信是简单的函数调用
微服务的服务间通信是网络传输。服务间通信使用不同的协议。

  1. 在代码层面,如何指定调用目标服务的地址(ip:port? 一般不会指定固定的地址。如果一个服务多个实例,只能返回一个ip,且服务的地址可能是动态改变的。
    如果使用DNS指定目的地址,部分来看是可以的,但是dns缓存会导致延时,且存在负载均衡问题,不支持服务实例的探活检查,域名无法配置端口。
    以DNS思想为启发,使用服务注册中心Service Registry,用于存储服务名到服务实例的映射。
  • 服务上线和下线的过程?
    服务下线前先在服务注册中心删除该服务,再下线服务是安全的。
    服务上线时需要先启动添加,health check(发送请求试探),再将服务注册到注册中心,恢复流量。

流量特征

基于流量的微服务。终端进入内网intranet->api gateway->servcie->offline training job.
rpc是二进制协议,内部的服务调用采用rpc。

核心服务治理能力

服务发布deployment

让一个服务升级运行新的代码的过程。
在线服务的发布可能出现1)服务不可用2)服务抖动3)服务回滚的问题

  • 蓝绿部署。将实例分类后,分别部署
  • 金丝雀发布 流量控制和回滚问题

流量治理

基于地区、集群、实例、请求等维度,对端到端流量的路由路径进行精确的流量控制。

负载均衡

负载分配请求在每个下游实例上的分布

稳定性治理

线上问题会出问题但与程序的正确性无关。

  • 限流 reject 部分qps
  • 熔断
  • 过载保护 dynamic overload
  • 降级

字节跳动服务治理实践---对请求重试机制进行探索

func LocalFunc(x int) int{
    res:=calculate(x*2)
    return res
   }

对于一个普通的本地函数调用,可能出现哪些异常?

  • 参数非法
  • OOM
  • NPE Null Pointer Exception
  • 边界case
  • 系统崩溃
  • 死循环
  • 程序异常退出 当然,该函数没有重试必要
func RemoteFunc(ctx context.Context,x int)(int,error){
          ctx2,defer_func:=context.WithTimeout(ctx,time.Second)
         defer defer_func()
         res,err:=grpc_client.Calculate(ctx2,x*2)
         return res,err
 }

对于该远程调用函数,可能会出现哪些异常?

  • 网络抖动
  • 下游负载高导致超时
  • 下游机器宕机
  • 本地机器负载高,调度超时
  • 下游熔断、限流
  • 。。。 对上述函数进行充实,避免偶发错误
  • 提高SLA(service-level agreement
  • 降低错误率
  • 降低长尾延时(对于偶尔耗时较长的请求,重试请求有机会提前返回
  • 容忍暂时性错误
  • 避开下游故障实例
func RemoteFuncRetry(ctx context.Context,x int)(res int,err error){
//重试三次
    for i:=0;i<3;i++{
        if res,err=RemoteFunc(ctx,x);err==nil{
            return 
            }
        }
    return 
    }

那么,为什么默认不使用重试?

  • 部分请求不具有幂等性
  • 重试风暴
    • 微服务调用链路较多,上游的每次重试都会带动下游,可能使下游机器宕机 解决重试风暴:
    • 可以限制重试比例,设置重试比例阈值,重试次数占所有请求比例不超过该阈值。
    • 可以防止链路重试。链路层面的防止重试风暴的核心是限制每层都重试,理想情况下只有下一层重试。如果链路失败返回特殊的status标明“请求失败,但别重试”
    • Hedged requests.对于延迟高或可能超时的请求,重新向下一个下游实例发送相同请求,等待先达到的响应。
  • 超时设置