NodeJS?基于?Dapr?構(gòu)建云原生微服務(wù)應(yīng)用快速入門教程
Dapr 是一個可移植的、事件驅(qū)動的運(yùn)行時,它使任何開發(fā)人員能夠輕松構(gòu)建出彈性的、無狀態(tài)和有狀態(tài)的應(yīng)用程序,并可運(yùn)行在云平臺或邊緣計(jì)算中,它同時也支持多種編程語言和開發(fā)框架。Dapr 確保開發(fā)人員專注于編寫業(yè)務(wù)邏輯,不必分神解決分布式系統(tǒng)難題,從而顯著提高了生產(chǎn)力。Dapr 降低了構(gòu)建微服務(wù)架構(gòu)類現(xiàn)代云原生應(yīng)用的門檻。
安裝 Dapr CLI
MacOS & Dapr 1.8:
sudo curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | /bin/bash
Linux/Windows 安裝方式:
https://docs.dapr.io/getting-started/install-dapr-cli/
本地環(huán)境中初始化 Dapr
Dapr 初始化包括:
- 運(yùn)行一個用于狀態(tài)存儲和消息代理的 Redis 容器實(shí)例
- 運(yùn)行一個用于提供可觀察性的 Zipkin 容器實(shí)例
- 創(chuàng)建具有上述組件定義的默認(rèn)組件文件夾
- 運(yùn)行用于本地 actor(我們的服務(wù)) 支持的 Dapr placement 服務(wù)容器實(shí)例
運(yùn)行初始化 CLI 命令
dapr init
驗(yàn)證 Dapr 版本
dapr -v CLI version: 1.8.0 Runtime version: 1.8.0
驗(yàn)證容器是否正在運(yùn)行
如前所述,dapr init
命令會啟動幾個容器,這些容器將幫助您開始使用 Dapr
。 驗(yàn)證您有運(yùn)行 daprio/dapr
、openzipkin/zipkin
和 redis
映像的容器實(shí)例:
驗(yàn)證組件目錄是否已初始化
在 dapr init
上,CLI
還會創(chuàng)建一個默認(rèn)組件文件夾,其中包含幾個 YAML
文件,其中包含狀態(tài)存儲、Pub/sub
和 Zipkin
的定義。Dapr sidecar
將讀取這些組件并使用:
- 用于狀態(tài)管理和消息傳遞的 Redis 容器。
- 用于收集蹤跡的 Zipkin 容器。
通過打開您的組件目錄進(jìn)行驗(yàn)證:
- Windows, 在
%UserProfile%\.dapr
下 - Linux/MacOS, 在
~/.dapr
下
ls $HOME/.dapr bin components config.yaml
使用 Dapr API
運(yùn)行 Dapr sidecar 并試用 state API
運(yùn)行 Dapr sidecar
dapr run
命令啟動一個應(yīng)用程序,以及一個 sidecar。
啟動一個 Dapr sidecar,它將在端口 3500 上偵聽名為 myapp
的空白應(yīng)用程序:
dapr run --app-id myapp --dapr-http-port 3500
由于沒有使用上述命令定義自定義組件文件夾,因此 Dapr 使用在 dapr init
流程期間創(chuàng)建的默認(rèn)組件定義。
保存狀態(tài)
使用對象更新狀態(tài)。新狀態(tài)將如下所示:
[ { "key": "name", "value": "Bruce Wayne" } ]
請注意,包含在狀態(tài)中的每個對象都有一個分配有值為 name
的 key
。您將在下一步中使用該 key
。
使用以下命令保存新的狀態(tài)對象:
curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "Bruce Wayne"}]' http://localhost:3500/v1.0/state/statestore
獲取狀態(tài)
使用帶有 key 為 name
的狀態(tài)檢索您剛剛存儲在 state 中的對象。在同一終端窗口中,運(yùn)行以下命令:
curl http://localhost:3500/v1.0/state/statestore/name
查看狀態(tài)如何存儲在 Redis 中
docker exec -it dapr_redis redis-cli
列出 Redis 鍵以查看 Dapr 如何使用您提供給 dapr run 的 app-id 作為 key
的前綴創(chuàng)建鍵值對:
keys * "myapp||name"
運(yùn)行以下命令查看狀態(tài)值:
hgetall "myapp||name" 1) "data" 2) "\"Bruce Wayne\"" 3) "version" 4) "1"
使用以下命令退出 Redis CLI:
exit
刪除狀態(tài)
在同一終端窗口中,從狀態(tài)存儲中刪除 name
狀態(tài)對象。
curl -v -X DELETE -H "Content-Type: application/json" http://localhost:3500/v1.0/state/statestore/name
上手實(shí)戰(zhàn)指南
所有官方示例筆者均在 MacOS/NodeJs v16.16.0
下實(shí)戰(zhàn)完成。
1. 服務(wù)調(diào)用
使用 Dapr 的服務(wù)調(diào)用構(gòu)建塊,您的應(yīng)用程序可以與其他應(yīng)用程序可靠且安全地通信。
示例倉庫
git clone https://github.com/dapr/quickstarts.git
運(yùn)行 order-processor 服務(wù)
從 quickstarts 的根目錄導(dǎo)航到 order-processor
目錄。
cd service_invocation/javascript/http/order-processor
安裝依賴項(xiàng):
npm install
與 Dapr sidecar 一起運(yùn)行 order-processor
服務(wù)。
dapr run --app-port 5001 --app-id order-processor --app-protocol http --dapr-http-port 3501 -- npm start
app.post('/orders', (req, res) => { console.log("Order received:", req.body); res.sendStatus(200); });
運(yùn)行 checkout 服務(wù)
在新的終端窗口中,從 quickstarts 根目錄導(dǎo)航到 checkout
目錄。
cd service_invocation/javascript/http/checkout
安裝依賴項(xiàng):
npm install
與 Dapr sidecar 一起運(yùn)行 checkout
服務(wù)。
dapr run --app-id checkout --app-protocol http --dapr-http-port 3500 -- npm start
在 checkout
服務(wù)中,您會注意到無需重寫您的應(yīng)用程序代碼即可使用 Dapr 的服務(wù)調(diào)用。您可以通過簡單地添加 dapr-app-id
header 來啟用服務(wù)調(diào)用,該 header 指定目標(biāo)服務(wù)的 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);
查看服務(wù)調(diào)用輸出
Dapr 在任何 Dapr 實(shí)例上調(diào)用應(yīng)用程序。在代碼中,sidecar 編程模型鼓勵每個應(yīng)用程序與其自己的 Dapr 實(shí)例通信。Dapr 實(shí)例隨后發(fā)現(xiàn)并相互通信。
checkout
& order-processor
服務(wù)輸出:
2. 狀態(tài)管理
讓我們看一下 Dapr 的狀態(tài)管理構(gòu)建塊。您將使用 Redis 進(jìn)行狀態(tài)存儲,來保存、獲取和刪除你的狀態(tài),您也可以將其換成任何一種受 Dapr 支持的狀態(tài)存儲。
操縱服務(wù)狀態(tài)
在終端窗口中,導(dǎo)航到 order-processor
目錄。
cd state_management/javascript/sdk/order-processor
安裝依賴項(xiàng),其中將包括 JavaScript SDK 中的 dapr-client
包:
npm install
驗(yàn)證您在服務(wù)目錄中包含以下文件:
package.json
package-lock.json
與 Dapr sidecar 一起運(yùn)行 order-processor
服務(wù)。
dapr run --app-id order-processor --components-path ../../../components/ -- npm run start
order-processor
服務(wù)將 orderId key/value
寫入、讀取和刪除到 statestore.yaml
組件中定義的 statestore
實(shí)例。一旦服務(wù)啟動,它就會執(zhí)行一個循環(huán)。
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 輸出
請注意,正如上面代碼中所指定的,代碼將應(yīng)用程序狀態(tài)保存
在 Dapr 狀態(tài)存儲中,讀取
它,然后將其刪除
。
Order-processor 輸出:
statestore.yaml
組件文件
當(dāng)你運(yùn)行 dapr init
時,Dapr 會創(chuàng)建一個默認(rèn)的 Redis statestore.yaml 并在你的本地機(jī)器上運(yùn)行一個 Redis 容器,它位于:
- Windows,
%UserProfile%\.dapr\components\statestore.yaml
- Linux/MacOS ,
~/.dapr/components/statestore.yaml
使用 statestore.yaml
組件,您可以輕松切換狀態(tài)存儲,而無需更改代碼。
本快速入門包含的 Redis statestore.yaml
文件包含以下內(nèi)容:
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: statestore spec: type: state.redis version: v1 metadata: - name: redisHost value: localhost:6379 - name: redisPassword value: "" - name: actorStateStore value: "true"
在 YAML 文件中:
metadata/name
是您的應(yīng)用程序與組件對話的方式(在代碼示例中稱為DAPR_STORE_NAME
)。spec/metadata
定義到組件使用的 Redis 實(shí)例的連接。
3. 發(fā)布和訂閱
開始使用 Dapr 的發(fā)布和訂閱構(gòu)建塊
讓我們看一下 Dapr 的發(fā)布和訂閱 (Pub/sub) 構(gòu)建塊。您將運(yùn)行發(fā)布者微服務(wù)和訂閱者微服務(wù),以演示 Dapr 如何啟用發(fā)布/訂閱模式。
- 使用發(fā)布服務(wù),開發(fā)人員可以重復(fù)發(fā)布消息到 topic。
- Pub/sub 組件對這些消息進(jìn)行排隊(duì)或代理。我們下面的示例使用 Redis,您可以使用 RabbitMQ、Kafka 等。
- 該 topic 的訂閱者從隊(duì)列中提取消息并處理它們。
訂閱 topic
在終端窗口中,從 quickstarts 根目錄導(dǎo)航到 order-processor 目錄。
cd pub_sub/javascript/sdk/order-processor
安裝依賴項(xiàng),其中將包括 JavaScript SDK 中的 dapr-client 包:
npm install
驗(yàn)證您在服務(wù)目錄中包含以下文件:
package.json
package-lock.json
與 Dapr sidecar 一起運(yùn)行 order-processor subscriber 服務(wù)。
dapr run --app-port 5001 --app-id order-processing --app-protocol http --dapr-http-port 3501 --components-path ../../../components -- npm run start
在 order-processor 訂閱者中,我們訂閱名為 order_pub_sub 的 Redis 實(shí)例(如 pubsub.yaml 組件中所定義)和 topic orders。這使您的應(yīng)用程序代碼能夠通過 Dapr sidecar 與 Redis 組件實(shí)例通信。
server.pubsub.subscribe("order_pub_sub", "orders", (data) => console.log("Subscriber received: " + JSON.stringify(data)));
發(fā)布 topic
在新的終端窗口中,從 Quickstarts 克隆目錄的根目錄導(dǎo)航到 checkout 目錄。
cd pub_sub/javascript/sdk/checkout
安裝依賴項(xiàng),其中將包括 JavaScript SDK 中的 dapr-client 包:
npm install
驗(yàn)證您在服務(wù)目錄中包含以下文件:
package.json
package-lock.json
與 Dapr sidecar 一起運(yùn)行 checkout 發(fā)布者服務(wù)。
dapr run --app-id checkout --app-protocol http --dapr-http-port 3500 --components-path ../../../components -- npm run start
在 checkout
發(fā)布者服務(wù)中,我們將 orderId 消息發(fā)布到名為 order_pub_sub
的 Redis 實(shí)例(在 pubsub.yaml 組件中定義)和 topic orders
。服務(wù)一啟動,就會循環(huán)發(fā)布:
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));
查看發(fā)布/訂閱輸出
請注意,正如上面代碼中所指定的,發(fā)布者將一個隨機(jī)數(shù)推送到 Dapr sidecar,而訂閱者接收它。
發(fā)布者 & 訂閱者輸出:
pubsub.yaml 組件文件
當(dāng)你運(yùn)行 dapr init
時,Dapr
會創(chuàng)建一個默認(rèn)的 Redis pubsub.yaml
并在你的本地機(jī)器上運(yùn)行一個 Redis 容器,它位于:
在 Windows 上,在 %UserProfile%\.dapr\components\pubsub.yaml
下在 Linux/MacOS 上,在 ~/.dapr/components/pubsub.yaml
下
使用 pubsub.yaml
組件,您可以輕松更換底層組件,而無需更改應(yīng)用程序代碼。
本快速入門包含的 Redis pubsub.yaml
文件包含以下內(nèi)容:
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: order_pub_sub spec: type: pubsub.redis version: v1 metadata: - name: redisHost value: localhost:6379 - name: redisPassword value: ""
在 YAML 文件中:
metadata/name
是您的應(yīng)用程序與組件對話的方式。spec/metadata
定義與組件實(shí)例的連接。scopes
指定哪個應(yīng)用程序可以使用該組件。
4. 輸入和輸出綁定
開始使用 Dapr 的 Binding 構(gòu)建塊
讓我們看一下 Dapr 的 Bindings 構(gòu)建塊。使用綁定,您可以:
- 使用來自外部系統(tǒng)的事件觸發(fā)您的應(yīng)用程序。
- 與外部系統(tǒng)的接口。
接下來您將使用輸入 Cron binding 安排批處理腳本每 10 秒運(yùn)行一次。該腳本使用 PostgreSQL Dapr binding 處理 JSON 文件并將數(shù)據(jù)輸出到 SQL 數(shù)據(jù)庫。
在本地運(yùn)行 PostgreSQL Docker 容器
在您機(jī)器上的 Docker 容器中本地運(yùn)行 PostgreSQL 實(shí)例。示例包含一個 Docker Compose 文件,用于在本地自定義、構(gòu)建、運(yùn)行和初始化帶有默認(rèn) orders
表的 postgres 容器。
在終端窗口中,從 quickstarts 根目錄導(dǎo)航到 bindings/db
目錄。
cd bindings/db
運(yùn)行以下命令來設(shè)置容器:
docker compose up
安排一個 Cron job 并寫入數(shù)據(jù)庫
在新的終端窗口中,導(dǎo)航到 SDK 目錄。
cd bindings/javascript/sdk/batch
安裝依賴項(xiàng):
npm install
與 Dapr sidecar 一起運(yùn)行 batch-sdk 服務(wù)。
dapr run --app-id batch-sdk --app-port 5002 --dapr-http-port 3500 --components-path ../../../components -- node index.js
process_batch 函數(shù)內(nèi)的代碼每 10 秒執(zhí)行一次(在 components 目錄的 binding-cron.yaml 中定義)。綁定觸發(fā)器在 Dapr sidecar 的 Flask 應(yīng)用程序中查找通過 HTTP POST 調(diào)用的路由。
async function start() { await server.binding.receive(cronBindingName,processBatch); await server.start(); }
batch-sdk 服務(wù)使用 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 調(diào)用輸出綁定。
你的輸出綁定的 print 語句輸出:
在新終端中,驗(yàn)證是否已將相同的數(shù)據(jù)插入到數(shù)據(jù)庫中。
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;
輸出應(yīng)如下所示:
components\binding-cron.yaml 組件文件
當(dāng)您執(zhí)行 dapr run 命令并指定組件路徑時,Dapr sidecar:
- 啟動 Cron 綁定構(gòu)建塊
- 每 10 秒調(diào)用一次綁定端點(diǎn)(批處理)
binding-cron.yaml 文件包含以下內(nèi)容:
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: cron namespace: quickstarts spec: type: bindings.cron version: v1 metadata: - name: schedule value: "@every 10s"
注意:binding-cron.yaml 的元數(shù)據(jù)部分包含一個 Cron 表達(dá)式,用于指定調(diào)用綁定的頻率。
component\binding-postgres.yaml 組件文件
當(dāng)您執(zhí)行 dapr run 命令并指定組件路徑時,Dapr sidecar:
- 啟動 PostgreSQL 綁定構(gòu)建塊
- 使用 binding-postgres.yaml 文件中指定的設(shè)置連接到 PostgreSQL
使用 binding-postgres.yaml 組件,您可以輕松換出后端數(shù)據(jù)庫綁定,而無需更改代碼。
本快速入門包含的 PostgreSQL binding-postgres.yaml 文件包含以下內(nèi)容:
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: sqldb namespace: quickstarts spec: 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 實(shí)例的連接。
5. Secrets 管理
開始使用 Dapr 的 Secrets Management 構(gòu)建塊
Dapr 提供了一個專用的 secrets API,允許開發(fā)人員從 secrets store 中檢索 secrets。接下來:
- 運(yùn)行帶有 secret 存儲組件的微服務(wù)。
- 在應(yīng)用程序代碼中使用 Dapr secrets API 檢索 secrets。
檢索 secrets
在終端窗口中,導(dǎo)航到 order-processor
目錄。
cd secrets_management/javascript/sdk/order-processor
安裝依賴項(xiàng):
npm install
與 Dapr sidecar 一起運(yùn)行 order-processor 服務(wù)。
dapr run --app-id order-processor --components-path ../../../components/ -- npm start
在幕后
order-processor 服務(wù)
請注意下面的 order-processor 服務(wù)如何指向:
- 在 local-secret-store.yaml 組件中定義的 DAPR_SECRET_STORE。
- 在 secrets.json 中定義的 secret。
// index.js const 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/v1alpha1 kind: Component metadata: name: localsecretstore namespace: default spec: type: secretstores.local.file version: v1 metadata: - name: secretsFile value: secrets.json - name: nestedSeparator value: ":"
在 YAML 文件中:
metadata/name
是您的應(yīng)用程序引用組件的方式(在代碼示例中稱為 DAPR_SECRET_STORE)。spec/metadata
定義與組件使用的 secret 的連接。
secrets.json 文件
SECRET_NAME
在位于 secrets_management/javascript/sdk/order-processor
的 secrets.json
文件中定義:
{ "secret": "YourPasskeyHere"}
查看 order-processor 輸出
正如上面的應(yīng)用程序代碼中所指定的,order-processor 服務(wù)通過 Dapr secret 存儲檢索 secret 并將其顯示在控制臺中。
6. 官方示例
倉庫(源碼) https://github.com/dapr/quickstarts.git
到此這篇關(guān)于NodeJS 基于 Dapr 構(gòu)建云原生微服務(wù)應(yīng)用,從 0 到 1 快速上手指南的文章就介紹到這了,更多相關(guān)NodeJS云原生微服務(wù)應(yīng)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Node.js和MongoDB實(shí)現(xiàn)簡單日志分析系統(tǒng)
這篇文章主要介紹了Node.js和MongoDB實(shí)現(xiàn)簡單日志分析系統(tǒng),本文給出了服務(wù)器端、客戶端、圖表生成、Shell自動執(zhí)行等功能的實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-04-04node.JS事件機(jī)制與events事件模塊的使用方法詳解
本文將詳細(xì)介紹nodeJS事件機(jī)制與events事件模塊的使用方2020-02-02node.js使用express-fileupload中間件實(shí)現(xiàn)文件上傳
本文使用express作為服務(wù)端,使用express-fileupload庫提供的中間件函數(shù)來接受從客戶端傳來的圖片,并將圖片作為文件存儲在服務(wù)端,感興趣的可以了解一下2021-07-07nodeJS實(shí)現(xiàn)路由功能實(shí)例代碼
本篇文章主要介紹了nodeJS實(shí)現(xiàn)路由功能實(shí)例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06Node.js環(huán)境下JavaScript實(shí)現(xiàn)單鏈表與雙鏈表結(jié)構(gòu)
Node環(huán)境下通過npm可以獲取list的幾個相關(guān)庫,但是我們這里注重于自己動手實(shí)現(xiàn),接下來就一起來看一下Node.js環(huán)境下JavaScript實(shí)現(xiàn)單鏈表與雙鏈表結(jié)構(gòu)2016-06-06學(xué)習(xí)使用grunt來打包JavaScript和CSS程序的教程
這篇文章主要介紹了學(xué)習(xí)使用grunt來打包JavaScript和CSS程序的教程,grunt基于node.js和需要的朋友可以參考下2016-01-01