本文承接我的另一篇博客微服务之间的相互调用的几种常见实现方式对比_微服务之间怎么互相调用-CSDN博客
目录
[1. Zuul](#1. Zuul)
[2. Spring Cloud Gateway](#2. Spring Cloud Gateway)
[Spring Cloud Stream](#Spring Cloud Stream)
[RESTful API与消息队列](#RESTful API与消息队列)
五、消息队列
消息队列是一种通过发送和接收消息来实现微服务之间异步通信的方式。常用的消息队列系统有RabbitMQ、Kafka、RocketMQ等。服务之间不直接调用,而是通过消息队列进行异步消息传递。
-
RabbitMQ: 基于AMQP(高级消息队列协议)的开源消息队列,提供了可靠性、灵活的消息传递机制。
-
Apache Kafka: 分布式事件流平台,通过持久化日志来处理大规模的实时数据。
-
Apache ActiveMQ: 开源的消息和集成模式服务总线,支持多种协议。
特点
它具有以下特点:
- 异步通信:消息队列允许发送方将消息发送到队列中,接收方可以异步地从队列中获取和处理消息。
- 松耦合:消息队列解耦了微服务之间的直接依赖关系,每个微服务只需要关注自己的消息消费逻辑。
- 可靠性:消息队列通常具有持久化机制,确保消息在发送失败或接收方不可用时不会丢失。
然而,使用消息队列也会带来一些考虑和挑战:
- 复杂性增加:消息队列的使用引入了额外的组件和配置,增加了系统的复杂性。
- 异步处理:由于消息队列是异步的,需要考虑处理顺序、消息重试和幂等性等问题。
- 系统延迟:由于消息的传递和处理需要时间,可能会引入一定的系统延迟。
适用场景
消息队列适用于需要异步处理、解耦的场景,如日志记录、通知推送等。例如,用户下单后需要通知库存系统,订单系统与库存系统通过消息队列进行通信。
- 异步任务处理:将耗时的任务放入消息队列中,由后台的异步任务消费者进行处理。
- 应用解耦:通过消息队列实现不同模块之间的解耦。
- 流量削峰:在系统面临大量请求时,通过消息队列平衡系统负载。
在实际项目中,使用消息队列可以有效地解耦微服务之间的依赖关系,提高系统的可伸缩性和弹性。以下是一些在实践中的最佳实践建议:
- 消息序列化: 确保消息的序列化和反序列化过程高效可靠。
- 消息确认机制: 使用消息确认机制确保消息在传输过程中的可靠性。
- 错误处理: 处理消息发送和接收过程中可能出现的异常情况,保证系统的健壮性。
- 监控与管理: 使用监控工具监控消息队列的健康状态,及时发现和解决问题。
六、服务代理
微服务代理模式是指在微服务架构中,通过引入一个代理层来管理和优化服务间通信的过程。这个代理层负责处理服务间的请求、响应、路由、负载均衡等,从而提高系统的性能、稳定性和可维护性。
微服务代理模式的主要作用包括:
- 简化服务间通信:通过代理层统一管理和优化服务间通信,降低服务之间的耦合度,提高系统的可维护性。
- 提高性能:通过负载均衡、缓存、限流等手段,提高服务间通信的效率和系统的整体性能。
- 增强安全性:代理层可以对服务间通信进行安全校验,防止恶意攻击和数据泄露。
- 提供监控和日志功能:代理层可以收集服务间通信的日志和监控信息,方便系统运维人员快速定位问题。
特点
它具有以下特点:
- 提高系统的可伸缩性:微服务代理模式可以将服务间的通信负载分散到多个代理节点上,实现负载均衡,从而提高系统的可伸缩性。
- 降低服务耦合度:通过代理层统一管理和优化服务间通信,微服务代理模式可以降低服务之间的耦合度,提高系统的可维护性。
- 提高系统的稳定性:代理层可以处理服务间的异常情况,如服务挂起、超时等,提高系统的稳定性。
- 提高安全性:代理层可以对服务间通信进行安全校验,防止恶意攻击和数据泄露。
常见实现方法
在微服务架构中,网关是至关重要的组件,用于处理服务间的通信和请求路由。目前,市面上有很多微服务代理层解决方案,如Spring Cloud Gateway、Zuul、Kong等。企业可以根据自己的需求和资源选择合适的代理层。
配置代理层时,需要考虑以下因素:
- 路由策略:根据请求的URL、请求头等参数进行路由。
- 负载均衡:根据服务实例的健康状态和性能进行负载均衡。
- 限流策略:防止恶意请求或异常请求对系统造成压力。
- 熔断策略:在服务实例出现问题时,快速熔断,防止级联故障
将代理层与微服务进行集成时,需要确保代理层能够正确处理服务间的通信。这通常需要编写相应的配置文件或代码。
1. Zuul
Zuul是Netflix开源的一款微服务网关,旨在提供动态路由、监控、弹性、安全等功能。它作为服务请求的前门,可以统一管理微服务架构中的所有请求,并实现动态路由、监控、弹性和安全性等功能,比如请求路由、负载均衡、认证授权等功能。
因为从某个时间开始闭源了,所以用的人越来越少,加上性能不如 gateway。
核心功能:
- 动态路由:根据请求的URL或其他属性,动态地路由到对应的微服务实例。
- 监控:监控微服务的健康状况,实现故障转移和流量管理。
- 弹性:根据微服务的负载情况,动态调整请求路由策略。
- 安全:提供认证、授权、限流等功能,保障微服务安全。
工作原理
基于过滤器(Filter)机制。Zuul的核心组件是ZuulFilter,通过编写不同的过滤器,可以实现各种复杂的网关功能。每个请求在通过Zuul时,都会经过一系列的过滤器,这些过滤器可以处理请求、响应等操作。
**Zuul大部分功能都是通过过滤器来实现的。**Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。
- PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- (ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器。
以下是一个简单的Zuul配置示例:
spring:
application:
name: zuul-gateway
server:
port: 8888
zuul:
routes:
service-a:
path: /service-a/**
serviceId: service-a
service-b:
path: /service-b/**
serviceId: service-b
在这个示例中,Zuul将所有以/service-a/
开头的请求路由到service-a
服务,将以/service-b/
开头的请求路由到service-b
服务。
2. Spring Cloud Gateway
Spring Cloud Gateway是基于Spring WebFlux实现的微服务网关,是一个独立的、可扩展的、可配置的 API 网关。提供了对微服务的统一访问入口,更丰富的路由规则和过滤器功能。通过 Gateway,可以统一管理和控制对微服务的访问,包括路由、安全、监控和限流等功能。
与Zuul相比,Spring Cloud Gateway更加灵活,性能更高。
主要功能如下:
- 路由管理:Gateway 根据配置的路由规则,将客户端的请求转发到相应的微服务。它支持动态路由和静态路由,可以根据请求的 URL、参数、头信息等条件进行匹配和转发。
- 安全控制:Gateway 可以对访问微服务的请求进行身份验证、授权和访问控制。通过 OAuth2.0、JWT 等安全协议,可以实现对 API 的安全访问控制。
- 监控和日志:Gateway 可以收集各种监控数据,如请求次数、响应时间、错误率等,并将这些数据发送给监控系统。同时,它还可以记录详细的日志信息,方便问题排查和追踪。
- 限流和熔断:Gateway 可以实现限流和熔断功能,防止因过多的请求导致微服务过载。通过限制请求的速率、并发数等方式,可以保护微服务的稳定性和可靠性。
选择合适的微服务网关 Gateway 需要考虑以下几个因素: - 技术栈匹配:选择与现有技术栈兼容的 Gateway,可以降低集成和开发的难度。
- 扩展性:Gateway 需要具备良好的扩展性,能够根据业务需求进行定制和开发。
- 稳定性:Gateway 需要具备高可用性和稳定性,能够应对高并发和大规模请求。
- 社区支持:选择有活跃社区支持的 Gateway,可以获得更好的技术支持和资源共享。
三大核心概念
**Route(路由)**是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
**Predicate(断言)**参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。
**Filter(过滤)**指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
工作流程
客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求匹配的路由,将其发送到Gateway Web Handler。Handler再通过指定的过滤器链来将请求发送给我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前("pre")或之后("post")执行业务逻辑。
Filter在"pre"类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在"post"类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量控制等有着非常重要的作用。
实现步骤
实现微服务网关 Gateway 的步骤如下:
- 确定需求:明确需要哪些功能和特性,以及如何集成到现有系统中。
- 选择合适的 Gateway:根据需求和技术栈选择合适的 Gateway,并进行评估和测试。
- 配置路由规则:根据业务需求配置路由规则,将请求转发到相应的微服务。
- 集成安全控制:实现身份验证、授权和访问控制等功能,确保 API 的安全性。
- 集成监控和日志:收集监控数据并发送给监控系统,同时记录日志信息。
- 实现限流和熔断:根据需求实现限流和熔断功能,防止请求过多导致微服务过载。
- 测试和部署:进行集成测试、性能测试和安全测试,然后部署到生产环境。
- 维护和升级:定期检查 Gateway 的运行状态和监控数据,根据需要进行维护和升级。
以下是一个简单的Spring Cloud Gateway配置示例:
spring:
application:
name: gateway
server:
port: 8888
spring:
cloud:
gateway:
routes:
- id: service-a
uri: lb://service-a
predicates:
- Path=/service-a/**
- id: service-b
uri: lb://service-b
predicates:
- Path=/service-b/**
在这个示例中,Spring Cloud Gateway同样将所有以/service-a/
开头的请求路由到service-a
服务,将以/service-b/
开头的请求路由到service-b
服务。
七、事件驱动
最后一种模式是事件驱动模式。事件驱动架构是一种通过发布和订阅事件来实现微服务之间通信的方式。这是另一种异步方法,它看起来完全消除了服务之间的耦合。
与消息传递模式不同,事件驱动方法不需要服务必须知道公共消息结构。服务之间的通信通过各个服务产生的事件进行。此处仍然需要消息代理,因为各个服务会将其事件写入其中。但是与消息方法不同,消费服务不需要知道事件的细节,它们对事件的发生做出反应,而不是产生能会或可能不会传递的信息。在形式上,这通常被称为"仅事件驱动的通信"。
工作流程:
- 事件发布者负责产生事件并将其发布到事件总线或消息队列。
- 事件订阅者则从事件总线或消息队列中订阅事件,并在事件发生时进行响应。
- 事件处理器负责处理接收到的事件。在微服务架构中,事件处理器可以是独立的进程或服务。
特点
它具有以下特点:
- 松散耦合:事件驱动提供了一种轻量级、异步的通信方式,使得微服务之间的通信松散耦合,每个微服务只关注自己感兴趣的事件。
- 实时性:事件驱动架构允许实时处理事件,及时响应系统中的变化。
- 可扩展性:通过添加新的订阅者和发布者,事件驱动架构具有较好的可扩展性。
然而,事件驱动架构也有一些需要考虑的因素:
- 事件顺序:事件驱动架构下的事件顺序是不确定的,需要考虑处理事件的顺序和一致性。
- 事件丢失:如果订阅者无法及时处理事件,可能会导致事件丢失的情况发生。
- 复杂性:需要设计合理的事件处理机制和消息传递策略。
- 调试和追踪:由于事件的异步性,调试和追踪事件的流程可能会更加困难。
案例分析
以下是一个基于Apache Kafka的微服务架构事件驱动案例,案例背景是一个电商系统,包含商品管理、订单管理和库存管理等微服务。
事件流:
- 商品新增或修改事件:商品管理服务发布事件,通知其他服务更新商品信息。
- 订单创建事件:订单管理服务发布事件,通知库存管理服务扣减库存。
事件处理:
- 商品管理服务订阅商品新增或修改事件,更新本地商品信息。
- 订单管理服务订阅订单创建事件,扣减库存并创建订单。
Spring Cloud Stream
Spring Cloud Stream 是一个用于构建基于事件驱动的微服务应用程序的框架,其核心目标是简化开发过程,降低消息通信的复杂性,从而使开发人员能够专注于编写业务逻辑。
Spring Cloud Stream 通过提供 Binder 抽象,将应用程序与消息中间件解耦,让开发人员无需关心底层通信细节。同时,它还提供了一套丰富的 API 和特性,如消息分组、分区和错误处理,使得构建强大、可扩展的事件驱动应用程序变得更加简单。
核心组件和特性
(1)Binder
Binder 是 Spring Cloud Stream 的核心组件,它充当应用程序和消息中间件之间的桥梁。通过使用 Binder,开发人员可以轻松地切换不同的消息中间件,而无需修改应用程序代码。
Binder 就像是一座桥,连接了应用程序和用于传递消息的消息中间件(比如 Kafka 或 RabbitMQ)。它使您的应用程序和消息中间件之间保持松散耦合,因此您可以在不修改应用程序代码的情况下轻松地更换消息中间件。
(2)消息通道(Message Channels)
消息通道是用于处理输入和输出数据流的组件。在 Spring Cloud Stream 中,开发人员可以使用@Input
和@Output
注解定义输入和输出消息通道,并使用@EnableBinding
注解将这些通道与应用程序的生产者和消费者绑定。
消息通道类似于一条传送带,负责将消息从一个地方传送到另一个地方。在 Spring Cloud Stream 中,您可以定义输入(接收)和输出(发送)消息通道,然后将这些通道与处理消息的应用程序组件(生产者和消费者)关联起来。
(3)消息转换
Spring Cloud Stream 提供了内置的消息转换功能,支持多种消息格式,如 JSON、Avro 等。这使得开发人员可以轻松地处理和转换不同格式的消息,而无需编写额外的代码。
这个功能就像一个翻译器,负责将一种消息格式转换为另一种消息格式。
(4)
想象一下正在组织一个大型聚会,邀请了来自世界各地的朋友。这个聚会中,Spring Cloud Stream 的三个核心组件可以分别类比为邮递员(Binder)、信箱(消息通道)和翻译员(消息转换)。
-
邮递员(Binder):邮递员负责将邀请函从您(应用程序)发送给您的朋友(消息中间件,如 Kafka 或 RabbitMQ),以及在朋友回复时将回复从朋友传递回给您。邮递员在这个过程中负责管理传递信息的方式和速度。
-
信箱(消息通道):信箱用于临时存放发出的邀请函和收到的回复。当您有邀请函需要发送时,您会将邀请函放入发件箱(输出消息通道);当朋友们的回复逐渐到达时,它们会被放入收件箱(输入消息通道)。信箱在这个过程中负责确保信息有序、安全地进行传递。
-
翻译员(消息转换):由于您的朋友们来自世界各地,他们可能使用不同的语言进行沟通。因此,翻译员负责在发送邀请函时将其翻译成接收方的语言,以及在您收到回复时将回复翻译成您能理解的语言。翻译员在这个过程中确保信息在发送和接收时保持正确的格式和可读性。
支持的消息中间件
Spring Cloud Stream 支持多种流行的消息中间件,包括但不限于:
-
Apache Kafka:一种高度可扩展的、分布式的消息队列,适用于处理大量数据流和实时分析。
-
RabbitMQ:一种广泛使用的、可靠的消息队列,支持多种消息协议,如 AMQP、MQTT 等。
-
Amazon Kinesis:一种用于实时数据流处理的云服务,适用于构建大规模、实时数据处理应用程序。
-
Google Cloud Pub/Sub:一种用于构建实时消息传递应用程序的全球性、高度可用的云服务。
通过支持这些消息中间件,Spring Cloud Stream 为开发人员提供了丰富的选择,使他们可以根据项目需求和场景选择最合适的消息中间件。此外,由于 Spring Cloud Stream 的可扩展性,开发人员还可以轻松地集成其他自定义消息中间件。
适用场景
- 物联网 (IoT) :大量传感器和设备通过事件驱动架构进行数据采集和处理。
- 金融领域:实现实时的交易处理和事件监控。
- 微服务架构:通过事件的发布和订阅,实现各个服务之间的解耦和协同工作。
八、几种调用方式的区别与联系
RESTful API与消息队列
Zuul和Gateway
Zuul和Gateway是微服务架构中常用的两种网关,它们在功能和使用上有一些显著的区别。
(1)API设计
Zuul使用的是阻塞式的API,不支持长连接,如websockets。底层使用的是servlet,处理的是HTTP请求,没有提供异步支持。流控等功能由Hystrix提供支持。
相比之下,Gateway不仅支持阻塞式API,还支持异步和非阻塞的API。这意味着Gateway可以更好地处理高并发请求,提高系统的吞吐量。
通俗来说,Zuul 相当于同步会阻塞的 servlet,请求到网关以后,Zuul 会自己维护一个线程池,从线程池拿出一个线程来处理这个请求,接着这个请求会发到某一个服务中去,接着这个服务各种处理最后响应到 Zuul,Zuul 再把数据返回给浏览器。从头到尾用的都是一个子线程,子线程处理完以后最后会被释放。这个是 Zuul 的特点,处理并发能力很弱;如果线程池只有 100 个线程,那么就只能处理 100 个请求。
gateway 就不一样,类似于异步 servlet,虽然请求到了 gateway 以后,也是会从线程池分配一个线程处理请求,但不是直接用线程处理,而是先用线程收到请求,接着这个线程立马 new 一个子线程,由这个子线程去做后面的事情。接着原本的那个线程立马会被释放,就不需要去等。
(2)异步支持
Zuul仅支持同步请求,而Gateway支持异步请求。在处理大量请求或需要高并发的场景下,Gateway的异步特性可以显著提高系统的响应性能。
(3)扩展性
从框架设计的角度来看,Gateway具有更好的扩展性。它已经发布了2.0.0的稳定版本,并得到了广泛应用。此外,由于Gateway使用了非阻塞的API,因此更容易与其他技术栈集成。
(4)性能
Zuul 1.x是基于阻塞IO的API网关。虽然Zuul已经发布了2.x版本,基于Netty实现非阻塞IO和支持长连接,但Spring Cloud暂时还没有整合计划。因此,在性能方面,Zuul可能无法充分利用非阻塞IO的优势。
而Gateway由于其异步和非阻塞的特性,理论上更适合提高系统吞吐量。然而,请注意,高并发并不一定意味着高性能。最终性能还需要通过严密的压测来决定。
(5)社区支持与生态系统
Zuul是Netflix开源的项目,已经在许多大型生产环境中得到广泛应用。然而,Spring Cloud Gateway作为Spring Cloud生态的一部分,也拥有强大的社区支持和丰富的生态系统。
(6)使用场景
如果您的微服务架构已经使用了Spring Cloud生态的基础组件,那么Spring Cloud Gateway可能更加具备优势。特别是从流式编程和异步支持的角度来看,Gateway是更好的选择。
在选择微服务通信方式时,开发人员需要根据实际需求权衡不同的因素。如果需要直接方法调用和较高的性能,RPC可能是一个不错的选择。如果希望实现松耦合和异步通信,消息队列可以提供可靠的解决方案。而事件驱动架构适用于实时性要求较高、系统需要高度扩展性和灵活性的场景。综合考虑项目需求和技术要求,选择适合的微服务通信方式能够提升系统的可靠性和可扩展性。