微服务架构笔记 | 青训营笔记

125 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
本文总结微服务架构课程中所做的笔记,行文逻辑是课堂上讲解的逻辑,并对其中弄不懂的概念进行了穿插注释。

微服务架构介绍

系统架构演变历史

原因:互联网爆炸性发展、硬件设施快速发展……

单体架构

将所有的业务场景的表示层、业务逻辑层和数据访问层放在一个工程中,最终经过编译、打包,部署在一台服务器上。

优点:性能最高、冗余小

缺点:debug困难、模块相互影响

垂直应用架构

按照业务线把项目垂直划分成多个子项目

优点:业务独立开发维护

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

分布式架构

抽出业务无关的公共模块,根据业务性质的不同做好分层

优点:业务无关的独立服务

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

SOA(Service Oriented Architecture)架构

在分布式架构的基础上进一步优化,面向服务,引入服务和服务注册的概念

优点:服务注册,解耦

缺点:整个系统设计是中心化的、需要自上至下设计、重构困难

微服务架构

是SOA架构的一种拓展,这种架构模式下它拆分粒度更小,服务更独立,把应用拆分一个个微小的服务。

优点:开发效率高、业务独立进展、自下而上、故障隔离

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

….

微服务架构核心要素:服务治理、可观测性、安全

微服务架构原理及特征

基本概念

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

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

实例与进程:没有必然的对应关系,一个实例通常对应一个或多个进程

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

服务注册与发现

如何在代码层面调用目标服务的地址?

  • 指定ip:port?

    • 因为服务实例的IP和端口本身是动态变化的
    • 一个服务有多个实例,对应多个IP
  • 指定域名DNS?

    • 本地DNS存在缓存,导致延时
    • 负载均衡问题
    • 不支持服务实例的探活检查
    • 域名无法配置端口
  • 服务注册与发现:

    • 新增一个统一的服务注册中心,用于存储服务名到服务实例的映射。如下图所示:

服务.jpeg

服务上线及下线

下线:先把在服务注册中心注销相应的映射,然后再下线机器

上线:先上线机器,再将IP及端口写道服务注册中心

流量特征(流量视角微服务长什么样子):

统一网管入口

内网通信多采用RPC

网状调用线路

核心服务治理功能

服务发布

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

难点:服务不可用、服务抖动、服务回滚

实践

蓝绿部署:

  • 将服务分成蓝绿两个部分,分别先后发布
  • 简单、稳定
  • 但需要两倍资源(因此在流量低峰时进行蓝绿部署)

灰度发布(金丝雀发布):金丝雀发布通过在生产环境中小规模地部署新版本,以便在生产环境中评估新版本的影响,并通过监控和诊断工具来验证新版本是否正常工作。如果新版本发现了问题,可以立即回滚。

  • 先发布少部分实例,接着逐步增加发布比例
  • 不需要增加资源
  • 回滚难度大,基础设施要求高

流量治理

在微服务架构中,可以从各个维度(地区、集群、实例、请求)对端到端的流量在链路上进行精确控制,如下图所示

负载均衡

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

  • 常见的LB策略
    • Round Robin(轮询调度):是一种以轮询的方式依次将一个域名解析到多个IP地址的调度不同服务器的计算方法。
    • Random:随即调度
    • Ring Hash:一致性哈希算法
    • ……

稳定性治理

定义:线上服务总是会出现问题,这与程序的正确性无关

原因

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

方法

限流:下级服务无法处理上级服务传递的全部数据,便会reject一些

熔断:在下级服务濒临崩溃的时候,立即中断服务,从而保障系统稳定避免崩溃

过载保护:是指负载超过系统的承载能力时,系统会自动采取保护措施,确保自身不被压垮。

降级:当服务过载,重要服务能正常工作,不重要的服务被reject

字节跳动服务治理实践

重试的意义:

  • 重试可以避免掉偶发的错误,提高SLA(sevice-level agreement)不过需要注意,本地函数调用没有重试的必要,远程函数调用有重试的必要(因为有可能因为网络问题导致函数调用失败)。

  • 降低错误率

  • 降低长尾延时

    • 对于偶尔耗时较长的请求,重试请求有机会提前返回
  • 容忍暂时性错误

  • 避开下游故障实例

重试的难点

幂等性:多次请求导致的数据不一致

重试风暴:服务分成很多级,随着调用深度的增加,重试次数指数级上涨

超时设置:超时时间的选择依赖于具体的情况,不能一概而论

重试风暴的解决措施

限制重试比例:设定一个重试比例阈值(例如1%),重试次数占所有比例不超过该阈值。因为重试只有在大部分请求成功,少量失败时才有必要,如果大部分请求失败,重试只会增加问题的严重性

防止链路重试:限制每层都发生重试,理想情况下只有最下一层发生重试,如果最下一层重试失败,可以返回特殊的状态变量status,表明请求失败,但不要重试

hedged request:对于可能超时的请求,重新向另一个下游实例发送一个相同的请求,并等先到达相应的效果:

思考题

  • 结合 CAP 等原理,思考微服务架构有哪些缺陷?
    • 维护数据一致性比较困难
    • 随着微服务数量增多,系统的复杂度和成本相应增加
    • 分布式链路难以跟踪,测试困难
  • 微服务是否拆分得越“微”越好?为什么?
    • 并不是,期间微服务的分解要考虑到业务需求,代码耦合度和维护难度等因素。
  • Service Mesh 这一架构是为了解决微服务架构的什么问题?
    • 解决系统架构微服务化后的服务间通信和治理问题