<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>