在软件架构领域,微服务架构已经成为许多企业应对复杂业务场景和快速变化需求的首选方案。微服务架构通过将庞大的单位应用拆分成一系列小型、独立的服务,每个服务都围绕着特定的业务能力进行构建和部署,从而带来了更高的可伸缩性、灵活性和可维护性。然后,如何合理地拆分微服务并不是一件简单的事情,它需要综合考虑业务、技术和组织等多个方面的因素。本文会从理论和实践两个角度,逐步探讨微服务拆分的原则、方法和最佳时间,帮助大家更好地理解和掌握微服务拆分这一关键技术。
单一职责原则是面向对象设计的基本原则之一,它要求一个类只负责一项职责,在微服务架构中,这一原则同样适用。每个微服务都应该具有清晰的业务边界和单一的职责,只负责完成一项特定的业务功能,这样可以确保微服务的内聚性高,耦合度低,便于独立开发、测试和部署。
服务自治是指每个微服务都应该具有独立的数据库、独立的开发团队和独立的部署环境,这样可以确保每个微服务都能够独立地进行版本迭代和功能升级,而不会对其他服务产生影响,同时,服务自治也有利于提高团队的协作效率和系统的可靠性。
持续集成和持续交付是敏捷开发的重要实践之一,强调将代码的开发、测试和部署过程自动化,以加快软件的交付速度。在微服务架构中,每个微服务都应该采用持续集成和持续交付的方式进行开发和部署,以确保代码的质量和系统的稳定性。
从拆分本身来讲,有水平和垂直两种拆分策略:
水平拆分是按照业务功能或者业务流程的不同阶段进行拆分,比如在电商平台中,按照水平拆分角度可以拆分为商品微服务、订单微服务、支付微服务等,每个微服务都处理电商流程中的一部分业务功能。这种拆分方式有利于各个微服务专注于自己的业务功能,提高内聚性,降低耦合度。
垂直拆分是按照系统的不同层次或者不同方面进行拆分,比如在一个垂直业务系统中,按照垂直拆分角度可以拆分为用户微服务、业务逻辑微服务、数据访问微服务,这是按照系统层级关系进行垂直拆分的。还有一种垂直拆分是按照不同的业务领域或者业务场景进行拆分,比如电商平台中的用户服务下会进一步拆分为买家微服务和卖家微服务两个独立的服务。
水平和垂直拆分的策略是拆分的最基本的策略,但在实际微服务拆分实践过程中,并不是如此简单的水平拆或者垂直拆,要根据系统的具体情况和业务场景,灵活结合水平和垂直的策略,这就会继续向往一层形成更细化的拆分策略,这将在下一部分拆分实践中详细介绍。
划定服务边界是微服务拆分过程中的关键步骤,它决定了每个微服务的职责范围和交互方式,从我实际经验来看,我给到大家一些在划定边界时应该要考虑的因素:
确保每个微服务包含完整的业务逻辑,避免跨服务调用导致的事务一致性问题,尽量将需要保持数据一致性的操作封装在同一个微服务内。
每个微服务应该具有高内聚性,就是服务内部的功能紧密相关;同时要保持低耦合性,目的就是减少服务间的依赖和交互复杂度。
在拆分微服务的时候,尽量让每个微服务拥有自己的数据存储,避免跨服务的直接数据访问,通过 API 进行数据交互,保持数据的独立性和隔离性。
在拆分之初就需要考虑拆分后的每个微服务的可扩展性需求,确保服务在面对增长时能够容易地进行横向扩展,同时要保证服务的可维护性,便于未来的功能迭代和问题排查。
根据业务需求和安全标准来划定服务边界,确保敏感数据和业务逻辑得到妥善的保护和隔离,比如数据隐私保护、访问控制等,是可以独立成为单独的微服务的。
服务边界的划定务必考虑团队的组织结构和协作方式,康威定律嘛,尽量让每个团队负责一个或多个微服务的全生命周期管理,以提高团队的协作效率和响应速度。
上面有讲到微服务拆分的水平策略和垂直策略是属于指导策略,但是在具体实践中还远远不够,根据我过往的经历,我把常用的拆分策略讲解如下:
基于业务功能进行微服务的拆分是最为常见的一种策略,在这个拆分策略指导下,要求我们先分析单体应用的业务功能,将紧密相关且内聚性高的功能划分为一个服务,也是符合高内聚与低耦合的原则,每个拆分出来的微服务对应一个完整的业务功能。这种拆分方法适用于大型公司有多个业务领域的场景,采用这种拆分方式有利于保持微服务的独立性和可维护性,同时也便于团队之间的协作和沟通。比如上面在水平拆分策略部分讲到的电商平台服务拆分例子。
基于数据流进行微服务拆分是一种在实践中更加细粒度的方法,在拆分之前要求将单体系统中的数据流有深度的分析和清晰的梳理,找到数据流的起点、终点和全生命周期中的各个关键点,然后根据这些点将系统进行拆分成多个独立的微服务。这种拆分方式一般不建议,因为需要对系统的数据流有深入的了解和分析能力,拆的好的话,是可以有利于优化系统的数据流和性能瓶颈的。比如在一个 CPS 系统中,我们根据数据流可以拆分为点击跟踪微服务、佣金计算微服务、佣金预结算微服务、数据对账微服务、佣金结算微服务等。
基于技术特性进行微服务拆分是一种相对比较灵活的方法,它要求根据系统中的技术特性和需求进行微服务的划分和设计。比如,你的系统中有实时计算功能和非实时计算功能,你可以拆分为两个独立的微服务;再者,你的系统中存在高性能需要和低性能需求的两种场景,可以分别拆分成不同的微服务。这种拆分方式虽然有利于发挥不同技术的优势和特点,但是对架构师的要比较高的技术要求,要求他们对技术有深入的了解和掌握能力。
在大量异步事件的系统中,可以考虑根据系统中的事件流来拆分微服务,对系统中的事件生产者和消费者进行全面分析,将相关的事件处理逻辑封装到一个独立的微服务中。
根据系统的性能需求进行拆分,比如我曾经做过的,把我当时系统中高负载的部分拆分为独立的微服务,便于对这部分进行单独的优化和扩展,这种策略有助于提高系统的整体性能和可伸缩性。
这个一般是多重技术栈并存的企业进行微服务拆分的首选策略,这种策略有助于发挥各种技术的优势,同时降低系统的复杂性。
基于 DDD 的方法根据业务领域的不同来拆分微服务,这种策略要求企业内有掌握 DDD 方法的人,首先要识别出系统的核心领域和子领域,然后为每个子领域去创建对应的一个或者多个微服务。这种策略有助于保持业务逻辑的清晰和一致性,但是要求比较高。
在进行微服务拆分时,可以总结提炼为以下四个步骤:
首先,对你所承担的系统进行全面分析,明确系统的业务边界和业务需求,有能力的我还是建议采用 DDD 的分析思想去做这个分析,通过对业务的深入分析和需求调研,找出系统中的核心业务功能和关键业务流程。
然后,根据这些功能和流程的明确结论,基于上面讲的原则、拆分策略、划定边界以及具体落地的拆分策略,进行微服务的划分和设计。
在这个过程中,一定要注意避免过度拆分和拆分不足的问题,要保持服务的合理力度和数量,不然后患无穷。
如果你是面临一个超大单体系统进行微服务拆分的话,我个人建议一个一个往外拆,不要一股脑玩,不然非常容易出事。如果你是一个从 0 到 1 的场景,那我建议你一定做好拆分前的准备工作,尽量拆分合理。
基于步骤一,有了相对明确的微服务拆分方案后,要根据这个方案充分考虑每一个可能成为独立微服务的服务的独立性和可维护性,每一个微服务要具有清晰的接口和明确的职责边界,能够独立地完成特定的业务功能。
这个过程中,要注意避免服务之间的循环依赖和过度耦合问题,一定要尽量保持服务的松耦合和高内聚特性。
完成以上两个步骤后,就要开始针对不同微服务的特性,选择合适的服务之间的通信机制进行服务之间的交互和数据传输,此时的目标是要保证服务间的通信效率和可靠性。
一般常见的通信机制有同步和异步两种,这个我之前的文章有过详细的介绍。这里不再赘述。
切记要根据具体的微服务承担的业务需求和技术特点来选择合适的通信机制,才能更好地提高系统的性能和稳定性。
如果你的微服务数量较多,且互相独立部署运行在不同的容器化环境中,一定要在服务投产前,做好服务的可观测性和可管理相关的设计。这样服务投产后,可以通过这两个设计结果及时发现问题并进行处理,而且这两项设计结果对保证系统稳定运行以及提高开发运维效率也有着非常重要的作用。
可以通过日志收集分析、监控告警等基础设施能力的构建,当然也可以基于云原生相关能力来达到这个目标,实现对微服务运行状态的实时监控和故障快速定位处理。
再加点猛料的话,你还可以采用服务网格等技术,来进一步增强微服务之间的通信安全性以及流量管理能力等,这些都是构成相对完善可靠易用易维护的微服务架构体系中不可缺少的组成部分。
读到这里,你是否对微服务拆分有了感觉了呢?请把你看完之后的感受留言给我,我们可以攒个场子,找个场景,玩一把拆拆游戏,如何呢?