一个事件驱动架构的例子
使用 RabbitMQ 构建事件驱动架构(使用 Node.js)在 Node.js 中
《介绍》在现代软件系统中,基于事件的架构 是可扩展性、灵活性和弹性的核心。这种架构允许服务异步地进行通讯,让它们解耦并实现独立扩展性。然而,实现这样的系统并非易事。开发人员会遇到诸如:
- 确保消息送达成功。
- 处理重试和死信。
- 防止重复处理。
- 解耦服务的同时保持可靠的通信。
本文介绍了@nodesandbox/event-bus
包,这是一个使用RabbitMQ实现的事件驱动系统自定义库,完全用纯Node.js编写。我们还将通过一个实际的例子来向您展示:一个电子商务系统,其中包括订单、库存、支付和通知等服务模块。
(Note: There seems to be a typo in the prompt, "pelase" is unintended. The correct translation should simply be:)
为何选择事件驱动架构?为什么它会是个好选择?事件驱动架构支持:
- 解耦:服务之间不需要了解彼此。它们通过发布和订阅事件来减少相互依赖。
- 可扩展性:每个服务都可以根据其自身的工作负载来独立扩展。
- 弹性:一个服务的故障不会扩散到其他服务。事件可以被重试或缓存起来以备后续处理。
RabbitMQ,一个强大且广泛使用的消息代理,非常适合用来构建这样的系统。它提供了可靠的消息传递,灵活的路由功能,以及丰富的监控和调试工具。
提供一个RabbitMQ事件总线包当使用像NestJS这样的框架时,开发人员可以利用内置的消息驱动微服务工具。不过,对于使用纯Node.js的开发人员来说,选择较少,他们不得不自己构建解决方案,或者使用如amqplib
这样的底层库之类的工具。
@nodesandbox/event-bus
这个包是为了在 Node.js 应用中实现事件驱动的通信而被创建的,提供了一个轻量级且灵活的库。
- 专为纯 Node.js 设计:适合偏爱独立 Node.js 应用而非框架的开发者。
- 由 RabbitMQ 驱动:当前,该包专注于使用 RabbitMQ 作为消息代理,利用其可靠性和功能。
- 高级功能:
- 死信队列 (DLQs):用于未处理的消息。
- 重试:具有可配置延迟,用于暂时性故障。
- 幂等性处理:防止重复操作。
- 动态配置:包括持久性、路由等配置。
该包正不断更新,以包含以下内容。
提供对更多经纪商的支持:
- 添加对常见消息队列如 Kafka ,Redis Streams 等的支持。
- 提升开发者控制权
- 可定制的消息存储(例如,内存存储、Redis和数据库)。
-
高级的重试和监控设置。
一个不断壮大的生态系统
简洁和可扩展的设计使其轻松融入任何 Node.js 项目。
电商项目示例:电子商务系统
为了展示这个包的强大功能,我们构建了一个包含以下微服务组件的电商系统示例:
- 订单服务:处理订单的创建和更新订单。
- 库存服务:管理库存的可用性和预留库存。
- 支付服务:处理支付并通知支付的状态。
- 通知服务:根据事件发送通知信息。
各个服务通过RabbitMQ异步地进行通信,确保服务之间的解耦和容错能力。
架构概览以下是我们的一个示例系统的架构如下:
+---------------+ +-----------------+ +------------------+ +-------------------+
| 订单服务 | --> | 存货服务 | --> | 支付 | --> | 通知 |
+---------------+ +-----------------+ +------------------+ +-------------------+
每个服务都会发布及消费与其所在领域相关的事件。例如:
- 订单服务 创建订单并发布
order.created
。 - 库存服务 检查库存情况并发布
stock.reserved
。 - 支付服务 处理支付并通知支付结果。
- 通知服务 监听所有事件并发送通知。
本地运行 RabbitMQ 或者通过 Docker 启动它。
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:management
运行一个持续的RabbitMQ容器,映射端口到主机,方便管理和调试。请在终端或命令行中执行此命令。
访问 RabbitMQ 管理 UI,http://localhost:15672/。
用户名: guest
,密码: guest
。
在您的 Node.js 应用程序中安装该包:
npm install @nodesandbox/event-bus
这行命令是用来安装一个名为@nodesandbox/event-bus的npm模块,它可以帮助管理应用中的事件。
第三步:实施订单服务订单服务系统会发送关于创建订单和检查库存数量的事件通知:
import { RabbitMQEventBus, EventFactory } from '@nodesandbox/event-bus';
import express from 'express';
import { v4 as uuid } from 'uuid';
const app = express();
const eventBus = new RabbitMQEventBus({
connection: { url: 'amqp://localhost:5672' },
producer: { persistent: true },
});
app.post('/orders', async (req, res) => {
const orderId = uuid();
const event = EventFactory.create('order.created', { orderId });
await eventBus.publish(event);
res.status(201).json({ orderId });
});
await eventBus.init();
app.listen(3001, () => console.log('订单服务正在端口3001运行'));
步骤 4:实施库存管理服务
库存服务订阅如 stock.check
之类的事件并据此更新库存状态:
await eventBus.subscribe(['stock.check'], async (event) => {
const { 订单ID: orderId, 商品列表: items } = event.data;
const 所有可用 = items.every(item => 检查库存(item.产品ID, item.数量));
if (所有可用) {
const 库存已预留事件 = EventFactory.create('stock.reserved', { 订单ID: orderId });
await eventBus.publish(库存已预留事件);
} else {
const 库存不足事件 = EventFactory.create('stock.unavailable', { 订单ID: orderId });
await eventBus.publish(库存不足事件);
}
});
// 订阅 stock.check 事件
第5步:启动系统
在不同的终端中打开每个服务:
切换到订单服务并启动它: cd order-service && npm start 运行
切换到库存服务并启动它: cd inventory-service && npm start 启动
切换到支付服务并启动它: cd payment-service && npm start 启动
切换到通知服务并启动它: cd notification-service && npm start 启动
通过 Postman 或柯尔创建订单:
curl -X POST http://localhost:3001/orders \
-H "Content-Type: application/json" \
-d '{ "userId": "user123", "items": [{ "productId": "PROD1", "quantity": 2 }] }'
# 发送POST请求到订单服务
高级选项:
- 死信队列(DLQ):捕获未处理的消息以便调试。
await eventBus.订阅(['events.dlx'], async (event) => { console.warn('死信消息:', event); });
共同学习,写下你的评论
评论加载中...
作者其他优质文章