架构师进阶,微服务设计与治理的16条常用原则

简介: 架构师进阶,微服务设计与治理的16条常用原则

上一篇文章我们从「存储选型」角度学习了架构师的基本能力。


今天将从存储的上一层「服务维度」学习架构师的第二项常用能力——微服务设计与治理。

  • 如何设计合理的微服务架构?
  • 如何保持微服务健康运行?

这是我们对微服务进行架构设计过程中非常关注的两个问题。


本文对微服务的生命周期定义了七个阶段,如下图所示。

640.png

围绕这七个阶段总结了16条常用原则。


1、微服务规划


原则1:按照业务能力(business capabilities)来规划或拆微服务。


康威定律:Conway’s law: Organizations which design systems[…] are constrained to produce designs which are copies of the communication structures of these organizations.
(设计系统的组织,其产生的设计和架构等价于组织间的沟通结构。)


组织的沟通和系统的设计之间紧密相连,特别是复杂系统,解决好人与人的沟通才能有一个更好的系统设计。


《人月神话》中总结出了随着人员的增加沟通成本呈指数增长的规律:沟通成本 = n(n-1)/2。举例说明:

  • 5人项目组,需要沟通的渠道是 5*(5–1)/2 = 10
  • 15人项目组,需要沟通的渠道是15*(15–1)/2 = 105
  • 50人项目组,需要沟通的渠道是50*(50–1)/2 = 1,225


系统越复杂,人手越多,沟通成本也呈指数增长。因此,分而治之便是大多数公司选择的解决方案。分不同的层级,分不同的小团队,让团队内部完成自治理。


原则2: 按照领域驱动设计(Domain-Driven Design,DDD)来规划或拆解微服务。

领域驱动设计是微服务领域的热门话题,本文不展开说明,仅说明几点重要事项:

  • 基本过程:抽象业务、分析流程、识别边界、建立模型、映射到服务和代码
  • 避免过度耦合、存在贫血领域对象等情况
  • 划分界限上下文,厘清上下文之间的映射关系,比如合作关系、共享内核、客户方-供应方开发、防腐层、开放主机服务等等。
  • 细化上下文对象,区分实体、值对象、聚合根、领域服务、领域事件

原则2与原则1的区别在于,原则1关注组织架构领域,原则2更偏向软件工程设计领域。


2、微服务设计


原则3:微服务的设计应该遵循「单一职责」原则

所谓单一职责原则,就是对一个服务而言,它的功能要单一,只做与它相关的事情。在微服务的设计过程中要按职责进行设计,彼此保持正交,互不干涉。


什么样的单一领域对象的单一职责微服务才是有价值的?就是不断有业务变化,能够维持业务持久性,有业务生命力的领域对象。举例来说:

  • 与别的功能点相比,调用频率非常高
  • 或者其数据量存量大,数据增速快,TB级甚至是PB级的。


那么就很有价值独立为一个微服务,实现独立演进、个性化的弹性伸缩。


所以,我们在进行微服务设计时,要能够分析、预测出需求变化的点在哪里?高并发的点在哪些?数据增长的位置在哪里?与DDD分析相结合,找出最有价值的那个单一职责,进行合理、适度的领域、子领域、有界上下文分解,才能更好的应对复杂的业务、不断变化的业务。


原则4: 微服务的设计应该遵循「高内聚」原则

过度追求「单一职责」,或者拆分微服务过细,往往会带来不良后果。微服务的设计并不是越细越好,过度拆分会导致调用性能变差、数据一致性难以保障、系统可用性降低等问题。


因此,「高内聚」原则要求:

  • 完全独立。微服务粒度的下界是它至少应满足独立,能够独立发布、独立部署、独立运行与独立测试
  • 足够内聚。强相关的功能与数据在同一个服务中处理
  • 足够完备。一个服务包含至少一项业务实体与对应的完整操作

    原则5:微服务的设计应该遵循「低耦合」原则

  • 避免数据过度暴露
  • 避免数据库共享
  • 最小化同步调用,如有必要,引入事件驱动进行异步调用


3、微服务实现


原则6:服务无状态。

什么是「状态」?如果一个数据需要被多个服务共享,才能完成一笔交易,那么这个数据被称为状态。


依赖这个「状态」数据的服务被称为有状态服务,反之称为无状态服务。


「无状态」原则并不是说在微服务架构里就不允许存在状态,而是要把有状态的业务服务改变为无状态的计算类服务,那么状态数据也就相应的迁移到对应的“有状态数据服务”中。

640.png

场景说明:例如我们以前在本地内存中建立的数据缓存、Session缓存,到现在的微服务架构中就应该把这些数据迁移到分布式缓存中存储,让业务服务变成一个无状态的计算节点。迁移后,就可以做到按需动态伸缩,微服务应用在运行时动态增删节点,就不再需要考虑缓存数据如何同步的问题。


只有服务无状态,才能实现快速弹性扩缩容,应对流量峰谷。


原则7:服务高可用。

接入高可用中间件(如sentinal),实现限流、熔断、降级,增强可用性


原则8:服务可观测。

除了默认系统监控外,微服务需要梳理并定义必要的「业务监控指标」。


原则9:服务配置可管理。

微服务相关配置需要统一接入配置中心进行管理、控制。


4、微服务调用


原则10:避免「分布式大单体」

只做单向调用,避免循环调用。

多个服务循环依赖调用形成集中式“分布式大单体”,违背微服务的原则。


原则11:异步解耦。

按需接入消息队列,实现「依赖解耦」、「流量削峰」

  • 串行同步调用异步化,提高响应能力和响应速度
  • 应对突发流量,实现流量削峰与流量控制
  • 解耦核心业务逻辑不必要的依赖
  • 业务设计中的最终一致性


原则12:引入BFF层,降低客户端与后端微服务之间的耦合

尽量设计BFF层,把前端的特殊需求交给BFF层,使后端服务逻辑具有高内聚、高复用性的精简核心逻辑。


5、微服务发布


原则13:服务发布遵循安全发布三板斧

保证「可灰度」、「可监控」、「可回滚」。


6、微服务治理


原则14:正视「架构腐化」,遵循「持续演进」原则

「架构腐化」的常见场景:

  • 多人维护一个微服务,出现「频繁代码冲突」,影响快速迭代,那么这个微服务就需要拆分了。
  • 当你修改了一个边角的小功能,但是你不敢马上上线,因为你依赖的其他模块才开发了一半,出现大量「功能耦合」,那么这个微服务就需要拆分了。
  • 当你发现微服务A内聚合a的功能变成了海量高频业务。这时聚合a就会拖累整个微服务A,并且因为聚合a面临性能瓶颈,在微服务A进行弹性扩缩时,也会造成资源浪费。这时,我们就可以将聚合a从微服务A中整体拆分,独立为一个新微服务B。在资源配置方面也可以更加有针对性的投入到微服务B,可以随时满足高频访问的性能要求了。
  • 当你发现在领域建模时错误地将聚合d放到了微服务C里,或者随着业务发展聚合d更适合放在微服务D里。由于领域模型的不合适,可能会导致微服务之间出现频繁调用,进而导致微服务之间出现「紧耦合关系」。这时,我们就可以对领域模型做出调整,将聚合d从微服务C整体迁移到微服务D里。


原则15:参考「AKF扩展立方」模型,服务除了「水平扩容」外,还可以考虑「功能拆分」或者 「数据分区」

640.png

  • X轴:服务和数据的水平扩容。
  • Y轴:功能/业务拆分
  • Z轴:沿客户边界的服务和数据分区


「水平扩容」比较容易理解,直白点说就是加机器。根据AKF模型,除了加机器外,我们还可以考虑「功能拆分」或者 「数据分区」。


「功能拆分」相对复杂,一般包括几种模式:

  • 微服务拆分。根据具体业务模型、领域模型拆分更细粒度的微服务。
  • 业务隔离拆分。利用消息队列,将在线业务(OLTP)和耗费大量资源的计算任务拆分隔离。
  • 核心与非核心隔离。对于一个微服务,可以将SKA客户与普通客户进行隔离,SKA客户使用独立的集群资源,提高稳定性。


「数据分区」往往指的是数据库层面。需要引入数据库中间件,像 sharding-jdbc、mycat 等,在数据层面需要配置相应的分片逻辑。正确的拆分对提高系统的容量有很大的帮助,失败的拆分可能会造成热点集中,得不偿失。常用的分区逻辑包括 按照时间分区、按照用户id取模分区等。


7、微服务下线


原则16:对于「废弃服务」,需要做好「下线」工作,包括服务下线、存储释放等。

清理无效代码、环境,减少维护成本。同时释放资源,节约成本。


8、总结


架构师在进行微服务设计和微服务治理时,可以围绕微服务生命周期的七个阶段展开。

本文总结了16条常用原则,希望能提供一些思路和启发。

如果你有其他补充和建议,欢迎留言讨论。


往期热门笔记合集推荐:

  • HBase原理与实战笔记合集
  • MySQL实战笔记合集
  • Canal/Otter源码与实战笔记合集
  • Java实战技巧笔记合集
目录
相关文章
|
3天前
|
存储 监控 API
构建高效微服务架构:后端开发的现代实践
【5月更文挑战第9天】 在本文中,我们将深入探讨如何在后端开发中构建一个高效的微服务架构。通过分析不同的设计模式和最佳实践,我们将展示如何提升系统的可扩展性、弹性和维护性。我们还将讨论微服务架构在处理复杂业务逻辑和高并发场景下的优势。最后,我们将分享一些实用的工具和技术,以帮助开发者实现这一目标。
|
1天前
|
监控 API 开发者
构建高效微服务架构:后端开发的新范式
【5月更文挑战第12天】 在现代软件开发的浪潮中,微服务架构已经成为了设计复杂系统的首选模式。它通过将大型应用程序拆分成一组小而专注的服务来增强系统的可维护性和可扩展性。本文将探讨微服务架构的关键概念、优势以及如何在后端开发中实现一个高效的微服务系统。我们还将讨论一些常见的挑战和最佳实践,以帮助开发者避免陷入常见的陷阱。
13 6
|
1天前
|
存储 NoSQL MongoDB
【MongoDB 专栏】MongoDB 与微服务架构的结合
【5月更文挑战第11天】微服务架构流行趋势下,选择合适的数据库至关重要。MongoDB作为非关系型数据库,与微服务有天然契合度。其灵活的文档模型、水平扩展性、高性能及局部事务支持,满足微服务对数据模型多样性、高可用性、快速读写的需求。实践中,需注意数据划分、索引优化、监控调优和版本控制。未来,MongoDB在微服务中的应用将更广泛,新技术将提升其在微服务架构中的价值。
【MongoDB 专栏】MongoDB 与微服务架构的结合
|
2天前
|
监控 数据库 开发者
构建高效可靠的微服务架构:策略与实践
【5月更文挑战第11天】在当今软件开发的世界中,微服务架构已经成为构建可扩展、灵活且容错的系统的首选方法。本文深入探讨了设计、部署和维护微服务系统时面临的挑战,并提出了一系列实用的策略和最佳实践。我们将从服务的划分原则出发,讨论如何确保每个微服务的自治性,以及如何通过容器化和编排技术实现服务的高效运行。文章还将涉及监控、日志记录和故障恢复的策略,旨在帮助开发人员构建一个既高效又可靠的微服务环境。
|
2天前
|
Kubernetes API 开发者
构建高效微服务架构:后端开发的新范式
【5月更文挑战第11天】 在现代软件开发的快速演变中,微服务架构已成为企业追求敏捷性、可扩展性和技术多样性的关键解决方案。本文旨在探讨如何构建高效的微服务架构,并分析其对后端开发的影响。我们将通过一系列最佳实践和策略,展示如何优化服务的独立性、弹性和性能,同时确保系统的整体稳定性和安全性。文章还将介绍容器化、API网关、服务发现和分布式追踪等关键技术的应用,为后端开发者提供一份全面的微服务实施指南。
|
2天前
|
设计模式 监控 API
构建高效的微服务架构:后端开发的新范式
【5月更文挑战第11天】 在当今的软件开发领域,微服务架构已经成为一种流行的设计模式。它通过将应用程序分解为一组小型、松散耦合的服务来提供高度可扩展和灵活的解决方案。本文将探讨如何构建一个高效的微服务架构,包括选择合适的技术栈、设计原则以及应对常见挑战的策略。我们将深入讨论如何确保系统的可维护性、可靠性和性能,同时考虑到安全性和监控的需求。
|
3天前
|
监控 持续交付 Docker
使用Docker进行微服务架构的最佳实践
【5月更文挑战第10天】本文探讨了使用Docker实施微服务架构的最佳实践。首先,理解微服务架构是拆分小型独立服务的模式,借助Docker实现快速部署、高可移植性和环境一致性。Docker的优势在于服务扩展、容器编排、自动化构建与部署。最佳实践包括:定义清晰服务边界,使用Dockerfile和Docker Compose自动化构建,利用Docker Swarm或Kubernetes编排,实施服务发现和负载均衡,监控与日志记录,以及持续集成和持续部署。Docker虽重要,但需与其他技术结合以确保系统整体稳定性。
|
3天前
|
缓存 负载均衡 API
微服务架构下的API网关性能优化实践
【5月更文挑战第10天】在微服务架构中,API网关作为前端和后端服务之间的关键枢纽,其性能直接影响到整个系统的响应速度和稳定性。本文将探讨在高并发场景下,如何通过缓存策略、负载均衡、异步处理等技术手段对API网关进行性能优化,以确保用户体验和服务的可靠性。
|
3天前
|
监控 持续交付 开发者
构建高效微服务架构:后端开发的新范式
【5月更文挑战第10天】在现代软件开发领域,微服务架构已经成为一种流行的设计模式,它通过将大型应用程序拆分为一组小型、独立和松散耦合的服务来提供更高的可伸缩性和灵活性。本文深入探讨了微服务架构的设计理念、实施步骤以及面临的挑战,并提出了一套实用的策略和最佳实践,帮助后端开发者构建和维护高效的微服务系统。
|
4天前
|
负载均衡 算法 NoSQL
探索微服务架构下的服务发现与治理
【5月更文挑战第9天】 在当今的软件开发领域,微服务架构已成为构建可伸缩、灵活且容错的系统的首选模式。随着服务的增多,如何有效地进行服务发现与治理成为了关键的挑战。本文将深入探讨微服务环境中服务发现的机制和治理策略,分析不同服务发现工具的优缺点,并提出一种基于一致性哈希和健康检查相结合的服务治理方案,旨在提高系统的可用性和性能。