NodeJS 基于 Dapr 构建云原生微服务应用,从 0 到 1 快速上手指南

网友投稿 567 2022-10-11

Nodejs 基于 Dapr 构建云原生微服务应用,从 0 到 1 快速上手指南

NodeJS 基于 Dapr 构建云原生微服务应用,从 0 到 1 快速上手指南

Dapr 是一个可移植的、事件驱动的运行时,它使任何开发人员能够轻松构建出弹性的、无状态和有状态的应用程序,并可运行在云平台或边缘计算中,它同时也支持多种编程语言和开发框架。Dapr 确保开发人员专注于编写业务逻辑,不必分神解决分布式系统难题,从而显著提高了生产力。Dapr 降低了构建微服务架构类现代云原生应用的门槛。

系列

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

安装 Dapr CLI

MacOS & Dapr 1.8:

sudo curl -fsSL | /bin/bash

Linux/Windows 安装方式:

​​Dapr

Dapr 初始化包括:

运行一个用于状态存储和消息代理的Redis 容器实例运行一个用于提供可观察性的Zipkin 容器实例创建具有上述组件定义的默认组件文件夹运行用于本地 actor(我们的服务) 支持的Dapr placement 服务容器实例

运行初始化 CLI 命令

dapr init

验证 Dapr 版本

dapr -vCLI version: 1.8.0Runtime version: 1.8.0

验证容器是否正在运行

如前所述,​​dapr init​​​ 命令会启动几个容器,这些容器将帮助您开始使用 ​​Dapr​​​。 验证您有运行 ​​daprio/dapr​​​、​​openzipkin/zipkin​​​ 和 ​​redis​​ 映像的容器实例:

验证组件目录是否已初始化

在 ​​dapr init​​​ 上,​​CLI​​​ 还会创建一个默认组件文件夹,其中包含几个 ​​YAML​​​ 文件,其中包含状态存储、​​Pub/sub​​​ 和 ​​Zipkin​​​ 的定义。​​Dapr sidecar​​ 将读取这些组件并使用:

用于状态管理和消息传递的 Redis 容器。用于收集踪迹的 Zipkin 容器。

通过打开您的组件目录进行验证:

Windows, 在​​%UserProfile%\.dapr​​ 下Linux/MacOS, 在​​~/.dapr​​ 下

ls $HOME/.daprbin components config.yaml

使用 Dapr API

运行 Dapr sidecar 并试用 state API

运行 Dapr sidecar

​​dapr run​​ 命令启动一个应用程序,以及一个 sidecar。

启动一个 Dapr sidecar,它将在端口 3500 上侦听名为 ​​myapp​​ 的空白应用程序:

dapr run --app-id myapp --dapr-3500

由于没有使用上述命令定义自定义组件文件夹,因此 Dapr 使用在 ​​dapr init​​ 流程期间创建的默认组件定义。

保存状态

使用对象更新状态。新状态将如下所示:

[ { "key": "name", "value": "Bruce Wayne" }]

请注意,包含在状态中的每个对象都有一个分配有值为 ​​name​​​ 的 ​​key​​​。您将在下一步中使用该 ​​key​​。

使用以下命令保存新的状态对象:

curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "Bruce Wayne"}]' key 为 ​​name​​ 的状态检索您刚刚存储在 state 中的对象。在同一终端窗口中,运行以下命令:

curl Redis 中

docker exec -it dapr_redis redis-cli

列出 Redis 键以查看 Dapr 如何使用您提供给 dapr run 的 app-id 作为 ​​key​​ 的前缀创建键值对:

keys *"myapp||name"

运行以下命令查看状态值:

hgetall "myapp||name"1) "data"2) "\"Bruce Wayne\""3) "version"4) "1"

使用以下命令退出 Redis CLI:

exit

删除状态

在同一终端窗口中,从状态存储中删除 ​​name​​ 状态对象。

curl -v -X DELETE -H "Content-Type: application/json" ​​MacOS/NodeJs v16.16.0​​ 下实战完成。

1. 服务调用

使用 Dapr 的服务调用构建块,您的应用程序可以与其他应用程序可靠且安全地通信。

示例仓库

git clone order-processor 服务

从 quickstarts 的根目录导航到 ​​order-processor​​ 目录。

cd service_invocation/javascript/install

与 Dapr sidecar 一起运行 ​​order-processor​​ 服务。

dapr run --app-port 5001 --app-id order-processor --app-protocol --dapr-3501 -- npm start

app.post('/orders', (req, res) => { console.log("Order received:", req.body); res.sendStatus(200);});

运行 checkout 服务

在新的终端窗口中,从 quickstarts 根目录导航到 ​​checkout​​ 目录。

cd service_invocation/javascript/install

与 Dapr sidecar 一起运行 ​​checkout​​ 服务。

dapr run --app-id checkout --app-protocol --dapr-3500 -- npm start

在 ​​checkout​​​ 服务中,您会注意到无需重写您的应用程序代码即可使用 Dapr 的服务调用。您可以通过简单地添加 ​​dapr-app-id​​ header 来启用服务调用,该 header 指定目标服务的 ID。

let axiosConfig = { headers: { "dapr-app-id": "order-processor" }};const res = await axios.post(`${DAPR_HOST}:${DAPR_HTTP_PORT}/orders`, order , axiosConfig);console.log("Order passed: " + res.config.data);

查看服务调用输出

Dapr 在任何 Dapr 实例上调用应用程序。在代码中,sidecar 编程模型鼓励每个应用程序与其自己的 Dapr 实例通信。Dapr 实例随后发现并相互通信。

​​checkout​​​ & ​​order-processor​​ 服务输出:

2. 状态管理

让我们看一下 Dapr 的状态管理构建块。您将使用 Redis 进行状态存储,来保存、获取和删除你的状态,您也可以将其换成任何一种受 Dapr 支持的状态存储。

操纵服务状态

在终端窗口中,导航到 ​​order-processor​​ 目录。

cd state_management/javascript/sdk/order-processor

安装依赖项,其中将包括 JavaScript SDK 中的 ​​dapr-client​​ 包:

npm install

验证您在服务目录中包含以下文件:

​​package.json​​​​package-lock.json​​

与 Dapr sidecar 一起运行 ​​order-processor​​ 服务。

dapr run --app-id order-processor --components-path ../../../components/ -- npm run start

​​order-processor​​​ 服务将 orderId ​​key/value​​​ 写入、读取和删除到 ​​statestore.yaml​​​ 组件中定义的 ​​statestore​​ 实例。一旦服务启动,它就会执行一个循环。

const client = new DaprClient(DAPR_HOST, DAPR_HTTP_PORT); // 将 state 保存到 state store 中 client.state.save(STATE_STORE_NAME, [ { key: orderId.toString(), value: order } ]); console.log("Saving Order: ", order); // 从 state store 中获取 state var result = client.state.get(STATE_STORE_NAME, orderId.toString()); result.then(function(val) { console.log("Getting Order: ", val); }); // 从 state store 中删除 state client.state.delete(STATE_STORE_NAME, orderId.toString()); result.then(function(val) { console.log("Deleting Order: ", val); });

查看 order-processor 输出

请注意,正如上面代码中所指定的,代码将应用程序状态​​保存​​​在 Dapr 状态存储中,​​读取​​​它,然后将其​​删除​​。

Order-processor 输出:

​​statestore.yaml​​ 组件文件

当你运行 ​​dapr init​​ 时,Dapr 会创建一个默认的 Redis statestore.yaml 并在你的本地机器上运行一个 Redis 容器,它位于:

Windows,​​%UserProfile%\.dapr\components\statestore.yaml​​Linux/MacOS ,​​~/.dapr/components/statestore.yaml​​

使用 ​​statestore.yaml​​ 组件,您可以轻松切换状态存储,而无需更改代码。

本快速入门包含的 Redis ​​statestore.yaml​​ 文件包含以下内容:

apiVersion: dapr.io/v1alpha1kind: Componentmetadata: name: statestorespec: type: state.redis version: v1 metadata: - name: redisHost value: localhost:6379 - name: redisPassword value: "" - name: actorStateStore value: "true"

在 YAML 文件中:

​​metadata/name​​​ 是您的应用程序与组件对话的方式(在代码示例中称为​​DAPR_STORE_NAME​​)。​​spec/metadata​​ 定义到组件使用的 Redis 实例的连接。

3. 发布和订阅

开始使用 Dapr 的发布和订阅构建块

让我们看一下 Dapr 的发布和订阅 (Pub/sub) 构建块。您将运行发布者微服务和订阅者微服务,以演示 Dapr 如何启用发布/订阅模式。

使用发布服务,开发人员可以重复发布消息到 topic。Pub/sub 组件对这些消息进行排队或代理。我们下面的示例使用 Redis,您可以使用 RabbitMQ、Kafka 等。该 topic 的订阅者从队列中提取消息并处理它们。

订阅 topic

在终端窗口中,从 quickstarts 根目录导航到 order-processor 目录。

cd pub_sub/javascript/sdk/order-processor

安装依赖项,其中将包括 JavaScript SDK 中的 dapr-client 包:

npm install

验证您在服务目录中包含以下文件:

​​package.json​​​​package-lock.json​​

与 Dapr sidecar 一起运行 order-processor subscriber 服务。

dapr run --app-port 5001 --app-id order-processing --app-protocol --dapr-3501 --components-path ../../../components -- npm run start

在 order-processor 订阅者中,我们订阅名为 order_pub_sub 的 Redis 实例(如 pubsub.yaml 组件中所定义)和 topic orders。这使您的应用程序代码能够通过 Dapr sidecar 与 Redis 组件实例通信。

server.pubsub.subscribe("order_pub_sub", "orders", (data) => console.log("Subscriber received: " + JSON.stringify(data)));

发布 topic

在新的终端窗口中,从 Quickstarts 克隆目录的根目录导航到 checkout 目录。

cd pub_sub/javascript/sdk/checkout

安装依赖项,其中将包括 JavaScript SDK 中的 dapr-client 包:

npm install

验证您在服务目录中包含以下文件:

​​package.json​​​​package-lock.json​​

与 Dapr sidecar 一起运行 checkout 发布者服务。

dapr run --app-id checkout --app-protocol --dapr-3500 --components-path ../../../components -- npm run start

在 ​​checkout​​​ 发布者服务中,我们将 orderId 消息发布到名为 ​​order_pub_sub​​​ 的 Redis 实例(在 pubsub.yaml 组件中定义)和 topic ​​orders​​。服务一启动,就会循环发布:

const client = new DaprClient(DAPR_HOST, DAPR_HTTP_PORT);await client.pubsub.publish(PUBSUB_NAME, PUBSUB_TOPIC, order); console.log("Published data: " + JSON.stringify(order));

查看发布/订阅输出

请注意,正如上面代码中所指定的,发布者将一个随机数推送到 Dapr sidecar,而订阅者接收它。

发布者 & 订阅者输出:

pubsub.yaml 组件文件

当你运行 ​​dapr init​​​ 时,​​Dapr​​​ 会创建一个默认的 Redis ​​pubsub.yaml​​ 并在你的本地机器上运行一个 Redis 容器,它位于:

在 Windows 上,在​​%UserProfile%\.dapr\components\pubsub.yaml​​ 下在 Linux/MacOS 上,在​​~/.dapr/components/pubsub.yaml​​ 下

使用 ​​pubsub.yaml​​ 组件,您可以轻松更换底层组件,而无需更改应用程序代码。

本快速入门包含的 Redis ​​pubsub.yaml​​ 文件包含以下内容:

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

在 YAML 文件中:

​​metadata/name​​ 是您的应用程序与组件对话的方式。​​spec/metadata​​ 定义与组件实例的连接。​​scopes​​ 指定哪个应用程序可以使用该组件。

4. 输入和输出绑定

开始使用 Dapr 的 Binding 构建块

让我们看一下 Dapr 的 Bindings 构建块。使用绑定,您可以:

使用来自外部系统的事件触发您的应用程序。与外部系统的接口。

接下来您将使用输入 Cron binding 安排批处理脚本每 10 秒运行一次。该脚本使用 PostgreSQL Dapr binding 处理 JSON 文件并将数据输出到 SQL 数据库。

在本地运行 PostgreSQL Docker 容器

在您机器上的 Docker 容器中本地运行 PostgreSQL 实例。示例包含一个 Docker Compose 文件,用于在本地自定义、构建、运行和初始化带有默认 ​​orders​​ 表的 postgres 容器。

在终端窗口中,从 quickstarts 根目录导航到 ​​bindings/db​​ 目录。

cd bindings/db

运行以下命令来设置容器:

docker compose up

安排一个 Cron job 并写入数据库

在新的终端窗口中,导航到 SDK 目录。

cd bindings/javascript/sdk/batch

安装依赖项:

npm install

与 Dapr sidecar 一起运行 batch-sdk 服务。

dapr run --app-id batch-sdk --app-port 5002 --dapr-3500 --components-path ../../../components -- node index.js

process_batch 函数内的代码每 10 秒执行一次(在 components 目录的 binding-cron.yaml 中定义)。绑定触发器在 Dapr sidecar 的 Flask 应用程序中查找通过 HTTP POST 调用的路由。

async function start() { await server.binding.receive(cronBindingName,processBatch); await server.start();}

batch-sdk 服务使用 binding-postgres.yaml 组件中定义的 PostgreSQL 输出绑定将 OrderId、Customer 和 Price 记录插入到 ​​orders​​ 表中。

async function processBatch(){ const loc = '../../orders.json'; fs.readFile(loc, 'utf8', (err, data) => { const orders = JSON.parse(data).orders; orders.forEach(order => { let sqlCmd = `insert into orders (orderid, customer, price) values (${order.orderid}, '${order.customer}', ${order.price});`; let payload = `{ "sql": "${sqlCmd}" } `; console.log(payload); client.binding.send(postgresBindingName, "exec", "", JSON.parse(payload)); }); console.log('Finished processing batch'); }); return 0;}

查看 job 的输出

请注意,如上所述,代码使用 OrderId、Customer 和 Price 作为 payload 调用输出绑定。

你的输出绑定的 print 语句输出:

在新终端中,验证是否已将相同的数据插入到数据库中。

cd bindings/db

启动交互式 Postgres CLI:

docker exec -i -t postgres psql --username postgres -p 5432 -h localhost --no-password

在 ​​admin=#​​​ 提示符下,更改为 ​​orders​​ 表:

\c orders;

在 ​​orders=#​​ 提示符下,选择所有行:

select * from orders;

输出应如下所示:

components\binding-cron.yaml 组件文件

当您执行 dapr run 命令并指定组件路径时,Dapr sidecar:

启动 Cron 绑定构建块每 10 秒调用一次绑定端点(批处理)

binding-cron.yaml 文件包含以下内容:

apiVersion: dapr.io/v1alpha1kind: Componentmetadata: name: cron namespace: quickstartsspec: type: bindings.cron version: v1 metadata: - name: schedule value: "@every 10s"

注意:binding-cron.yaml 的元数据部分包含一个 Cron 表达式,用于指定调用绑定的频率。

component\binding-postgres.yaml 组件文件

当您执行 dapr run 命令并指定组件路径时,Dapr sidecar:

启动 PostgreSQL 绑定构建块使用 binding-postgres.yaml 文件中指定的设置连接到 PostgreSQL

使用 binding-postgres.yaml 组件,您可以轻松换出后端数据库绑定,而无需更改代码。

本快速入门包含的 PostgreSQL binding-postgres.yaml 文件包含以下内容:

apiVersion: dapr.io/v1alpha1kind: Componentmetadata: name: sqldb namespace: quickstartsspec: type: bindings.postgres version: v1 metadata: - name: url value: "user=postgres password=docker host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10"

在 YAML 文件中:

spec/type 指定 PostgreSQL 用于此绑定。spec/metadata 定义到组件使用的 PostgreSQL 实例的连接。

5. Secrets 管理

开始使用 Dapr 的 Secrets Management 构建块

Dapr 提供了一个专用的 secrets API,允许开发人员从 secrets store 中检索 secrets。接下来:

运行带有 secret 存储组件的微服务。在应用程序代码中使用 Dapr secrets API 检索 secrets。

检索 secrets

在终端窗口中,导航到 ​​order-processor​​ 目录。

cd secrets_management/javascript/sdk/order-processor

安装依赖项:

npm install

与 Dapr sidecar 一起运行 order-processor 服务。

dapr run --app-id order-processor --components-path ../../../components/ -- npm start

在幕后

order-processor 服务

请注意下面的 order-processor 服务如何指向:

在 local-secret-store.yaml 组件中定义的 DAPR_SECRET_STORE。在 secrets.json 中定义的 secret。

// index.jsconst DAPR_SECRET_STORE = "localsecretstore";const SECRET_NAME = "secret";async function main() { // ... const secret = await client.secret.get(DAPR_SECRET_STORE, SECRET_NAME); console.log("Fetched Secret: " + JSON.stringify(secret));}

local-secret-store.yaml 组件

DAPR_SECRET_STORE 定义在 local-secret-store.yaml 组件文件中,位于 secrets_management/components 中:

apiVersion: dapr.io/v1alpha1kind: Componentmetadata: name: localsecretstore namespace: defaultspec: type: secretstores.local.file version: v1 metadata: - name: secretsFile value: secrets.json - name: nestedSeparator value: ":"

在 YAML 文件中:

​​metadata/name​​ 是您的应用程序引用组件的方式(在代码示例中称为 DAPR_SECRET_STORE)。​​spec/metadata​​ 定义与组件使用的 secret 的连接。

secrets.json 文件

​​SECRET_NAME​​​ 在位于 ​​secrets_management/javascript/sdk/order-processor​​​ 的 ​​secrets.json​​ 文件中定义:

{ "secret": "YourPasskeyHere"}

查看 order-processor 输出

正如上面的应用程序代码中所指定的,order-processor 服务通过 Dapr secret 存储检索 secret 并将其显示在控制台中。

6. 官方示例仓库(源码)

​​https://github.com/dapr/quickstarts.git​​

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

上一篇:Wafer - 腾讯云下一代小程序综合解决方案(wafer连接器)
下一篇:Alita- 将 React Native 代码转换成微信小程序代码(阿丽塔)
相关文章

 发表评论

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