异步处理和消息队列简介
介绍
在客户端-服务器体系结构中,客户端可以通过相互发送消息来请求服务器完成作业。
当您开始管理消息发送的速率、服务器可以处理的请求数量或客户端要求的响应时间时,处理这种通信的复杂性会增加。
在这篇博客中,我们将看到一种处理这种复杂问题的方法。
什么是同步处理?
在同步处理中,客户端向服务器发送请求,并等待服务器完成其工作并发回响应,然后客户端才能继续执行任何其他工作。
该过程通常被称为阻塞请求,因为客户端在收到响应之前无法执行任何其他工作。
什么是异步处理?
异步处理与同步处理完全相反。客户端向服务器发送请求后不会等待响应,而是继续执行其他工作。
此过程称为非阻塞请求,因为客户端的执行线程不会被阻塞。这使得系统能够扩展,在给定的时间内完成更多工作。
同步与异步处理
-
同步请求会阻塞客户端的执行线程,迫使它们等待响应才能执行其他操作。另一方面,异步请求不会阻塞,并允许在给定时间内完成更多工作。
-
由于我们不知道请求需要多少时间,因此很难使用同步处理来构建响应式应用程序。阻塞操作越多,系统就越慢。使用异步处理,响应时间会很快,因为客户端无需等待请求。
-
异步处理的容错性比同步处理高,当请求失败时,很容易建立重试机制。
什么是消息队列?
消息队列是一个缓冲来自一个服务的请求并异步广播到另一个服务的组件。
在这里,客户端是消息生产者,它们向队列(而不是任何服务器)发送请求消息。当消息添加到队列时,它们会收到确认,这使得它们能够继续执行其他任务,而无需等待服务器。
服务器被称为消息消费者,根据其在特定时间内能够处理的请求数量,从队列中接收消息。此过程持续进行,直到队列中的所有消息都已处理完毕。
消息队列的结构
消息队列主要是消息生产者和消息消费者之间的消息代理。
消息队列设置(生产者、消费者和队列)中的每个不同实体都有责任,并且它们尽可能地彼此分离。
所有实体之间的唯一契约是消息队列促进消息从生产者到消费者的移动。
在接下来的章节中,我们将讨论每个组件的职责,并研究消息队列向消费者传递消息的各种模式。
消息生产者
消息生产者发起异步处理请求。生产者负责生成有效消息并将其发布到消息队列。提交到队列的消息随后会被排队,并被传递给消费者进行异步处理。
生产者使用高级消息队列协议 (AMQP) 与消息队列进行通信。
消息代理
消息代理其实就是一个队列。你甚至可以用编程的方式实现一个简单的代理,用来缓存消息,并在需要时发送给消费者。
消息代理是设置中的实际解耦元素,位于生产者和消费者之间并管理他们的通信过程。
由于其简单性,代理针对高并发性和吞吐量进行了优化。
需要注意的是,添加消息代理会给你的基础架构带来额外的复杂性,并且需要你对其进行扩展。在可扩展性方面,代理也有特定的要求和限制。
消息消费者
消费者的主要职责是从队列中接收和处理消息。
大多数消费者都是执行实际异步处理的 API 服务。
消费者可以用不同的应用语言或技术来实现,并且独立于其他组件进行维护。
为了实现解耦,消费者不应该对生产者一无所知。两者之间唯一的契约就是来自队列的有效消息。
当正确解耦时,消费者可以作为独立的服务层,可供消息队列设置和基础设施中的其他组件使用。
消费者沟通策略
消息队列需要将消息向下传递到消费者,根据应用程序开发者如何实现消费者,消息队列有三种不同的方式向消费者传递消息:
- 拉动模型
在这个模型中,消费者会定期检查队列的状态。这是按照消费者端设定的时间间隔进行的。
如果队列中有消息,消费者会继续接收这些消息,直到没有剩余消息需要处理,或者已消费了“N”条消息。“N”可以在消息代理上配置。
- 推模型
一旦添加消息,消费者就会收到通知,然后消息就会被推送给消费者。消息推送的速度是消费者可以轻松控制的。
- 订阅模式
在此模型中,消费者可以订阅主题。发布者将消息发布到主题而不是队列。连接到代理的每个消费者都维护其私有队列,用于接收来自主题的消息。
在消费者订阅主题后,当有消息发布到该主题时,该消息会被克隆到每个订阅者并添加到消费者的私有队列中。
比较不同的消息代理
正如我们上面看到的,对于异步通信,我们通常需要一个消息代理。
以下是选择代理来管理异步操作时需要考虑的几个因素:
- 规模:系统每秒发送的消息数量
- 数据持久性:恢复消息的能力
- 消费者能力:管理一对一/一对多消费者的能力
RabbitMQ
- 规模:基于配置和资源。
- 持久性:支持持久消息和瞬态消息。
- 一对一与一对多消费者:两者皆是。
RabbitMQ 支持所有主流语言,包括 Python、Java、.NET、PHP、Ruby、JavaScript、Go、Swift 等。
卡夫卡
- 规模:每秒最多可发送一百万条消息。
- 坚持:是的。
- 一对一 vs 一对多消费者:仅一对多
Kafka 已在 Azure 和 AWS 上管理 SaaS。Kafka 还支持所有主流语言,包括 Python、Java、C/C++、Clojure、.NET、PHP、Ruby、JavaScript、Go、Swift 等。
Redis
- 规模:每秒最多可发送一百万条消息。
- 持久性:不支持(它是一个内存数据库)。
- 一对一与一对多消费者:两者皆是。
Redis 与其他消息代理略有不同。Redis 是一个内存数据存储。最初,Redis 仅支持与消费者进行一对一通信。但是,自从 Redis 5.0 引入了发布-订阅模式后,您可以添加一对多通信选项。
结论
在这篇博客中,我们介绍了异步处理相对于其他处理方式的优势,以及消息队列如何帮助我们实现异步处理,同时保持其设置中的不同实体彼此分离。
我们还介绍了最常用的消息代理的一些基本特征:Redis、Kafka 和 RabbitMQ。
以下是根据不同用例选择合适的消息代理的更详细说明:
短期消息:Redis
- Redis 适用于不需要持久性的短期消息。
大量数据:Kafka
- Kafka 非常适合长期存储大量数据。对于需要持久性的一对多用例,Kafka 也非常理想。
复杂路由:RabbitMQ
- RabbitMQ 适合复杂的路由通信。
祝你编码愉快!💻
(如果您发现任何疑问、更新或更正以改进本文,请随时在评论中分享)😊
刚开始从事 Web 开发?💻
查看 ▶ HTML 到 React:终极指南
这本电子书是一本全面的指南,通过大量易于理解的示例和经过验证的路线图,教你成为一名 Web 开发人员所需的一切知识
它包含👇
✅ 直截了当的解释
✅ 简单的代码示例
✅ 50+ 有趣的项目创意
✅ 3 个秘密资源清单
✅ 额外面试准备
您甚至可以查看本书的免费样本
这是全套书原价 60% 的链接⬇
文章来源:https://dev.to/apoorvtyagi/introduction-to-asynchronous-processing-and-message-queues-27od