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

83 阅读4分钟

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

系统架构演变历史

单体架构

all in one process

优势:性能最高、冗余小

劣势:debug困难、模块项目影响、模块分工、开发流程

垂直应用架构

按照业务线垂直划分

优势:业务单独开发维护

劣势:不同业务存在冗余、仍然存在单体架构的问题

分布式架构

抽出业务无关的公共模块

优势:业务无关的独立服务,进行公共业务的复用

劣势:业务系统到服务层是一个n对n的调用,用户服务可以影响全栈的业务线、调用关系复杂、不同服务冗余

SOA架构

面向服务:有了服务注册中心

优势:服务注册

劣势:整个系统设计是中心化的、需要从上至下设计、重构困难

微服务架构

彻底的服务化

优势:开发效率、业务独立设计、自下而上、故障隔离(服务粒度拆分很细,造成的影响最低)

劣势:治理、运维难度、观测挑战、安全性、分布式系统

核心要素:

  • 服务治理
  • 可观测性: 链路追踪
  • 安全: 服务调用必须要授权、身份验证

微服务

基本概念

服务:一组具有相同逻辑的运行实体

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

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

服务包含集群,集群包含实例

实例与进程的关系:没有比如安关系,一个实例可以对应一个或多个进程

实例承载形式:进程、VM、k8s pod

有状态/无状态服务:服务的实例是否存储了可持久化的数据

服务间通信:

对于单体服务,不同模块通信只是简单的函数调用。

对于微服务,服务间通信意味着网络传输。

服务注册及发现

如何指定调用一个目标服务的地址(ip : port )?

方案一:硬编码

// 硬编码
client := grpc.NewClient("10.23.345.67:8080")
  • 地址动态变化,不可能写死
  • 一个服务有多个实例,不可能写死

\

方案二:域名 + DNS

  • 本地DNS存在缓存,导致延时
  • 负载均衡问题,一个域名指定三个ip,但往往只会返回第一个ip
  • 不支持服务实例的探活检查
  • 域名无法配置端口,仍然要硬编码:8080

\

方案三:新增一个同意的服务注册中心,用于存储「服务名」到「服务实例」的映射

可以自己实现负载均衡算法

服务实例上线及下线过程

直接下线?有流量过来,直接线上产品故障

下线:首先把服务注册中心中对应实例的映射删除,然后下线实例

上线:先把服务的实例提起来,再注册到服务注册中心

流量特征

统一网关入口

内网通信多数采用RPC

网状调用链路

核心服务治理功能

服务发布

服务发布,即指让一个服务「升级」运行新的代码的过程

难点:

  • 服务不可用
  • 服务抖动
  • 服务回滚:不管问题是什么,先回滚,将损失降到最小

方案一:

蓝绿部署:分集群,控制流量

简单,稳定,但需要「两倍资源」

方案二:

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

服务回滚对基础设施的要求特别高,k8s这方面做的比较好

流量治理

基于地区、集群、实例、请求等维度,对端到端流量的路由路径选择

负载均衡

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

稳定性治理(企业实践关键)

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

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

客观的因素没办法避免,需要稳定性治理:

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

\

企业服务治理实践

本地函数调用没有特殊重试的意义。

远程函数调用有重试的必要。

重试可以避免偶发的错误,提高SLA(Service-Level Agreement)

重试的意义:

  • 降低错误率
  • 降低长尾延时
  • 容忍暂时性错误
  • 避开下游故障实例

\

重试这么好,为什么默认不用呢?

难点:

  • 幂等性:发生一次和发生多次,效果一样
  • 重试风暴:长链路下重试次数几何增加(限制重试比例)(防止链路重试,用特殊的status“请求失败,但别重试”)
  • 超时设置:超时时间通用设置不了(长尾99时间设置)