为了账号安全,请及时绑定邮箱和手机立即绑定

使用RabbitMQ构建可靠的事件驱动架构:Node.js环境下的实战教程

标签:
MongoDB Node.js

一个事件驱动架构的例子

使用 RabbitMQ 构建事件驱动架构(使用 Node.js)

在 Node.js 中

《介绍》

在现代软件系统中,基于事件的架构 是可扩展性、灵活性和弹性的核心。这种架构允许服务异步地进行通讯,让它们解耦并实现独立扩展性。然而,实现这样的系统并非易事。开发人员会遇到诸如:

  • 确保消息送达成功
  • 处理重试死信
  • 防止重复处理
  • 解耦服务的同时保持可靠的通信

本文介绍了@nodesandbox/event-bus包,这是一个使用RabbitMQ实现的事件驱动系统自定义库,完全用纯Node.js编写。我们还将通过一个实际的例子来向您展示:一个电子商务系统,其中包括订单、库存、支付和通知等服务模块。

_pelase_为何选择事件驱动架构?什么是事件驱动架构?为什么它会是个好选择?

(Note: There seems to be a typo in the prompt, "pelase" is unintended. The correct translation should simply be:)

为何选择事件驱动架构?为什么它会是个好选择?

事件驱动架构支持:

  1. 解耦:服务之间不需要了解彼此。它们通过发布和订阅事件来减少相互依赖。
  2. 可扩展性:每个服务都可以根据其自身的工作负载来独立扩展。
  3. 弹性:一个服务的故障不会扩散到其他服务。事件可以被重试或缓存起来以备后续处理。

RabbitMQ,一个强大且广泛使用的消息代理,非常适合用来构建这样的系统。它提供了可靠的消息传递灵活的路由功能,以及丰富的监控和调试工具。

提供一个RabbitMQ事件总线包

当使用像NestJS这样的框架时,开发人员可以利用内置的消息驱动微服务工具。不过,对于使用纯Node.js的开发人员来说,选择较少,他们不得不自己构建解决方案,或者使用如amqplib这样的底层库之类的工具。

@nodesandbox/event-bus 这个包是为了在 Node.js 应用中实现事件驱动的通信而被创建的,提供了一个轻量级且灵活的库。

主要特点
  • 专为纯 Node.js 设计:适合偏爱独立 Node.js 应用而非框架的开发者。
  • 由 RabbitMQ 驱动:当前,该包专注于使用 RabbitMQ 作为消息代理,利用其可靠性和功能。
  • 高级功能
  • 死信队列 (DLQs):用于未处理的消息。
  • 重试:具有可配置延迟,用于暂时性故障。
  • 幂等性处理:防止重复操作。
  • 动态配置:包括持久性、路由等配置。
一个正在进行的项目:下一步会是啥?

该包正不断更新,以包含以下内容。

提供对更多经纪商的支持:

  • 添加对常见消息队列如 KafkaRedis Streams 等的支持。
  1. 提升开发者控制权
  • 可定制的消息存储(例如,内存存储、Redis和数据库)。
  • 高级的重试和监控设置。

    一个不断壮大的生态系统

    简洁和可扩展的设计使其轻松融入任何 Node.js 项目。

电商项目示例:电子商务系统

为了展示这个包的强大功能,我们构建了一个包含以下微服务组件的电商系统示例:

  1. 订单服务:处理订单的创建和更新订单。
  2. 库存服务:管理库存的可用性和预留库存。
  3. 支付服务:处理支付并通知支付的状态。
  4. 通知服务:根据事件发送通知信息。

各个服务通过RabbitMQ异步地进行通信,确保服务之间的解耦和容错能力。

架构概览

以下是我们的一个示例系统的架构如下:

    +---------------+      +-----------------+      +------------------+      +-------------------+  
    |   订单服务     | --> |   存货服务     | --> |   支付           | --> |   通知           |  
    +---------------+      +-----------------+      +------------------+      +-------------------+

每个服务都会发布及消费与其所在领域相关的事件。例如:

  • 订单服务 创建订单并发布 order.created
  • 库存服务 检查库存情况并发布 stock.reserved
  • 支付服务 处理支付并通知支付结果。
  • 通知服务 监听所有事件并发送通知。
动手做:构建事件驱动系统
第一步:配置 RabbitMQ

本地运行 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请求到订单服务
高级选项:
  1. 死信队列(DLQ):捕获未处理的消息以便调试。
  • await eventBus.订阅(['events.dlx'], async (event) => { console.warn('死信消息:', event); });
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消