Dapr+NestJs編寫Pub及Sub裝飾器實(shí)戰(zhàn)示例

Dapr 是一個(gè)可移植的、事件驅(qū)動(dòng)的運(yùn)行時(shí),它使任何開發(fā)人員能夠輕松構(gòu)建出彈性的、無狀態(tài)和有狀態(tài)的應(yīng)用程序,并可運(yùn)行在云平臺(tái)或邊緣計(jì)算中,它同時(shí)也支持多種編程語言和開發(fā)框架。Dapr 確保開發(fā)人員專注于編寫業(yè)務(wù)邏輯,不必分神解決分布式系統(tǒng)難題,從而顯著提高了生產(chǎn)力。Dapr 降低了構(gòu)建微服務(wù)架構(gòu)類現(xiàn)代云原生應(yīng)用的門檻。
系列
本地使用 Docker Compose 與 Nestjs 快速構(gòu)建基于 Dapr 的 Redis 發(fā)布/訂閱分布式應(yīng)用
NodeJS 基于 Dapr 構(gòu)建云原生微服務(wù)應(yīng)用,從 0 到 1 快速上手指南
Dapr JavaScript SDK
用于在 JavaScript 和 TypeScript 中構(gòu)建 Dapr 應(yīng)用程序的客戶端庫。 該客戶端抽象了公共 Dapr API,例如服務(wù)到服務(wù)調(diào)用、狀態(tài)管理、發(fā)布/訂閱、Secret 等,并為構(gòu)建應(yīng)用程序提供了一個(gè)簡(jiǎn)單、直觀的 API。
安裝
要開始使用 Javascript SDK,請(qǐng)從 NPM 安裝 Dapr JavaScript SDK 包:
npm install --save @dapr/dapr
?? dapr-client 現(xiàn)在已棄用。 請(qǐng)參閱#259 了解更多信息。
結(jié)構(gòu)
Dapr Javascript SDK 包含兩個(gè)主要組件:
- DaprServer: 管理所有 Dapr sidecar 到應(yīng)用程序的通信。
- DaprClient: 管理所有應(yīng)用程序到 Dapr sidecar 的通信。
上述通信可以配置為使用 gRPC 或 HTTP 協(xié)議。
實(shí)戰(zhàn)
創(chuàng)建一個(gè)小應(yīng)用程序來生成有關(guān)網(wǎng)站中用戶行為的統(tǒng)計(jì)信息。
Demo 源碼
準(zhǔn)備環(huán)境和項(xiàng)目結(jié)構(gòu)
npm install -g @nestjs/cli nest new api mv api nest-dapr cd nest-dapr nest generate app page-view npm install dapr-client wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash
創(chuàng)建一個(gè) decorators.ts 文件(apps/shared/decorators.ts),這樣所有微服務(wù)都可以從我們即將編寫的基礎(chǔ)架構(gòu)中受益。
注入 Dapr 賴項(xiàng)
注入 DaprClient 和 DaprServer,我們需要提供它們到 nest.js。
在 app.module.ts 中讓我們注冊(cè) DaprClient:
providers: [
...
{
provide: DaprClient,
useValue: new DaprClient()
}
]
在 page-view.module.ts 中以同樣的方式添加 DaprServer:
providers: [
...
{
provide: DaprServer,
useValue: new DaprServer()
}
]
配置 Dapr 組件(rabbitMQ)
用 docker compose 啟動(dòng) rabbitmq:
version: '3.9'
services:
pubsub:
image: rabbitmq:3-management-alpine
container_name: 'pubsub'
ports:
- 5674:5672
- 15674:15672 #web port
我們還需要配置 Dapr 組件。在根文件夾中創(chuàng)建一個(gè) component/pubsub.yml:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
namespace: default
spec:
type: pubsub.rabbitmq
version: v1
metadata:
- name: host
value: 'amqp://guest:guest@localhost:5674'
每個(gè) Dapr 微服務(wù)都需要自己的 config。
api/dapr/config.yml:
apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: api namespace: default
page-view/dapr/config.yml:
apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: page-view namespace: default
API/Gateway 服務(wù)
在 app.controller.ts 中,我們將公開一個(gè)簡(jiǎn)單的 API — /add-page-view。
@Post('/add-page-view')
async prderAdd(@Body() pageViewDto: PageViewDto): Promise<void> {
try {
console.log(pageViewDto);
await this.daprClient.pubsub.publish('pubsub', 'page-view-add', pageViewDto);
} catch (e) {
console.log(e);
}
}
內(nèi)部監(jiān)聽微服務(wù)
在我們將數(shù)據(jù)發(fā)布到隊(duì)列之后,我們需要監(jiān)聽它并調(diào)用它:
在 page-view.controller.ts 添加:
@DaprPubSubSubscribe('pubsub', 'add')
addPageView(data: PageViewDto) {
console.log(`addPageView executed with data: ${JSON.stringify(data)}`);
this.data.push(data);
}
注意我們現(xiàn)在需要?jiǎng)?chuàng)建的新裝飾器:@DaprPubSubscribe。
@DaprPubSubscribe 裝飾器
在 shared/decorators.ts 中:
import { INestApplication } from '@nestjs/common';
import { DaprServer } from 'dapr-client';
export type PubsubMap = {
[pubSubName: string]: {
topic: string;
target: any;
descriptor: PropertyDescriptor;
};
};
export const DAPR_PUB_SUB_MAP: PubsubMap = {};
export const DaprPubSubSubscribe = (
pubSubName: string,
topic: string,
): MethodDecorator => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
DAPR_PUB_SUB_MAP[pubSubName] = {
topic,
target,
descriptor,
};
return descriptor;
};
};
export const useDaprPubSubListener = async (app: INestApplication) => {
const daprServer = app.get(DaprServer);
for (const pubSubName in DAPR_PUB_SUB_MAP) {
const item = DAPR_PUB_SUB_MAP[pubSubName];
console.log(
`Listening to the pubsub name - "${pubSubName}" on topic "${item.topic}"`,
);
await daprServer.pubsub.subscribe(
pubSubName,
item.topic,
async (data: any) => {
const targetClassImpl = app.get(item.target.constructor);
await targetClassImpl[item.descriptor.value.name](data);
},
);
}
};
運(yùn)行應(yīng)用程序
運(yùn)行:
docker-compose up -d # 啟動(dòng) rabbitmq npm run dapr:api:dev # 啟動(dòng) api/gateway npm run page-view:dev # 啟動(dòng)內(nèi)部微服務(wù)監(jiān)聽 dapr rabbitmq 隊(duì)列
執(zhí)行請(qǐng)求:
curl --location --request POST 'http://localhost:7001/v1.0/invoke/api/method/statistics/add-page-view' \
--header 'Content-Type: application/json' \
--data-raw '{
"pageUrl" : "https://test.com/some-page",
"userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0"
}'以上就是Dapr+NestJs編寫Pub及Sub裝飾器實(shí)戰(zhàn)示例的詳細(xì)內(nèi)容,更多關(guān)于Dapr NestJs編寫Pub及Sub的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 如何在NestJS中添加對(duì)Shopify的WebHook驗(yàn)證詳解
- 如何在NestJS中添加對(duì)Stripe的WebHook驗(yàn)證詳解
- NestJS開發(fā)核心概念Providers類基本用法詳解
- Nestjs自定義注解實(shí)現(xiàn)接口權(quán)限控制詳解
- Docker?Compose+Nestjs構(gòu)建Dapr?Redis發(fā)布訂閱分布式應(yīng)用
- NestJS+Redis實(shí)現(xiàn)緩存步驟詳解
- nestjs返回給前端數(shù)據(jù)格式的封裝實(shí)現(xiàn)
- 如何在Nestjs和Vue3中使用socket.io示例詳解
相關(guān)文章
Node.js多進(jìn)程的方法與參數(shù)實(shí)例說明
這篇文章主要介紹了Node.js多進(jìn)程的方法與參數(shù)實(shí)例說明,Node.js 是以單線程的模式運(yùn)行的,但它使用的是事件驅(qū)動(dòng)來處理并發(fā),這樣有助于我們?cè)诙嗪?nbsp;cpu 的系統(tǒng)上創(chuàng)建多個(gè)子進(jìn)程,從而提高性能,需要的朋友可以參考下2023-05-05
nodeJS?express路由學(xué)習(xí)req.body與req.query方法實(shí)例詳解
這篇文章主要為大家介紹了nodeJS?express路由學(xué)習(xí)req.body與req.query方法實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
nodejs對(duì)項(xiàng)目下所有空文件夾創(chuàng)建gitkeep的方法
這篇文章主要介紹了nodejs對(duì)項(xiàng)目下所有空文件夾創(chuàng)建gitkeep的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
搭建簡(jiǎn)單的nodejs http服務(wù)器詳解
本篇文章主要介紹了搭建簡(jiǎn)單的nodejs服務(wù)器詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
nodejs實(shí)現(xiàn)的連接MySQL數(shù)據(jù)庫功能示例
這篇文章主要介紹了nodejs實(shí)現(xiàn)的連接MySQL數(shù)據(jù)庫功能,結(jié)合實(shí)例形式分析了nodejs連接及查詢mysql數(shù)據(jù)的相關(guān)操作步驟與實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-01-01
node.js +mongdb實(shí)現(xiàn)登錄功能
這篇文章主要介紹了node.js +mongdb實(shí)現(xiàn)登錄功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
export?default?和?export?的使用方式示例詳解
這篇文章主要介紹了export?default?和?export?的使用方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08

