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


能够看到暴露两个 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

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

微软的分布式应用框架 Dapr Helloworld的更多相关文章

  1. 微软的分布式应用框架 Dapr

    微服务架构已成为构建云原生应用程序的标准,微服务架构提供了令人信服的好处,包括可伸缩性,松散的服务耦合和独立部署,但是这种方法的成本很高,需要了解和熟练掌握分布式系统.为了使用所有开发人员能够使用任何 ...

  2. 微软分布式云计算框架Orleans(2):容灾与集群(1)

    在上一篇:微软分布式云计算框架Orleans(1):Hello World,我们大概了解了Orleans如何运用,当然上一篇的例子可以说是简单且无效的,因为用了Orleans不可能只写一个Hello ...

  3. 阿里巴巴的分布式应用框架-dubbo负载均衡策略--- 一致哈希算法

    dubbo是阿里巴巴公司开发的一个开源分布式应用框架,基于服务的发布者和订阅者,服务者启动服务向注册中心发布自己的服务:消费者(订阅者)启动服务器向注册中心订阅所需要的服务.注册中心将订阅的服务注册列 ...

  4. 微软的权限框架Asp.Net Identity

    Asp.Net Identity 深度解析 之 注册登录的扩展   关于权限每个系统都有自己的解决方案,今天我们来讨论一下微软的权限框架Asp.Net Identity ,介绍如下  http://w ...

  5. 使用Strust2框架写HelloWorld

    使用Strust2框架写HelloWorld 一.创建JavaWeb项目 二.搭建Stust2 FrameWork开发环境 三步完成Struts2 FrameWork开发环境的搭建 1.加入搭建Str ...

  6. 跟着刚哥学习Spring框架--创建HelloWorld项目(一)

    1.Spring框架简介 Spring是一个开源框架,Spring是在2003年兴起的一个轻量级的开源框架,由Rod johnson创建.主要对JavaBean的生命周期进行管理的轻量级框架,Spri ...

  7. 解析分布式应用框架Ray架构源码

    摘要:Ray的定位是分布式应用框架,主要目标是使能分布式应用的开发和运行. Ray是UC Berkeley大学 RISE lab(前AMP lab) 2017年12月 开源的新一代分布式应用框架(刚发 ...

  8. 动手写一个简单的Web框架(HelloWorld的实现)

    动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...

  9. MassTransit | .NET 分布式应用框架

    引言 A free, open-source distributed application framework for .NET. 一个免费.开源的.NET 分布式应用框架. -- MassTran ...

随机推荐

  1. WebGL简易教程(六):第一个三维示例(使用模型视图投影变换)

    目录 1. 概述 2. 示例:绘制多个三角形 2.1. Triangle_MVPMatrix.html 2.2. Triangle_MVPMatrix.js 2.2.1. 数据加入Z值 2.2.2. ...

  2. .Net Core 3.0 稳定版发布啦!

    上个月的月底(9.23-9.25),.NET 开发者大会开始了,这届大会最主要的议题其实就是微软终于将.NET Core 3.0的面纱揭开了,我们也终于了解到了最新版本的.Net Core平台给我们带 ...

  3. 02-12 Logistic(逻辑)回归

    目录 逻辑回归 一.逻辑回归学习目标 二.逻辑回归引入 三.逻辑回归详解 3.1 线性回归与逻辑回归 3.2 二元逻辑回归的假设函数 3.2.1 让步比 3.2.2 Sigmoid函数图像 3.3 二 ...

  4. 从一道ctf看php反序列化漏洞的应用场景

    目录 0x00 first 前几天joomla爆出个反序列化漏洞,原因是因为对序列化后的字符进行过滤,导致用户可控字符溢出,从而控制序列化内容,配合对象注入导致RCE.刚好今天刷CTF题时遇到了一个类 ...

  5. python pip源安装模块的一些常见问题

    刷bugku的web时需要用python写脚本,web方面需要安装对应的模块,下面就分享一下我在安装模块时碰到的一些问题以及解决方法 首先找到pip文件所在的位置 打开cmd,cd文件位置,打开文件夹 ...

  6. conversion function——转换函数

    类型转换函数 与 explicit关键字 1.类型转换函数 在C++中,可以使用构造函数将一个指定类型的数据转换为类的对象,也可以使用类型转换函数 (type conversion function) ...

  7. CS184.1X 计算机图形学导论L3V2和L3V3(部分)

    组合变换 连接矩阵的优点是可以使用这些矩阵单独操作. 多个变换依然是一个矩阵. 连接矩阵不可交换,因为矩阵乘法不具有交换性. X3=RX2 X2=SX1 X3=R(SX1)=(RS)X1 X3≠SRX ...

  8. Vue的介绍及安装和导入

    08.27自我总结 Vue的介绍及安装和导入 本质就是封装一些js 一Vue的介绍 进式 JavaScript 框架 通过对框架的了解与运用程度,来决定其在整个项目中的应用范围,最终可以独立以框架方式 ...

  9. 单引号、双引号与定界符——PHP

    单引号与双引号 单引号和双引号在echo输出时的区别 echo输出时,如果使用单引号,那么echo会把单引号之间的全部内容当成普通字符串输出,不能识别变量和转义字符(单引号串中的内容总被认为是普通字符 ...

  10. 运用第一性原理探寻AI本质

    摘要:使用第一性原理探讨理解AI本质. 文章来源:宜信技术学院|宜信支付结算团队技术分享第二期-支付结算机器学习技术团队负责人 刘创 分享<AI与第一性原理> 分享者:宜信支付结算机器学习 ...