返回

本地使用 Docker Compose 与 Nestjs 快速构建基于 Dapr 的 Redis 发布/订阅分布式应用

后端

介绍

Dapr 是一个可移植的、事件驱动的运行时,它使任何开发人员能够轻松构建出弹性的、无状态和有状态的应用程序,并可运行在云平台或边缘计算中,它同时也支持多种编程语言。

Redis 是一个开源的、支持多种数据结构的内存数据库,经常用作缓存和消息代理。

Nestjs 是一个渐进式的 Node.js 框架,旨在帮助开发人员轻松构建可扩展和可维护的服务器端应用程序。

先决条件

  • Node.js v12+
  • Docker
  • Docker Compose

项目设置

首先,创建一个新的文件夹,并将该文件夹用作您的项目目录。

mkdir dapr-redis-pubsub
cd dapr-redis-pubsub

接下来,初始化一个新的 Nestjs 项目。

nest new my-app

这将创建一个名为 my-app 的新 Nestjs 项目。

安装依赖项

现在,让我们安装 Dapr 和 Nestjs 的依赖项。

npm install --save dapr-client nestjs

创建服务

现在,让我们创建发布者服务和订阅者服务。

发布者服务

my-app/src/publisher 目录下创建一个新的文件夹,并创建一个名为 publisher.controller.ts 的文件。

mkdir -p my-app/src/publisher
touch my-app/src/publisher/publisher.controller.ts

然后,将以下代码添加到 publisher.controller.ts 文件中:

import { Controller, Post, Body } from '@nestjs/common';
import { Client, Message } from 'dapr-client';

@Controller('publisher')
export class PublisherController {
  private readonly client: Client;

  constructor() {
    this.client = new Client();
  }

  @Post('publish')
  async publish(@Body() body: any) {
    const data = JSON.stringify(body);
    const message: Message = {
      topic: 'my-topic',
      data: data,
    };
    await this.client.publish(message);
    return {
      message: 'Message published successfully',
    };
  }
}

订阅者服务

my-app/src/subscriber 目录下创建一个新的文件夹,并创建一个名为 subscriber.controller.ts 的文件。

mkdir -p my-app/src/subscriber
touch my-app/src/subscriber/subscriber.controller.ts

然后,将以下代码添加到 subscriber.controller.ts 文件中:

import { Controller, Post, Body } from '@nestjs/common';
import { Client, Subscription } from 'dapr-client';

@Controller('subscriber')
export class SubscriberController {
  private readonly client: Client;
  private readonly subscription: Subscription;

  constructor() {
    this.client = new Client();
    this.subscription = this.client.subscribe({
      pubsubName: 'pubsub',
      topic: 'my-topic',
      route: 'my-subscription',
    });
  }

  @Post('subscribe')
  async subscribe(@Body() body: any) {
    await this.subscription.onReceive((message) => {
      const data = JSON.parse(message.data);
      console.log(`Received message: ${data.message}`);
    });
    return {
      message: 'Subscription created successfully',
    };
  }
}

运行应用程序

现在,我们可以使用 Docker Compose 来运行应用程序。

首先,在项目的根目录下创建一个名为 docker-compose.yml 的文件。

touch docker-compose.yml

然后,将以下代码添加到 docker-compose.yml 文件中:

version: '3.7'

services:
  publisher:
    build: ./my-app/src/publisher
    ports:
      - "3000:3000"
    environment:
      DAPR_APP_ID: publisher
      DAPR_HTTP_PORT: 3500
      DAPR_GRPC_PORT: 50001
  subscriber:
    build: ./my-app/src/subscriber
    ports:
      - "3001:3001"
    environment:
      DAPR_APP_ID: subscriber
      DAPR_HTTP_PORT: 3501
      DAPR_GRPC_PORT: 50002
  dapr:
    image: "dapr/dapr:v1.10.2"
    ports:
      - "3500:3500"
      - "9000:9000"
      - "50001:50001"
      - "50002:50002"

现在,我们可以使用以下命令启动应用程序:

docker-compose up

这将启动 Dapr sidecar 容器和发布者和订阅者服务。

测试应用程序

现在,我们可以使用 HTTPie 来测试应用程序。

首先,让我们发布一条消息:

http POST http://localhost:3000/publisher/publish message="Hello, world!"

然后,让我们订阅这条消息:

http POST http://localhost:3001/subscriber/subscribe

现在,当我们再次发布一条消息时,订阅者服务将接收并打印这条消息:

http POST http://localhost:3000/publisher/publish message="Hello, Dapr!"

结论

在本教程中,我们学习了如何使用 Dapr (分布式应用程序运行时) 和 Nestjs 在本地使用 Docker Compose 快速构建一个基于 Redis 的发布/订阅分布式应用程序。我们使用 Nestjs 作为应用程序的框架,并使用 Dapr 来处理应用程序之间的通信。该应用程序包含一个发布者服务和一个订阅者服务,发布者服务将发布消息到 Redis,订阅者服务将订阅这些消息并处理它们。我们使用 Docker Compose 来本地运行这两个服务。