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

网友投稿 807 2022-10-11

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

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

Dapr(分布式应用程序运行时)介绍

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

Dapr 官网:​​Dapr 的 Redis 发布/订阅应用

1. 创建项目

首先,我们将创建我们的项目根文件夹来托管我们将在后续步骤中创建的所有服务。

mkdir dapr-nestjs-redis-pub-sub

2. 创建 Dapr Placement 服务

由于我们将创建多个服务,我们将使用 ​​docker-compose​​ 来运行这些服务。

让我们在项目的根文件夹中创建 ​​docker-compose.yml​​ 文件

cd dapr-nestjs-redis-pub-subtouch docker-compose.yml

version: "3.5"services: dapr-placement: image: "daprio/dapr" command: ["./placement", "-port", "50006"]

​​Dapr placement​​​ 服务将负责管理 ​​Dapr actors​​(我们的服务)之间的所有通信。

简单来说,它负责将所有通信路由到假设接收通信的相应 ​​actor​​​。它充当 ​​message broker​​(消息代理)。

3. 创建 Redis Publish 服务

将以下代码添加到 ​​docker-compose.yml​​ 的服务部分:

redis-publisher: image: redis restart: always depends_on: - dapr-placement

4. 创建 Dapr Pub-Sub 组件

创建一个 ​​dapr/components​​​ 文件夹。然后创建组件文件 ​​redis-pubsub.yaml​​。

mkdir -p dapr/componentscd dapr/componentstouch redis-pubsub.yaml

然后打开文件并插入我们的 ​​Dapr pub/sub​​ 组件的详细信息

apiVersion: dapr.io/v1alpha1kind: Componentmetadata: name: redis-pubsub namespace: defaultspec: type: pubsub.redis version: v1 metadata: - name: redisHost value: redis-publisher:6379 - name: redisPassword value: ""

​​redisHost​​​ 是我们的 ​​Redis​​​ 服务 ​​redis-pub​​​ 的名称,默认 ​​Redis​​​ 端口为 ​​6379​​。

5. 创建 Redis Dapr Sidecar

正如前面部分反复提到的,服务直接与 ​​Dapr​​​ 通信,而不是直接与其他服务通信。​​Dapr​​ 充当所有服务的中间人。

服务通过它们自己的 ​​Dapr sidecar​​​ 直接与 ​​Dapr​​​ 通信,​​Dapr sidecar​​​ 将通信传递给 ​​Dapr placement​​​,该 ​​placement​​​ 再次将其传递给假设接收通信的服务的 ​​Dapr sidecar​​。

将 ​​redis-dapr-sidecar​​​ 服务添加到我们的 ​​docker-compose.yml​​

redis-dapr-sidecar: image: "daprio/daprd:edge" command: [ "./daprd", "-app-id", "redis-publisher", "-app-port", "6379", "-dapr- "5000", "-components-path", "/components", "-placement-host-address", "dapr-placement:50006" ] volumes: - "./dapr/components/:/components" depends_on: - redis-publisher network_mode: "service:redis-publisher"

在这里,我们使用 ​​app-id​​​ 将 ​​Dapr sidecar​​​ 分配给 ​​redis-publisher​​​,同时我们使用 ​​redis​​​ 端口 ​​6379​​。

我们还必须将 ​​dapr/components(redis-pubsub.yaml)​​​ 文件夹挂载到 ​​docker​​ 容器中。

定义您的 ​​dapr-很重要,因为您将在此处调用各种 ​​HTTP 调用/方法/请求​​。

最后,注意将 ​​redis-dapr-sidecar​​​ 附加到 ​​redis-publisher​​ 网络命名空间。

6. 创建 NestJS Server

我们将使用 ​​NestJS​​​ 作为我们的 ​​node server​​​ 作为我们的 ​​Redis subscriber(订阅者)​​。

进入到项目文件夹

cd dapr-nestjs-redis-pub-sub

然后执行以下命令设置一个 ​​NestJS node server​​:

npm i -g @nestjs/clinest new nest-subscriber

对于这个项目,我们将选择 ​​yarn​​ 作为包管理器。

接下来,我们将设置一个 ​​post API​​​ 端点。​​​Dapr​​​ 将调用这个端点,一旦它收到我们的 ​​Redis​​ 服务发布,它就被调用。

转到 ​​nest-subscriber/src/app.controller.ts​​

将此文件中的代码替换为以下内容:

import { Controller, Post, Body } from '@nestjs/common';import { AppService } from './app.service';@Controller()export class AppController { constructor(private readonly appService: AppService) {} @Post('/redis-publisher') async postRedisPub(@Body() reqBody) { console.log(`Redis 发布了 ${JSON.stringify(reqBody)} `); return `NestJS 订阅者收到的 ${reqBody} 发布`; }}

7. 为 NestJS 订阅服务器创建 Dockerfile

我们将 ​​NestJS​​​ 服务器作为 ​​Docker​​​ 容器运行。需要创建一个 ​​Dockerfile​​。

cd nest-subscribertouch Dockerfile

然后打开文件并粘贴以下代码:

FROM node:16.13.0-alpineWORKDIR "/app"COPY ./nest-subscriber/package.json ./RUN yarn installCOPY ./nest-subscriber .RUN yarn run buildEXPOSE 3000CMD ["yarn","start:prod"]

构建镜像:

docker build -f ./nest-subscriber/Dockerfile -t nest-subscriber:latest . --no-cache

8. 将 NestJS 订阅服务添加到 docker-compose 文件

在创建了我们的 ​​NestJS​​​ 服务器和 ​​Dockerfile​​​ 之后,我们创建了 ​​nest-subscriber​​​ ​​docker​​ 服务。

将以下内容添加到 ​​docker-compose.yml​​:

nest-subscriber: image: "nest-subscriber:latest" depends_on: - redis-publisher - dapr-placement restart: always

9. 创建 Dapr 订阅

我们将为我们的 ​​pub/sub​​ 订阅定义配置。

创建一个 ​​dapr/subscriptions​​​ 文件夹。然后创建组件文件 ​​redis-subscription.yaml​​

mkdir -p dapr/subscriptionscd dapr/subscriptionstouch redis-subscription.yaml

然后打开文件并插入我们的 ​​Dapr​​ 订阅组件的详细信息

apiVersion: dapr.io/v1alpha1kind: Subscriptionmetadata: name: nest-redis-subspec: topic: nest-redis-pub-topic route: /redis-publisher pubsubname: redis-pubsubscopes: - nest-subscriber

路由是发布 ​​topic​​​ 时 ​​Dapr​​​ 将调用的 ​​API​​

​​scope​​​ 是订阅该 ​​topic​​ 的服务。

​​pubsubname​​ 是 redis-pubsub,它等于我们的 ​​redis-pubsub.yaml​​ 文件中定义的元数据名称。

在这个项目中,如果发布了一个 topic ​​nest-redis-pub-topic​​​,Dapr 将在我们的 ​​nest-subscriber​​​ 服务中调用 API ​​/redis-publisher​​。

10. 创建 NestJS 服务器 Dapr Sidecar

我们需要为我们的 ​​NestJS​​​ 服务创建一个 ​​sidecar​​​,就像 ​​redis-publisher​​ 服务一样。

将 ​​nest-subscriber-dapr-sidecar​​​ 服务添加到我们的 ​​docker-compose.yml​​

nest-subscriber-dapr-sidecar: image: "daprio/daprd:edge" command: [ "./daprd", "-app-id", "nest-subscriber", "-app-port", "3000", "-components-path", "/components", "-placement-host-address", "dapr-placement:50006", ] volumes: - "./dapr/components/:/components" depends_on: - nest-subscriber network_mode: "service:nest-subscriber"

11. 测试它是否有效

通常 ​​Dapr Docker​​​ 容器会在 ​​Docker​​ 网络中进行通信。

但是为了我们做测试,我们将打开映射暴露端口 ​​5000​​​ 到我们的本地机器 ​​5001​​。

redis-publisher: image: redis depends_on: - dapr-placement restart: always ports: - 5001:5000

然后在您的终端中执行以下命令:

curl --location --request POST '\--header 'Content-Type: application/json' \--data-raw '{ "hello": "world"}'

​​Dapr​​​ 的优点之一是它遵循特定的 ​​URL​​​ 格式。这里我们只使用 ​​Dapr sidecar HTTP​​​ 端口(​​5001​​​),然后是版本号(​​v1.0​​​),然后是 ​​action(publish)​​​。然后是我们 ​​redis-pubsub.yaml​​​ 配置文件中定义的 ​​pubsubname​​​(​​redis-pubsub​​​)和 ​​topic​​​(​​nest-redis-pub-topic​​)。

一旦发出 ​​HTTP post​​​ 请求。我们的 ​​NestJS​​​ 服务器应该在 ​​/redis-publisher​​​ 收到一个 ​​post​​ 请求,这将导致以下日志:

我们可以看到它正在通过 ​​Dapr​​​ 接收 ​​Redis​​​ 发布。但是我们的 ​​NestJS​​ 服务器无法正确处理消息。

只有 ​​{}​​ 被发布,而不是我们发布的消息。

我们将在下一步中解决这个问题。

注意:我们通过 ​​redis-dapr-sidecar​​​ 的 ​​dapr-调用发布服务。通常会有一个单独的 ​​Docker​​​ 服务(例如另一个服务器),它有自己的 ​​Dapr sidecar​​​,它将调用 ​​redis​​​ 发布服务。 在这种情况下,我们将使用该 ​​Docker​​​ 服务的 ​​Dapr sidecar ​​sidecar​​​ 发送到 ​​Dapr placement​​​ 服务,然后该服务将确定将请求转发到的正确 ​​Dapr sidecar​​。

12. 允许 NestJS 解析 application/cloudevents+json

我们的 ​​nest-subscriber-dapr-sidecar​​​ 向我们的 ​​nest-subscriber​​​ 服务器发出的 ​​post​​​ 请求的 ​​Content-Type​​ 将是 application/cloudevents+json 而不是 ​​application/json​​

目前我们的 ​​NestJS​​​ 服务器无法解析 ​​application/cloudevents+json​​。

为了解决这个问题,我们首先需要安装 ​​body-parser​​:

cd nest-subscriberyarn add body-parser

接下来我们需要修改我们的 ​​NestJS​​​ 服务器 ​​main.ts​​:

import { NestFactory } from '@nestjs/core';import { AppModule } from './app.module';import * as bodyParser from 'body-parser';async function bootstrap() { const app = await NestFactory.create(AppModule); app.use(bodyParser.json({ type: 'application/cloudevents+json' })); app.use(bodyParser.json()); await app.listen(3000);}bootstrap();

当我们再次发送 ​​post​​​ 请求时,我们的 ​​NestJS​​ 服务器将能够处理请求正文并显示以下日志:

好了,我们现在有一个基于 ​​Dapr​​​ 工作的 ​​Redis Pub/Sub​​ 分布式应用。

13. 完整 docker-compose.yaml

version: "3.5"services: dapr-placement: image: "daprio/dapr" command: ["./placement", "-port", "50006"] redis-publisher: image: redis depends_on: - dapr-placement restart: always ports: - 5001:5000 redis-dapr-sidecar: image: "daprio/daprd:edge" command: [ "./daprd", "-app-id", "redis-publisher", "-app-port", "6379", "-dapr- "5000", "-components-path", "/components", "-placement-host-address", "dapr-placement:50006" ] volumes: - "./dapr/components/:/components" depends_on: - redis-publisher network_mode: "service:redis-publisher" nest-subscriber: image: "nest-subscriber:latest" depends_on: - redis-publisher - dapr-placement restart: always nest-subscriber-dapr-sidecar: image: "daprio/daprd:edge" command: [ "./daprd", "-app-id", "nest-subscriber", "-app-port", "3000", "-components-path", "/components", "-placement-host-address", "dapr-placement:50006", ] volumes: - "./dapr/components/:/components" depends_on: - nest-subscriber network_mode: "service:nest-subscriber"

14. 源码

​​Dapr JS SDK 让 Nest.js 集成 Dapr​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Alita- 将 React Native 代码转换成微信小程序代码(阿丽塔)
下一篇:微信小程序相关资源整理,不定期更新(微信小程序相关资源整理,不定期更新怎么办)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~