<a name="XMoC2"></a>javascript
Distributed Application Runtime. An event-driven, portable runtime for building microservices on cloud and edge.java
分佈式應用運行時、事件驅動、爲雲和邊緣構建微服務提供便攜化運行時。node
我如今也不是很懂。git
<a name="MCBci"></a>github
GitHubredis
Dapr is a portable, serverless, event-driven runtime that makes it easy for developers to build resilient, stateless and stateful microservices that run on the cloud and edge and embraces the diversity of languages and developer frameworks.docker
Dapr codifies the best practices for building microservice applications into open, independent, building blocks that enable you to build portable applications with the language and framework of your choice. Each building block is independent and you can use one, some, or all of them in your application.express
比上面的介紹多了 stateless or stateful 的標籤。學《計算理論》的時候接觸過一些狀態機。npm
」狀態時萬惡之源「 編程
注意提到了多語言和多開發者框架,我認爲這是他選擇的經過通訊共享信息,即 HTTP
和 GRPC
支持多語言等特性。微軟想經過這個設定一個構建微服務應用的規則。從根本上確立你開發的每個應用的獨立性。
下面進行一個 QuickStart
<a name="BuQMg"></a>
<a name="9Pq3v"></a>
Install the latest darwin Dapr CLI to /usr/local/bin
curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | /bin/bash
有條件能夠加速
執行初始化(會啓動 docker 容器)
$ dapr init ⌛ Making the jump to hyperspace... Downloading binaries and setting up components ✅ Success! Dapr is up and running $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b3a5600e672f redis "docker-entrypoint.s…" 44 hours ago Up 44 hours 0.0.0.0:6379->6379/tcp xenodochial_hofstadter e5010ba0c33f daprio/dapr "./placement" 44 hours ago Up 44 hours 0.0.0.0:50005->50005/tcp dapr_placement
<a name="qGzU3"></a>
<a name="s5AAY"></a>
<br />可以看到暴露兩個
endpoint
是 HTTP
訪問,一個建立一個查詢。
主要看咱們使用 Dapr
的交互。在圖中它做爲 Runtime
<a name="Szu0t"></a>
下載並進入相應文件夾
git clone https://github.com/dapr/samples.git cd samples/1.hello-world
<a name="nsc6T"></a>
// $ cat app.js // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. // ------------------------------------------------------------ const express = require('express'); const bodyParser = require('body-parser'); require('isomorphic-fetch'); const app = express(); app.use(bodyParser.json()); const daprPort = process.env.DAPR_HTTP_PORT || 3500; const stateUrl = `http://localhost:${daprPort}/v1.0/state`; const port = 3000; app.get('/order', (_req, res) => { fetch(`${stateUrl}/order`) .then((response) => { return response.json(); }).then((orders) => { res.send(orders); }); }); app.post('/neworder', (req, res) => { const data = req.body.data; const orderId = data.orderId; console.log("Got a new order! Order ID: " + orderId); const state = [{ key: "order", value: data }]; fetch(stateUrl, { method: "POST", body: JSON.stringify(state), headers: { "Content-Type": "application/json" } }).then((response) => { console.log((response.ok) ? "Successfully persisted state" : "Failed to persist state"); }); res.status(200).send(); }); app.listen(port, () => console.log(`Node App listening on port ${port}!`));
這是一些路由和 handlers
注意 14-16 行
const daprPort = process.env.DAPR_HTTP_PORT || 3500; const stateUrl = `http://localhost:${daprPort}/v1.0/state`; const port = 3000;
3500 是 Dapr
的環境端口,若是你安裝時有改動,須要考慮。<br />stateurl
就是 Dapr
提供的 URL 了
<a name="zjdNP"></a>
<a name="iWwkd"></a>
app.post('/neworder', (req, res) => { const data = req.body.data; const orderId = data.orderId; console.log("Got a new order! Order ID: " + orderId); const state = [{ key: "order", value: data }]; fetch(stateUrl, { method: "POST", body: JSON.stringify(state), headers: { "Content-Type": "application/json" } }).then((response) => { console.log((response.ok) ? "Successfully persisted state" : "Failed to persist state"); }); res.status(200).send(); });
這裏重點是狀態存儲,即將 state
經過 stateurl
存儲在 Dapr
中。
<a name="IaPwp"></a>
咱們並非直接經過 res.json
做爲 Response
來進行已經持久化的數據的使用,而是經過暴露一個 GET endpoint 經過訪問它來驗證持久化是否成功。
app.get('/order', (_req, res) => { fetch(`${stateUrl}/order`) .then((response) => { return response.json(); }).then((orders) => { res.send(orders); }); });
如今咱們經過狀態轉移在 Dapr
裏實現了 stateless
,一樣咱們也能夠在加上一個 local cache
並經過一個新的 endpoint 訪問來使 Node
application 變成 stateful
<a name="6NX8n"></a>
npm install
:經過當前目錄下的 package.json
, 會安裝 express
和 body-parser
,在 app.js 7-8行咱們能夠看到這兩項。dapr run --app-id mynode --app-port 3000 --port 3500 node app.js
$ dapr run --app-id mynode --app-port 3000 --port 3500 node app.js ℹ️ Starting Dapr with id mynode. HTTP Port: 3500. gRPC Port: 55099 ✅ You're up and running! Both Dapr and your app logs will appear here.
應該是有後臺運行的 CLI
命令,這裏是前臺打印的日誌
== DAPR == time="2019-11-06T10:37:41+08:00" level=info msg="starting Dapr Runtime -- version 0.1.0 -- commit 4358565-dirty" == DAPR == time="2019-11-06T10:37:41+08:00" level=info msg="log level set to: info" == DAPR == time="2019-11-06T10:37:41+08:00" level=info msg="standalone mode configured" == DAPR == time="2019-11-06T10:37:41+08:00" level=info msg="dapr id: mynode" == DAPR == time="2019-11-06T10:37:41+08:00" level=info msg="loaded component messagebus (pubsub.redis)" == DAPR == time="2019-11-06T10:37:41+08:00" level=info msg="loaded component statestore (state.redis)" == DAPR == time="2019-11-06T10:37:41+08:00" level=info msg="application protocol: http. waiting on port 3000" == APP == Node App listening on port 3000! == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="application discovered on port 3000" == DAPR == 2019/11/06 10:37:42 redis: connecting to localhost:6379 == DAPR == 2019/11/06 10:37:42 redis: connected to localhost:6379 (localAddr: [::1]:55130, remAddr: [::1]:6379) == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="actors: starting connection attempt to placement service at localhost:50005" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="http server is running on port 3500" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="gRPC server is running on port 55099" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="local service entry announced" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 945.8297490000001ms" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="actors: established connection to placement service at localhost:50005" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="actors: placement order received: lock" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="actors: placement order received: update" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="actors: placement tables updated" == DAPR == time="2019-11-06T10:37:42+08:00" level=info msg="actors: placement order received: unlock"
⚠️:注意到 Node App
在指定的 3000
端口運行,同時還有狀態存儲的 redis
在 6379
端口運行
<a name="4c61x"></a>
接下來注意,文中的端口是 app.js
裏默認的 3500
<a name="B0eiO"></a>
<a name="zK8en"></a>
curl -XPOST -d @sample.json http://localhost:3500/v1.0/invoke/mynode/method/neworder
<a name="4JeyP"></a>
若是你用 vscode ,使用這個插件 Rest Client Plugin<br />而後打開目錄下的 sample.http
, 能夠看到 send request 的選項<br />sample.http
POST http://localhost:3500/v1.0/invoke/mynode/method/neworder { "data": { "orderId": "42" } }
<a name="b0mVa"></a>
如圖: http://localhost:3500/v1.0/invoke/mynode/method/neworder
<a name="iMLzt"></a>
你能夠在你啓動的終端中看到新的日誌
== APP == Got a new order! Order ID: 42 == APP == Successfully persisted state
<a name="VFOMe"></a>
<a name="zYZpd"></a>
curl http://localhost:3500/v1.0/invoke/mynode/method/order
<a name="RiAVm"></a>
GET http://localhost:3500/v1.0/invoke/mynode/method/order
<a name="oi8De"></a>
<a name="sOJNZ"></a>
ctrl + c
或者 dapr stop --app-id mynode
^C ℹ️ terminated signal received: shutting down ✅ Exited Dapr successfully ✅ Exited App successfully
<a name="sojfC"></a>
<a name="lMDgW"></a>