Intro

Dapr 官方团队已于最近(2021.1.17)正式发布Dapr v1.0,Dapr已正式生产可用,可以部署到自托管环境或 Kubernetes 集群。对于绝大多数开发者来说,想必对Dapr只是有所耳闻,而具体是什么(What),可以解决什么样的问题(Why&How),有怎样的应用场景(Where),并不知悉。本文就尝试简要梳理下Dapr,并尝试回答以上问题。

What's Dapr

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

分布式应用运行时。一个事件驱动、可移植的运行时用于在云上和边缘计算上构建微服务。

以上是Dapr官方GitHub仓库上对Dapr的简介。文字虽短,口气却很大,因为其除了涵盖了当前所有的技术热点:分布式、云、微服务,还自我标榜为:分布式应用运行时。分布式应用我们或多或少有些了解,运行时也听到不少,比如常见的语言运行时:Java 运行时,.NET 运行时,Go 运行时等等,那运行时又是什么东西?简要来说:运行时是程序运行依赖的执行环境。以.NET 程序运行时CLR为例,它为.NET应用程序提供了一个托管的代码执行环境负责应用程序在整个执行期间的内存管理、线程管理、安全管理、远程管理、即使编译等。

那分布式应用运行时,就是提供分布式应用运行所依赖的的执行环境。那运行分布式应用需要哪些环境依赖呢?回答这个问题,我们要先思考开发分布式应用的挑战是什么?明确了挑战,那就找到了答案。

从单机到分布式,是追求更快和更高的性能,但也带来了更多的不确定性。比如,不确定计算机何时异常,不确定磁盘何时损坏,不确定网络通信的延迟,也不确定消息是否被正常消费。这些不确定性构成了分布式应用的挑战,简而言之:

  1. 异构的机器与网络:稳定性问题
  2. 普遍的节点故障:可靠性问题
  3. 不可靠的网络:一致性问题

面对这些挑战,业界提出了诸多的分布式理论、协议,如CAP定理,BASE理论,一致性协议2PC/3PC/ZAB,来保证系统的正常运行。虽然问题貌似是有了解决方案,但是应用的复杂度升高了。应用除了需要实现业务需求,还要兼顾非业务需求,集成诸如服务发现、负载均衡、失效转移、动态扩容、数据分片、调用链路监控等分布式系统的核心功能,对应用有很强的侵入性,这就是以Spring Cloud为代表的微服务框架的常见做法。

那如何解决侵入性的问题呢?这个问题随着容器编排技术的成熟有了新的解法。Kubernetes可以不侵入应用层,在容器层解决问题,比如K8S Service就具有服务发现、负载均衡的能力,HPA具有动态扩容的能力。随着K8S的快速发展,云原生的概念,也就越来越深入人心,那如何利用好K8S提供的基座能力,将更多的分布式能力下沉,让应用开发回归业务呢?其中Service Mesh提出的Sidecar模式,就很好的解决了微服务架构中网络通信的问题。Sidecar主要就是用来处理诸如服务发现、负载均衡、请求熔断等一系列非业务需求,应用在部署时动态插入Sidecar,服务间的通信通过Sidecar进行代理,以完成对服务间网络通信的接管。

到这里,微服务开发在Service Mesh的帮助下,已经渐渐回归业务本身,让更多的开发者看到了一丝曙光。It's enough? 来看下Bilgin Ibryam在Multi-Runtime Microservices Architecture文章中提及的分布式应用的四大需求:

从上图可以看出,除了网络(Networking)外,生命周期(Lifecycle)、状态(State)、捆绑(Binding)也是分布式应用要解决的问题之一。网络问题可以借由Service Mesh 比如Istio予以解决。那其他三个该如何解决呢?又要应用自行开发集成吗?显然不符合应用回归业务本身的诉求。这时,Dapr登场了,Dapr提出的分布式应用运行时就是实现了以上四个需求并将其下沉作为分布式应用的运行环境。

简而言之:Dapr将分布式能力进行封装下沉作为运行时以简化分布式应用开发的技术复杂度。

How Dapr Works

那Dapr如何简化分布式应用的开发呢?下面我们来看一看Dapr的主要特性。



一图胜千言:Dapr通过以HTTP/gRPC API这种与语言无关的方式暴露封装的分布式能力供应用调用,从而支持使用任意语言或框架进行开发集成。目前官方已经提供了Go,Node,Python,.NET,Java, C++,PHP,Rust,Javascript的Sdk,简化Dapr的集成。

其中Dapr的核心构建块(Building Block)就是用来提供各种不同的分布式能力,我们来分别看一看。

1. Service-to-service invocation(服务调用)

提到跨服务方法调用,这个大家肯定会想,这简单啊,不就是服务暴露API就好了嘛。是,但不完全是。比如nodeapp暴露了一个API:http://10.0.0.2:8000/neworder,按照传统的方式,直接HTTP POST这个API访问就得了,但在Dapr中,其提供了服务间方法调用的接口规范,需要按照

POST/GET/PUT/DELETE http://localhost:<daprPort>/v1.0/invoke/<appId>/method/<method-name> 的格式进行访问。那假设pythonapp需要访问nodeapp的方法,就需要POST一个请求到http://localhost:3500/v1.0/invoke/nodeapp/method/neworder。你可能会想为何多此一举呢?此举的意义何在呢?目的很简单,就是为了实现对服务间网络通信的控制以完成诸如服务发现、流量控制、重试熔断、安全访问等,而这相关的网络控制功能就是集成在Dapr的Sidecar中,以对应用透明的方式集成进来的。整体的服务调用流程如下图所示:

PS:如果对Istio熟悉的同学需要注意,二者虽然都是通过Sidecar的模式进行网络控制,但二者是有有区别的。Dapr是以API的方式,而Istio是以代理的方式(不改变HTTP请求URI)。

2. State management(状态管理)

在进行微服务开发时,绕不开的话题就是服务间的状态共享、并发一致性问题。对于状态共享,你可能会说,各个服务连接到同一个Redis实例就OK了。是,但不得不考虑潜在的更新冲突的问题。Dapr 以更友好的HTTP API的方式进行状态的存储和读取,同时支持通过ETags进行并发控制,并支持通过选项设置并发和一致性行为。

  • 存储: POST http://localhost:<daprPort>/v1.0/state/<storename>
  • 读取: GET http://localhost:<daprPort>/v1.0/state/<storename>/<key>
  • 删除:DELETE http://localhost:<daprPort>/v1.0/state/<storename>/<key>

以下是保存状态的举例:

  • concurrency用于指定并发选项:first-write-wins/last-write-wins(以第一次写入为准/以最后一次写入为准),默认以最后一次写入为准。
  • consistency用于指定一致性选项:strong/eventual(强一致性/最终一致性),默认为最终一致性。
curl -X POST http://localhost:3500/v1.0/state/starwars \
-H "Content-Type: application/json" \
-d '[
{
"key": "weapon",
"value": "DeathStar",
"etag": "xxxxx",
"options": {
"concurrency": "first-write",
"consistency": "strong"
}
}
]'

目前支持使用Azure CosmosDB、 Azure SQL Server、 PostgreSQL,、AWS DynamoDB、Redis 作为状态存储介质。

3. Publish and subscribe(消息发布及订阅)

发布订阅模式,老生常谈了,主要是用于微服务间基于消息进行相互通信。你可能也会说,这也要拿出来说,我搞个RabbitMQ/RocketMQ就是了。是的,但我还是要说,Dapr提供了一致性的消息发布、订阅API,而无需关注具体使用的是何种Message Broker,从而和底层基础设施解耦。

  • 发布:POST http://localhost:<daprPort>/v1.0/publish/<pubsubname>/<topic>[?<metadata>]
  • 获取可订阅主题:GET http://localhost:<appPort>/dapr/subscribe
  • 订阅:POST http://localhost:<appPort>/<path>

4. Resource bindings and triggers (资源绑定及事件触发)

Dapr的Bindings与Azure Functions很类似,其是建立在事件驱动架构的基础之上的。通过建立触发器与资源的绑定,可以从任何外部源(例如数据库,队列,文件系统等)接收和发送事件,而无需借助消息队列,即可实现灵活的业务场景。Dapr的Bindings分为两种:

  1. Input Bindings(输入绑定):当外部资源的事件发生时,借助输入绑定,你的应用即可通过特定的API:POST http://localhost:<appPort>/<name>收到外部资源的事件,用于处理特定逻辑。
  2. Output Bindings(输出绑定):输出绑定允许你调用外部资源。比如,在订单处理场景中,在订单创建成功后,可以将订单信息通过Dapr的绑定API:POST/PUT http://localhost:<daprPort>/v1.0/bindings/<name>输出到Kafka特定队列上。

5. Actors

Dapr中的Actor模型,和Orleans的Virtual Actor一脉相传,之前写过一篇文章Orleans 知多少 | .NET Core 分布式框架介绍过。简单来讲:Actor模型 = 状态 + 行为 + 消息。一个应用/服务由多个Actor组成,每个Actor都是一个独立的运行单元,拥有隔离的运行空间,在隔离的空间内,其有独立的状态和行为,不被外界干预,Actor之间通过消息进行交互,而同一时刻,每个Actor只能被单个线程执行,这样既有效避免了数据共享和并发问题,又确保了应用的伸缩性。

Actor模型大大简化了并发编程的复杂度,Dapr在Actor运行时中提供了许多功能,包括并发控制,状态管理,生命周期管理如Actor的激活/停用以及用于唤醒Actor的Timer(计时器)和Reminder(提醒)。这些功能同样也是通过API的方式予以提供。

  • 调用Actor 方法:POST/GET/PUT/DELETE http://localhost:3500/v1.0/actors/<actorType>/<actorId>/method/<method>
  • 创建 Timer:POST/PUT http://localhost:3500/v1.0/actors/<actorType>/<actorId>/timers/<name>
  • 创建 Reminder:POST/PUT http://localhost:3500/v1.0/actors/<actorType>/<actorId>/reminders/<name>

6. Observability(遥测)

Dapr记录指标,日志,链路以调试和监视Dapr和用户应用的运行状况。 Dapr支持分布式跟踪,其使用W3C跟踪上下文标准和开放式遥测技术,可以轻松地诊断在生产环境中服务间的网络调用,并发送到不同的监视工具,如Prometheus。

7. Secrets(安全)

Dapr 提供了Secret管理,不过不同于K8S中的Secret,其支持与公有云和本地的Secret存储集成,以供应用检索使用。

What Can We Do With Dapr

了解了Dapr是什么,以及其提供的特性,那Dapr的应用场景就一目了然了。也就是官网首页的Slogan:Simplify cloud-native application development--Focus on your application’s core logic and keep your code simple and portable。

简化云原生应用的开发,确保应用专注于业务,并保证代码简单可移植。

因此,在考虑云原生应用开发的技术选型时,尽情尝试吧,目前在国内阿里云也已采用。

Last

在云原生如火如荼发展之际,Dapr V1.0 的正式发布,为开发者指明了云原生时代微服务的开发方向。相信Dapr 在未来的微服务架构选型中必将占有一席之地!

参考:

什么是分布式系统,如何学习分布式系统

Mecha:将Mesh进行到底

Dapr 知多少 | 分布式应用运行时的更多相关文章

  1. 乘风破浪,.Net Core遇见Dapr,为云原生而生的分布式应用运行时

    Dapr是一个由微软主导的云原生开源项目,国内云计算巨头阿里云也积极参与其中,2019年10月首次发布,到今年2月正式发布V1.0版本.在不到一年半的时间内,github star数达到了1.2万,超 ...

  2. 分布式应用运行时 Dapr 1.7 发布

    Dapr 是一个开源.可移植的.事件驱动的运行时,可以帮助开发人员构建在云和边缘上运行的弹性的.微服务的.无状态和有状态应用程序,并且关注于业务逻辑而不用考虑分布式相关的问题. 分布式相关的问题交给D ...

  3. java中的编译时与运行时

    ----?基础知识   -- 编译时 编译器将源代码翻译成机器能够读懂的代码,如java中就是翻译成jvm能够读懂的字节码文件.简单说,编译时就是机器帮我们检查代码是否有出现语法错误,关键字写错之类的 ...

  4. “ compiler-rt”运行时runtime库

    " compiler-rt"运行时runtime库 编译器-rt项目包括: Builtins-一个简单的库,提供了代码生成和其他运行时runtime组件所需的特定于目标的低级接口. ...

  5. runtime运行时

    /** * Describes the instance variables declared by a class. * * @param cls The class to inspect. * @ ...

  6. tomcat之一:指定tomcat运行时JDK版本

    tomcat作为日常开发的web应用服务器,给开发测试带来了很多便利,tomcat的运行依赖JDK的支持,在安装JDK时经常会配置环境变量:JAVA_HOME.CLASSPAT,且需要添加path变量 ...

  7. 【原】iOS动态性(五)一种可复用且解耦的用户统计实现(运行时Runtime)

    声明:本文是本人 编程小翁 原创,转载请注明. 为了达到更好的阅读效果,强烈建议跳转到这里查看文章. iOS动态性是我的关于iOS运行时的系列文章,由浅入深,从理论到实践.本文是第5篇.有兴趣可以看看 ...

  8. vs发布的程序不依赖运行时库msvcp100.dll

      [摘要:msvcr100.dll:MS Visual C Runtime 100 msvcp100.dll:MS Visual CPp 100 vs建立的工程,运转时库的范例有MD(MDd)战MT ...

  9. 无法启动调试。未安装Silverlight Developer运行时。最新运行时可以从以下地址下载: http://go.microsoft.com/fwlink/?LinkId=146060.

    无法启动调试.未安装Silverlight Developer运行时.最新运行时可以从以下地址下载: http://go.microsoft.com/fwlink/?LinkId=146060. 解决 ...

随机推荐

  1. 一块网卡配2IP地址

    我们知道在Linux下网卡被称为eth0,eth1,eth2.....,所有网卡的配置文件都存储在 /etc/sysconfig/network-script/下,文件名是以ifcfg-eth0,if ...

  2. Spring boot AOP 实现Redis 存储

    package com.carloan.common.web.annotation; import java.lang.annotation.*; /** * 自定义redis缓存注解.只要在serv ...

  3. PHP-文件、目录相关操作

    PHP-文件.目录相关操作 一  目录操作(Directory 函数允许获得关于目录及其内容的信息) 相关函数: 函数 描述 chdir() 改变当前的目录. chroot() 改变根目录. clos ...

  4. MySQL安全审计(init_connect)

    1.常规安全 在说审计之前我们先提一点一般我们常用的MySQL的安全注意事项. 指定完善的MySQL安全流程 用户授权邮件备注 每个人对应权限均需留底 所有用户非管理员及特殊账户,均精细化授权 2.s ...

  5. Commons Collections1分析

    0x01.基础知识铺垫 接下来这个过程将涉及到几个接口和类 1.LazyMap 我们通过下⾯这⾏代码对innerMap进⾏修饰,传出的outerMap即是修饰后的Map: Map outerMap = ...

  6. cassandra权威指南读书笔记--安全

    认证和授权driver,JMX和cassandra服务器支持SSL/TLS,cassandra节点间也支持SSL/TLS.密码认证器cassandra还支持自定义,可插拔的认证机制.默认的认证器:or ...

  7. 【xml】控件常用属性

    https://www.cnblogs.com/xqz0618/p/textview.html (常用,生动) https://www.jianshu.com/p/992324336dd9 (全,简洁 ...

  8. 牛客练习赛64 D【容斥+背包】

    牛客练习赛64 D.宝石装箱 Description \(n\)颗宝石装进\(n\)个箱子使得每个箱子中都有一颗宝石.第\(i\)颗宝石不能装入第\(a_i\)个箱子.求合法的装箱方案对\(99824 ...

  9. AtCoder Beginner Contest 188 E - Peddler (树)

    题意:有\(n\)个点,\(m\)条单向边,保证每条边的起点小于终点,每个点都有权值,找到联通的点的两个点的最大差值. 题解:因为题目说了起点小于终点,所以我们可以反向存边,然后维护连通边的前缀最小值 ...

  10. Panasonic Programming Contest (AtCoder Beginner Contest 186) E.Throne (数学,线性同余方程)

    题意:有围着一圈的\(N\)把椅子,其中有一个是冠位,你在离冠位顺时针\(S\)把椅子的位置,你每次可以顺时针走\(K\)个椅子,问最少要走多少次才能登上冠位,或者走不到冠位. 题解:这题和洛谷那个青 ...