微服务架构原理与治理实践 | 豆包MarsCode AI 刷题

81 阅读7分钟

微服务架构

系统架构演变历史

单体架构

项目的所有模块均部署在一台机器上。

屏幕截图 2024-11-25 110514.png

优势:

  • 性能最高

  • 冗余小

劣势:

  • 大量程序员开发一个程序,导致 debug 困难。

  • 不同模块之间互相依赖,互相影响。

  • 单个项目仓库几乎无法模块分工,依赖管理,开发流程设置。

垂直应用架构

按照业务线垂直划分成多个模块。

屏幕截图 2024-11-25 110533.png

优势:

  • 业务独立开发维护。

劣势:

  • 不同业务之间存在冗余,无法进行复用。

  • 每个业务还是单体架构的。

分布式架构

抽取业务无关的公共模块,分布式独立部署运行。

屏幕截图 2024-11-25 110547.png

优势:

  • 使得业务无关的服务相互独立

劣势:

  • 一个模块服务有问题,可能导致整个系统崩溃。

  • 不同模块之间的调用关系错综复杂。

  • 不同服务之间依然存在冗余。

SOA ( Service Oriented Architecture ) 架构

SOA 也就是面向服务的架构,开始引入“服务”,“服务注册”的概念。不同服务的调用通过服务注册中心实现。

屏幕截图 2024-11-25 110601.png

优势:

  • 服务注册

劣势:

  • 整个系统从设计上依然是中心化的

  • 整个服务架构需要从上至下去设计划分

  • 重构困难

微服务架构

彻底的服务化,不同服务模块之间,通过某种通信机制进行互相调用、协作。

屏幕截图 2024-11-25 110615.png

优势:

  • 不同模块之间完全独立,开发、迭代效率高

  • 业务独立设计

  • 故障隔离,某个服务模块挂了,不会影响其他服务模块。

缺点:

  • 治理、运维难度大

  • 服务运行观测挑战

  • 安全性

  • 分布式系统本身的复杂性

微服务架构核心要素

  • 服务治理:服务注册、服务发现、负载均衡、动态扩缩容、流量治理、稳定性治理

  • 可观测性:日志采集、日志分析、监控打点、监控大盘、异常报告、链路追踪

  • 安全:身份验证、认证授权、访问令牌、审计、传输加密

微服务架构原理及特征

基本概念

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

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

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

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

  • 常见的实例载体:进程, VM, k8s pod ...

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

  • 服务间通信

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

    • 对于微服务,服务间通信意味着需要进行网络传输。

服务注册及发现

在代码层面,如何指定调用一个目标服务的地址( ip:port )?一个最朴素的想法是直接在代码中写死固定目标服务地址:

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

但这存在一些问题,服务是有多个实例的,服务实例本身的 ip + port 是动态变化的,所以没有办法在代码中写死 ip + port.

屏幕截图 2024-11-25 112240.png

其次,可以想到通过 DNS 来记录目标服务地址。但是 DNS 依然存在一些问题:

  • 本地 DNS 存在缓存,导致延时。

  • 负载均衡问题。

  • 不支持服务实例的探活检查。

  • 域名无法配置端口。

屏幕截图 2024-11-25 153349.png

于是,正确的解决思路是:新增一个统一的服务注册中心,用于存储服务名到服务实例的映射。

屏幕截图 2024-11-25 170406.png

如果现在想下线一个服务实例,不能直接下线,因为还有流量在访问该实例。

于是,先在服务注册中心中删除该服务实例映射,防止新的流量访问该实例。

屏幕截图 2024-11-25 171059.png

当该实例上所有请求都处理完毕时,下线该实例。

屏幕截图 2024-11-25 171214.png

屏幕截图 2024-11-25 171231.png

如果我想上线一个新的实例,首先需要检查以下该实例是否正常。

屏幕截图 2024-11-25 171432.png

然后,再将该实例注册到服务注册中心。

屏幕截图 2024-11-25 171649.png

核心服务治理功能

服务发布

蓝绿部署

一共有两套系统:一套是正在提供服务系统,标记为“绿色”;另一套是准备发布的系统,标记为“蓝色”。蓝色系统用来做发布前测试,测试过程中发现任何问题,可以直接在蓝色系统上修改,不干扰用户正在使用的系统。

蓝色系统经过反复的测试、修改、验证,确定达到上线标准之后,直接将用户切换到蓝色系统。

切换后的一段时间内,依旧是蓝绿两套系统并存,但是用户访问的已经是蓝色系统。这段时间内观察蓝色系统(新系统)工作状态,如果出现问题,直接切换回绿色系统。

当确信对外提供服务的蓝色系统工作正常,不对外提供服务的绿色系统已经不再需要的时候,蓝色系统正式成为对外提供服务系统,成为新的绿色系统。 原先的绿色系统可以销毁,将资源释放出来,用于部署下一个蓝色系统。

优势:简单、稳定。劣势:需要两倍资源。

屏幕截图 2024-11-25 175953.png

灰度发布(金丝雀发布)

在灰度发布开始后,先启动一个新版本应用,但是并不直接将流量切过来,而是测试人员对新版本进行线上测试,启动的这个新版本应用,就是我们的金丝雀。

如果没有问题,那么可以将少量的用户流量导入到新版本上,然后再对新版本做运行状态观察。

当确认新版本运行良好后,再逐步将更多的流量导入到新版本上,在此期间,还可以不断地调整新旧两个版本的运行的服务器副本数量,以使得新版本能够承受越来越大的流量压力。直到将100%的流量都切换到新版本上,最后关闭剩下的老版本服务,完成灰度发布。

如果在灰度发布过程中(灰度期)发现了新版本有问题,就应该立即将流量切回老版本上,这样,就会将负面影响控制在最小范围内。

劣势:回滚难度大,基础设施要求高。

屏幕截图 2024-11-25 205038.png

负载均衡

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

常见的负载均衡策略:

  • Round Robin 轮询:按照顺序轮流将请求分配给不同的服务器。

  • Random 随机:随机选择服务器来处理请求。

  • Ring Hash 一致性哈希:将哈希空间想象成一个圆环,每个服务节点映射到这个环上,每次请求也映射到这个环上,并按照顺时针顺序(哈希值增大),找到第一个服务节点转发请求。即使,服务节点数量有变化,也无需改变哈希策略。

  • Least Request 最小请求:将请求发送给当前处理连接数最少的服务器。

屏幕截图 2024-11-25 211720.png

稳定性治理

限流

设置最大 qps, 超过直接拒接。

屏幕截图 2024-11-25 220033.png

熔断

当某个模块服务出现故障而调用失败时,通过直接返回一个默认的错误响应,而不是继续调用该服务,防止整个系统因为单个服务的故障而陷入瘫痪。并在适当的时候自动恢复服务调用。

屏幕截图 2024-11-25 220043.png

过载保护

当服务节点 CPU 过载时,直接拒绝大量的请求。

屏幕截图 2024-11-25 220053.png

降级

在系统面临高负载或资源紧张的情况下,牺牲非核心功能的可用性,来确保核心功能的正常运行。

屏幕截图 2024-11-25 220103.png