V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
abser
V2EX  ›  Go 编程语言

微软的分布式应用框架 Dapr Helloworld

  •  1
     
  •   abser ·
    abserari · 2019-11-06 19:51:19 +08:00 · 3687 次点击
    这是一个创建于 1604 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Dapr HelloWorld

    Dapr

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

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

    我现在也不是很懂。

    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

    环境

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

    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
    

    HelloWorld

    Application Architecture

    image.png
    能够看到暴露两个 endpoint 是 HTTP 访问,一个创建一个查询。

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

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

    Download Code

    下载并进入相应文件夹

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

    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 的环境端口,如果你安装时有改动,需要考虑。
    stateurl 就是 Dapr 提供的 URL 了

    Handlers

    /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 中。

    /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

    Dapr Run Node.js App

    1. npm install :通过当前目录下的 package.json , 会安装 express 和 body-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 端口运行

    Post and Get

    接下来注意,文中的端口是 app.js 里默认的 3500

    Post

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

    Vscode

    如果你用 vscode,使用这个插件 Rest Client Plugin
    然后打开目录下的 sample.http , 可以看到 send request 的选项
    sample.http

    POST http://localhost:3500/v1.0/invoke/mynode/method/neworder
    {
      "data": {
        "orderId": "42"
      } 
    }
    

    Postman

    如图: http://localhost:3500/v1.0/invoke/mynode/method/neworder 

    Result Update

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

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

    Get

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

    Vscode

    sample.http

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

    Postman

    image.png

    Terminate

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

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

    Feature

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

    Refer

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5150 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 09:33 · PVG 17:33 · LAX 02:33 · JFK 05:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.