当前位置: 首页 > 科技观察

使用DockerCompose和Nestjs在本地快速构建基于Dapr的Redispub-sub分布式应用程序

时间:2023-03-16 13:49:25 科技观察

Dapr(分布式应用程序运行时)可以运行在云平台或边缘计算上。它还支持多种编程语言和开发框架。Dapr官网:https://dapr.io/Dapr的Redis发布/订阅应用实战1.创建一个项目首先,我们将创建我们的项目根文件夹来存放我们将在接下来的步骤中创建的所有服务。mkdirdapr-nestjs-redis-pub-sub2。创建DaprPlacement服务由于我们将创建多个服务,因此我们将使用docker-compose来运行这些服务。让我们在项目的根文件夹中创建docker-compose.yml文件cddapr-nestjs-redis-pub-subtouchdocker-compose.ymlversion:"3.5"services:dapr-placement:image:"daprio/dapr"命令:["./placement","-port","50006"]Dapr放置服务将负责管理Dapr参与者(我们的服务)之间的所有通信。简单来说,它负责将所有通信路由到应该接收通信的相应参与者。它充当消息代理(messagebroker)。3.创建Redis发布服务让我们继续修改我们的docker-compose.yml文件,添加我们的Redis服务。在docker-compose.yml的服务部分添加如下代码:redis-publisher:image:redisrestart:alwaysdepends_on:-dapr-placement4.创建DaprPub-Sub组件创建dapr/components文件夹。然后创建组件文件redis-pubsub.yaml。mkdir-pdapr/componentscddapr/componentstouchredis-pubsub.yaml然后打开文件并插入我们的Daprpub/sub组件详细信息apiVersion:dapr.io/v1alpha1kind:Componentmetadata:name:redis-pubsubnamespace:defaultspec:type:pubsub。redisversion:v1metadata:-name:redisHostvalue:redis-publisher:6379-name:redisPasswordvalue:""redisHost是我们的Redis服务redis-pub的名字,默认的Redis端口是63795.创建RedisDaprSidecar在上一节中反复提到,服务直接与Dapr通信,而不是直接与其他服务通信。Dapr充当所有服务的中间人。服务通过它们自己的Daprsidecar直接与Dapr通信,Daprsidecar将通信传递给Daprplacement,Daprplacement又将其传递给应该接收通信的服务的Daprsidecar。将redis-dapr-sidecar服务添加到我们的docker-compose.ymlredis-dapr-sidecar:image:"daprio/daprd:edge"command:["./daprd","-app-id","redis-publisher","-app-port","6379","-dapr-http-port","5000","-components-path","/components","-placement-host-address","dapr-placement:50006"]volumes:-"./dapr/components/:/components"depends_on:-redis-publishernetwork_mode:"service:redis-publisher"这里我们使用app-id将Daprsidecar分配给redis-publisher,同时我们使用redis端口6379。我们还必须将dapr/components(redis-pubsub.yaml)文件夹安装到docker容器中。不要忘记声明dapr-http-port。这是我们的Daprsidecar的api,它允许我们调用各种HTTP方法。定义您的dapr-http-port很重要,因为您将在这里调用各种HTTP调用/方法/请求。最后,注意将redis-dapr-sidecar附加到redis-publisher网络命名空间。6.创建NestJSServer我们将使用NestJS作为我们的节点服务器作为我们的Redis订阅者(subscriber)。转到项目文件夹cddapr-nestjs-redis-pub-sub并执行以下命令来设置NestJS节点服务器:npmi-g@nestjs/clinestnewnest-subscriber对于这个项目,我们将选择yarn作为包管理器。接下来,我们将设置一个postAPI端点。一旦Dapr从我们的Redis服务收到一个帖子,它就会调用这个端点。转到nest-subscriber/src/app.controller.ts并将此文件中的代码替换为以下内容:import{Controller,Post,Body}from'@nestjs/common';从'./app.import{AppService}service';@Controller()exportclassAppController{constructor(privatereadonlyappService:AppService){}@Post('/redis-publisher')asyncpostRedisPub(@Body()reqBody){console.log(`Redispublished${JSON.stringify(reqBody)}`);返回NestJS订阅者发布收到的${reqBody};}}7.为NestJS订阅者创建一个Dockerfile我们将NestJS服务器作为Docker容器运行。需要创建一个Dockerfile。cdnest-subscribertouchDockerfile然后打开文件并粘贴以下代码:FROMnode:16.13.0-alpineWORKDIR"/app"COPY./nest-subscriber/package.json./RUNyarninstallCOPY./nest-subscriber.RUNyarn运行buildEXPOSE3000CMD["yarn","start:prod"]构建镜像:dockerbuild-f./nest-subscriber/Dockerfile-tnest-subscriber:latest。--无缓存8。将NestJS订阅服务添加到docker-compose文件创建NestJS服务器和Dockerfile后,我们创建nest-subscriberdocker服务。将以下内容添加到docker-compose.yml:nest-subscriber:image:"nest-subscriber:latest"depends_on:-redis-publisher-dapr-placementrestart:always9.创建Dapr订阅我们将订阅我们的pub/sub定义配置。创建一个dapr/subscriptions文件夹。然后创建组件文件redis-subscription.yamlmkdir-pdapr/subscriptionscddapr/subscriptionstouchredis-subscription.yaml然后打开文件并插入我们的Dapr订阅组件的详细信息apiVersion:dapr.io/v1alpha1kind:Subscriptionmetadata:name:nest-redis-subspec:topic:nest-redis-pub-topicroute:/redis-publisherpubsubname:redis-pubsubscopes:-nest-subscriber路由是Dapr在发布主题时会调用的API作用域,以及订阅的服务到主题。pubsubname是redis-pubsub,它等于我们的redis-pubsub.yaml文件中定义的元数据名称。在这个项目中,如果一个topicnest-redis-pub-topic被发布,Dapr会在我们的nest-subscriber服务中调用API/redis-publisher。10.创建NestJS服务器DaprSidecar我们需要为我们的NestJS服务创建一个Sidecar,就像redis-publisher服务一样。将nest-subscriber-dapr-sidecar服务添加到我们的docker-compose.ymlnest-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”,]卷:-"./dapr/components/:/components"depends_on:-nest-subscribernetwork_mode:"service:nest-subscriber"11.测试是否正常DaprDocker容器在Docker网络中通信。但出于测试目的,我们将打开映射以在本地计算机上公开端口5000到5001。redis-publisher:image:redisdepends_on:-dapr-placementrestart:alwaysports:-5001:5000然后在终端中执行以下命令:curl--location--requestPOST'http://localhost:5001/v1。0/publish/redis-pubsub/nest-redis-pub-topic'\--header'Content-Type:application/json'\--data-raw'{"hello":"world"}'DaprOne的优势是它遵循特定的URL格式。这里我们只使用DaprsidecarHTTP端口(5001),然后是版本号(v1.0),然后是操作(发布)。然后是我们的redis-pubsub.yaml配置文件中定义的pubsubname(redis-pubsub)和topic(nest-redis-pub-topic)。一旦发出HTTPpost请求。我们的NestJS服务器应该在/redis-publisher收到一个发布请求,这应该会产生以下日志:我们可以看到它正在通过Dapr接收Redis发布。但是我们的NestJS服务器无法正确处理消息。仅发布{},而不是我们发布的消息。我们将在下一步中解决这个问题。注意:我们通过redis-dapr-sidecar的dapr-http-port调用发布服务。通常会有一个单独的Docker服务(例如另一个服务器),它有自己的Daprsidecar,它将调用redis发布服务。在这种情况下,我们将使用该Docker服务的Daprsidecarhttp-port。该请求将由sidecar发送到Dapr放置服务,然后该服务将确定将请求转发到的正确Daprsidecar。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:cdnest-subscriberyarnaddbody-parser接下来我们需要修改我们的NestJS服务器main.ts:import{NestFactory}from'@nestjs/core';import{AppModule}from'./app.module';import*asbodyParserfrom'body-parser';asyncfunctionbootstrap(){constapp=awaitNestFactory.create(AppModule);app.use(bodyParser.json({type:'application/cloudevents+json'}));app.use(bodyParser.json());等待app.listen(3000);}bootstrap();当我们再次发送post请求时,我们的NestJS服务器将能够处理请求文本并显示以下日志:好的,我们现在有一个在Dapr之上运行的RedisPub/Sub分布式应用程序。13.完成docker-compose.yamlversion:"3.5"services:dapr-placement:image:"daprio/dapr"command:["./placement","-port","50006"]redis-publisher:image:redisdepends_on:-dapr-placement重启:始终端口:-5001:5000redis-dapr-sidecar:图像:“daprio/daprd:edge”命令:[“./daprd”,“-app-id”,“redis-publisher”","-app-port","6379","-dapr-http-port","5000","-components-path","/components","-placement-host-address","dapr-placement:50006"]volumes:-"./dapr/components/:/components"depends_on:-redis-publishernetwork_mode:"service:redis-publisher"nest-subscriber:image:"nest-subscriber:latest"depends_on:-redis-publisher-dapr-placement重启:总是nest-subscriber-dapr-sidecar:图像:“daprio/daprd:edge”命令:[“./daprd”,“-app-id”,“nest-subscriber”,“-app-port”,“3000”,“-components-path”,“/components”,“-placement-host-address”,“dapr-placement:50006”,]卷:-“./dapr/components/:/components”depends_on:-nest-subscribernetwork_mode:“service:nest-subscriber”14。源码https://github.com/Hacker-Linner/dapr-nestjs-redis-pub-sub.git