Dapr HelloWorld

Dapr HelloWorld

<a name="XMoC2"></a>

Dapr

Distributed Application Runtime. An event-driven, portable runtime for building microservices on cloud and edge.

分布式应用运行时、事件驱动、为云和边缘构建微服务提供便携化运行时。

我现在也不是很懂。

<a name="MCBci"></a>

dapr/dapr

GitHub

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.

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.

比上面的介绍多了 stateless or stateful 的标签。学《计算理论》的时候接触过一些状态机。

”状态时万恶之源“

注意提到了多语言和多开发者框架,我认为这是他选择的通过通信共享信息,即 HTTPGRPC 支持多语言等特性。微软想通过这个设定一个构建微服务应用的规则。从根本上确立你开发的每一个应用的独立性。

下面进行一个 QuickStart

<a name="BuQMg"></a>

环境

  1. Install Docker(微服务已经离不开容器化了)
  2. Install Dapr
  3. Node.js version 8 or greater(这个 Helloworld 是 node 应用)

<a name="9Pq3v"></a>

On MacOS

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>

HelloWorld

<a name="s5AAY"></a>

Application Architecture

image.png
image.png
<br />能够看到暴露两个 endpointHTTP 访问,一个创建一个查询。

主要看我们使用 Dapr 的交互。在图中它作为 Runtime

  • 提供 Dapr API 给多语言调用。
  • 提供 状态管理 By state stores

<a name="Szu0t"></a>

Download Code

下载并进入相应文件夹

git clone https://github.com/dapr/samples.git
cd samples/1.hello-world

<a name="nsc6T"></a>

Cat app.js

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

Handlers

<a name="iWwkd"></a>

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

/order

我们并不是直接通过 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>

Dapr Run Node.js App

  1. npm install :通过当前目录下的 package.json , 会安装 expressbody-parser ,在 app.js 7-8行我们可以看到这两项。
  2. 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 端口运行,同时还有状态存储的 redis6379 端口运行

<a name="4c61x"></a>

Post and Get

接下来注意,文中的端口是 app.js 里默认的 3500
<a name="B0eiO"></a>

Post

<a name="zK8en"></a>

Curl
curl -XPOST -d @sample.json http://localhost:3500/v1.0/invoke/mynode/method/neworder

<a name="4JeyP"></a>

Vscode

如果你用 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>

Postman

如图: http://localhost:3500/v1.0/invoke/mynode/method/neworder [图片上传失败...(image-ae2848-1573038683951)]

<a name="iMLzt"></a>

Result Update

你可以在你启动的终端中看到新的日志

== APP == Got a new order! Order ID: 42
== APP == Successfully persisted state

<a name="VFOMe"></a>

Get

<a name="zYZpd"></a>

Curl
curl http://localhost:3500/v1.0/invoke/mynode/method/order

<a name="RiAVm"></a>

Vscode

sample.http

GET http://localhost:3500/v1.0/invoke/mynode/method/order

<a name="oi8De"></a>

Postman
image.png
image.png

<a name="sOJNZ"></a>

Terminate

ctrl + c 或者 dapr stop --app-id mynode

^C
ℹ️  terminated signal received: shutting down
✅  Exited Dapr successfully
✅  Exited App successfully

<a name="sojfC"></a>

Feature

  • 具有可插入提供程序和至少一次语义的事件驱动的Pub-Sub系统
  • 使用可插入提供程序的输入和输出绑定
  • 具有可插拔数据存储的状态管理
  • 一致的服务到服务发现和调用
  • 选择加入状态模型:强大/最终一致性,首次写入/最后写入获胜
  • 跨平台虚拟演员
  • 限速
  • 使用OpenTelemetry的内置分布式跟踪
  • 使用专用的Operator和CRD在Kubernetes上本地运行
  • 通过HTTP和gRPC支持所有编程语言
  • 来自Azure,AWS,GCP的多云,开放式组件(绑定,发布-订阅,状态)
  • 作为过程或容器化在任何地方运行
  • 轻量级(58MB二进制,4MB物理内存)
  • 作为辅助工具运行-无需特殊的SDK或库
  • 专用的CLI-易于调试的开发人员友好体验
  • Java,Dotnet,Go,Javascript和Python的客户端

<a name="lMDgW"></a>

Refer

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容