微服务设计模式是一种指导微服务架构设计和开发的一系列原则和实践。微服务设计模式的目的是为了解决微服务架构中遇到的一些常见的问题和挑战,比如服务划分、服务通信、服务治理、服务测试等。微服务设计模式可以帮助我们构建出高效、可靠、可扩展、可维护的微服务系统。
本文将介绍以下十种微服务设计模式:
API 网关是访问任何微服务的入口点,位于客户端和微服务之间,负责处理诸如鉴权、限流、重试、负载均衡、服务发现等通用功能,以及根据客户端的需求进行数据过滤、映射和聚合等操作。这种模式可以简化客户端的逻辑,减少网络开销,保护后端服务,以及实现不同级别的 API 接口。在 Spring Cloud 中我们可以使用 Zuul 或 Spring Cloud Gateway 来实现这一点。
应用场景
服务注册与发现是一种用于管理微服务实例地址变化的技术。它可以让微服务之间通过一个统一的服务名来进行通信,而不需要知道对方的具体位置。它主要包括两个组件:服务注册中心和服务发现客户端。
引入服务注册与发现可以给微服务架构带来很多好处,例如,
常见的服务注册中心如下,
断路器是一种处理远程调用失败或超时的模式。由于微服务之间需要通过网络进行通信,因此可能会遇到网络故障、超时、拥塞等问题,导致远程调用失败或延迟。如果不及时处理这些问题,可能会造成雪崩效应(Cascading Failure),即一个失败的调用会引起其他调用的失败,最终导致整个系统崩溃。电路断路器模式可以避免这种情况,它类似于电路中的保险丝,当检测到某个远程调用出现故障时,就会切断该调用,防止进一步的损害,并尝试恢复该调用。在 Spring Cloud 中,我们可以使用 Hystrix 或 Resilient4J 来实现断路器。
断路器模式通常有三种状态:闭合(Closed)、打开(Open)和半开(Half-Open)。闭合状态表示远程调用正常工作,打开状态表示远程调用出现故障,半开状态表示远程调用正在恢复。电路断路器根据一定的条件和策略来切换这三种状态,比如故障次数、故障比例、故障时间等。电路断路器还可以提供一些备选方案来处理失败的调用,比如重试、降级、缓存等。
断路器行为类似于电路中的断路器。当连续的请求失败的次数超过阈值时,断路器将跳闸一段时间,并且在跳闸的这段时间内,所有远程服务调用的尝试都将立即失败。当超过了断路器跳闸时间之后,断路器将允许有限数量的测试请求通过。如果这些请求成功,则断路器将恢复正常操作。否则如果有一个请求失败,则断路器再次跳闸。对于一个应用试图尝试调用另一个远程服务或者获取共享资源,并且该操作很容易的失败的情况来说, 这个模式非常适用。
隔板模式(Bulkhead Pattern)通过根据需要调用的服务数量划分线程池,帮助处理与线程池相关的容错问题。例如我们在服务 A 中定义了一个 50 线程池,服务 A 会向服务 B 和 C 发出请求。因此服务 A 应该将 50 线程池分为 2 个(服务 B 25 个,服务 C 25 个),如果服务 C 不可用或需要较长时间来处理请求,则不会影响服务 B 调用,因为它有自己的线程池来执行作业。在 Spring Cloud 中,我们可以使用 Resilient4J 来实现这一点。
隔板模式类似于船体中一个个被隔离的分区。根据使用者负载和可用性要求,这些分区服务实例被分割到不同的组里面。这种设计模式有助于隔离故障(isolate failures), 并允许即使在故障期间仍可为某些使用者提供服务功能。
命令和查询职责分离(Command Query Responsibility Segregation,CQRS)模式,是一种将数据存储的读取操作和更新操作分离的模式。这种模式的目的是提高微服务的性能、可扩展性和安全性。CQRS 的基本思想是,对于不同的操作,可以使用不同的模型、服务和数据库。例如,读取操作可以使用一个优化了查询效率的数据库,而更新操作可以使用一个保证了数据一致性的数据库。这样就可以根据不同的需求来选择合适的技术和架构。
优点
缺点
微服务中的事件驱动模式是一种让微服务之间通过发布和订阅事件来进行异步通信的模式。事件是一种表示系统中发生了某种变化或动作的消息,比如订单创建、支付完成、用户注册等。事件驱动模式的优点是可以降低微服务之间的耦合度,提高系统的可扩展性、性能和可靠性,以及支持复杂的业务逻辑和流程。事件驱动模式的挑战是需要保证事件的顺序、一致性、幂等性和可追溯性,以及处理分布式事务和异常情况。事件驱动模式中的事件一般是通过消息队列发出,例如 RabbitMQ 或 Apache Kafka。
事件驱动模式让微服务之间通过发布和订阅事件来进行异步通信,而不是直接调用或依赖其他微服务的接口。这样每个微服务只需要关注自己的业务逻辑,而不需要知道其他微服务的存在和状态。
众所周知,处理分布式系统很困难,尤其是涉及分布式事务时,二阶段提交是最好的选择,但由于其悲观锁的性质使其难以扩展、性能较低,所以就有了 Saga 模式,是一种在分布式事务场景中跨微服务管理数据一致性的方法。Saga 是一系列事务,用于更新每项服务并发布消息或事件来触发下一个事务步骤。如果某个步骤失败,则 Saga 将执行补偿事务,以抵消上一个事务的影响。这种模式可以保证数据的最终一致性,同时避免了长时间锁定资源的问题。有两种常见的 Saga 实现方法,即协调和编排。 每个方法都有自己的一组挑战和技术来协调工作流。
协调是协调 Saga 的一种方法,参与者在没有集中控制点的情况下交换事件。 通过协调,每个本地事务都会发布在其他服务中触发本地事务的域事件。。
好处
缺点
编排是协调 Saga 的一种方法,在此方法中,中央控制器告诉 Saga 参与者要执行的本地事务。 Saga 编排器处理所有事务,并告知参与者根据事件执行哪项操作。 编排器执行 Saga 请求、存储和解释每个任务的状态,并通过补偿事务处理故障恢复。
好处
缺点
扼杀者(Strangler Pattern)模式是一种将单体应用逐渐迁移到微服务架构的模式,它的灵感来源于一种缠绕并杀死它所依附的树木的藤蔓植物。扼杀者模式的基本思想是,通过创建单体应用的新版本来替换旧版本,同时保持外部 API 不变,让客户端感知不到任何变化。随着转换进度的推进,最终所有功能都被重构为微服务,新架构“扼杀”取代了原来的单体架构。
扼杀应用(Strangler Application)的步骤分为转换,共存和消灭三步:
扼杀者模式的优点是可以渐进地进行微服务化,而不是一次性地重写整个应用,这样可以降低风险和成本,同时保持业务的连续性和稳定性。缺点是需要维护两套系统之间的兼容性和同步性,这可能会增加系统的复杂度和开发成本。
边车模式(Sidecar Pattern)是一种将一些与业务逻辑无关的功能(如日志、监控、配置、安全等)从主应用程序中分离出来,部署在同一个主机或容器中的一个独立的进程或服务中的模式。这样,主应用程序可以专注于自己的核心功能,而边车服务可以提供一些通用的功能,比如数据转换、网络通信、故障处理等。边车服务与主应用程序之间通过本地接口或共享内存来进行通信,从而实现高效和透明的协作。
边车模式的优点是可以降低微服务之间的耦合度,提高微服务的性能、可靠性和灵活性,以及简化微服务的开发和维护。缺点是需要额外的资源和管理成本,以及处理边车与主应用程序之间的通信和协调问题。
BFF 模式是一种为前端定制的后端的模式,它的全称是 Backend for Frontend。BFF 模式的目的是将后端的微服务根据不同的前端渠道和场景进行适配和聚合,提供给前端友好和统一的 API,从而提升前端的用户体验和开发效率。BFF 模式可以让前端与后端之间实现更好地解耦和协作。
BFF 模式的优点是可以根据不同的前端需求来定制和优化 API,避免了过度抽象或者冗余的 API,提高了网络传输和数据处理的效率。缺点是需要额外的开发和维护成本,每个前端渠道都需要一个对应的 BFF,可能会导致代码重复或者不一致。
应用场景
以上的十种设计模式能帮助我们构建扩展性良好的软件系统,但是在生产实践中,我们还需要根据具体的业务场景和需求来引入合适的微服务设计模式。
最后感谢大家阅读,希望本文能对你有所帮助.
关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!