f10@t's blog

重新审视微服务

字数统计: 2.6k阅读时长: 8 min
2023/10/09

曾写过一篇文章"微服务入门-5W和微服务思想",想要搞清楚微服务是什么?来源?作用?微服务架构本质上是分布式架构,这方面我没有经验或理论基础,因此对微服务技术本身的目的和体系也是一知半解。

最近阅读了一本22年的书《分布式系统架构与开发》,作者是郑天民。基于该书的内容重新整理关于一下微服务技术及其生态的"思维导图"。

讨论微服务架构本身之前,先要清晰它上层的概念——分布式系统(Distributed System)。即指:软件或硬件分布在不同的网络计算机上,彼此之间仅仅依靠消息传递进行通信和协调的系统。

分布式系统意义何在?如何改造?

那好端端的把他们分布在多个网络计算机上干什么?意义在哪里?

我们平时自己写的应用,比如一个springboot应用,其涵盖了业务代码、中间件(如运行环境tomcat)等,在代码规模不大也即业务不复杂的情况下,具有:

  • 便于维护。没几个人参与。
  • 部署简单。比如打成jar包。

但随着:

  • 业务的不断扩展。比如你想要添加很多其他的功能进来,这个单块系统(Monolith System)就会越来越庞大,比如利用Maven,管理了大量的Module。
  • 业务结构的不断变化。以往的老旧代码会不断传下去,导致代码腐化的问题。
  • 产品用户量的不断增加。如请求量不断增大,导致系统可伸缩性无法满足的问题。

拿着针对上述的三个问题,我们此时就需要将单块系统改造为分布式系统,从而解决上述问题。

怎么改?有指导思路依据吗?

方法——系统拆分。怎么拆?——纵向拆分横向拆分。区别?

假设我们有一个商城系统,涵括诸多业务如商品下单业务等。这两种不同思路怎么分?

  • 纵向拆分关注业务,将一个大应用拆分为多个小应用,如果新业务较为独立,则可以直接设计部署为一个单独的应用系统。如下图,将一个内聚度较高的业务剥离以形成不同的子系统。

  • 横向拆分关注技术,将可以复用的业务拆分出来并独立部署为分布式服务,其他新业务可以直接调用这些分布式服务完成构建。很像轮子的思路,如下图:

因而纵向拆分要点是识别内聚度高的业务;而横向拆分的要点是识别可复用的业务。

那这么一拆就算改造好了吗?

事情没有想象的那么好。

分布式系统区别于单块系统的最大特点,即是引入了网络通信的部分。

毕竟单块应用都是在本地来回调用的,不存在这部分的内容。那么这样的特点带来的问题或挑战是什么呢?

  • 网络通信三态性。因为网络通信的结果存在三种可能:成功、失败、超时。要分别处理对应情况。
  • 请求的容错性。拆分后,你的某一个服务由于比如断电了,不可用了怎么办?上层业务就无法使用该业务了。
  • 系统的异构性。由于部署在不同的机器上,存在网络不同、操作系统不同、技术体系不同的问题,这可能就导致了开发过程中存在诸多不便。那如何实现一种通用的服务集成和交互方式来屏蔽掉上述差异呢?
  • 数据的一致性。假设多个相同的服务运行在不同的机器上,由于网络异常出现了网络分区的问题,此时总不能这个服务说用户A还有5块钱,那个服务说是4块钱吧?即如何在数据被分散或复制到不同机器上时、确保各台主机之间数据的一致性?

因而在对单块系统改造的时候,我们还需要考虑上述问题。

微服务架构特点

那它和传统分布式架构区别在哪里?

在上述传统分布式架构的四个特性的基础上,微服务架构还提倡服务的组件化,且组件之间尽可能使用如RESTful的轻量级通信方式进行服务集成,确保技术无关性。而不是采用一些私有化协议和重量级通信方式。

Martin Flowler指出,微服务架构特点如下:

  • 服务组件化。即实现服务的独立部署,假设应用由多个不同组件组成,那么只需要重新部署那个改变了的服务就可以完成替换或升级。
  • 按业务能力组织服务。研发团队划分时,倾向于围绕业务功能的组织分割出特征团队,而不是按照技术来划分(如App前端、服务器端等职能团队)。这样的特征团队是跨职能的,具备多项技能如用户体验、项目管理、技术开发等。
  • 去中心化。技术上,将组件拆分为不同服务,各自可以选择适合的语言、工具;数据上,对数据进行分散管理,每个微服务管理自己的数据库。
  • 基础设施自动化。除了CI/CD,也要依赖基础设施自动化技术,比如Vagrant,通过编写yaml文件,就可以自动化的生成一个虚拟机了。

既然有上述特点,如何设计微服务架构呢?有理论指导吗?

首要切入点——服务建模。方法?——领域驱动设计(Domain Driven Design)。(ps:这部分内容我还一直没有学习。

微服务系统核心设计要求以及对应技术开发组件

讨论技术开发组件之前,先要明确需求或设计要求,知其所然而所以然

核心设计要求

一共分为四点,性能、可用性、可扩展性和服务治理。我将一一列举其含义、面临的挑战和解决意义。

性能,如何衡量?哪些指标?

性能的具体表现有两方面:当前承载体量下的执行能力未来流量变化时的弹性处理能力。具体衡量指标如:

  • 响应时间
  • 系统吞吐量
  • 架构的可伸缩性
  • 性能问题
  • 峰值负载

可用性,什么意思?有什么意义吗?如何确保?

可用性指在业务需要时能够完整提供服务并有效处理影响其可用性的故障的能力。

一些常见事件如系统升级、停机、维修、备份、灾难恢复等,都会对服务产生一些影响,因而需要对应的实施计划。

具体方法如使用容错硬件、容错软件、引入服务的降级和限流机制、确保采用主流的集群和负载均衡机制(如四层、七层负载均衡)、加强日志管理和分析、采用组件复制策略等。

可扩展性,和可伸缩是一个东西吗?有什么意义吗?如何确保?

扩展指系统对自身灵活性及实现这种灵活性索要付出的成本进行平衡的能力。良好可扩展性意味着可以以较低的成本扩展出新的特性或业务。注意可扩展的是业务的可扩展性,区别于性能中的可伸缩性,后者指的是性能。

为了提高可扩展性可以从两方面考虑。加强产品管理,从需求源头把握变化以降低后续不必要变更;采用合理的技术方法,如采用异步消息等实现系统解耦、尽量使用SPI等业内标准技术,确保较高的可扩展性。

服务治理,为什么要治理?怎么治理?

对于一个微服务系统,其中可能包含了数百个服务,因而存在如下三个问题:

  • 有哪些服务在运行?
  • 部署方式调整后,服务自身暴露状态的动态性
  • 有多少服务在运行?什么状态?

也即总结为两个挑战:

  • 服务实例的数量如何管理?
  • 服务实例的状态如何管理?

针对上述挑战,我们就需要引入服务治理的方法和工具。对每个服务实例信息进行抽象并构建一个独立的媒介来管理这些服务实例信息,且这个媒介要具备服务注册和发现机制。此外,我们还需要引入系统监控和链路跟踪等技术,确保对出现的异常情况进行及时的干预。

开发技术组件

针对上述的四个要求:性能、可用性、可扩展性、服务治理,我们可以梳理为如下三类组件(图片来自原书,我增加与上述问题的提炼):

后话:关于服务网格技术

上述开发技术架构虽然可以满足我们的需求、解决面临的问题,但是也存在代码侵入高的问题,如依赖文件、配置文件等,这就导致了其版本升级对业务代码存在一定影响的问题。

因而2016年国外Buoyant公司提出了服务网格(Service Mesh)的概念,按照数据层面和控制层面进行划分,将上述组件如网络通信、负载均衡、容错等功能下沉。具体来说,基于K8s平台,数据平面上,以Sidecar方式部开源Envoy实现流量代理;控制平面上,依靠istiod对所有代理进行管理和配置。最终实现了将业务与微服务组件分离的效果,从而解决了上述问题。

业内成熟框架Istio的架构图如下所示:

参考学习

  • 《分布式系统架构与开发 技术原理与面试题解析》——郑天民
  • Istio / Architecture

CATALOG
  1. 1. 分布式系统意义何在?如何改造?
  2. 2. 微服务架构特点
  3. 3. 微服务系统核心设计要求以及对应技术开发组件
    1. 3.1. 核心设计要求
    2. 3.2. 开发技术组件
  4. 4. 后话:关于服务网格技术
  5. 5. 参考学习