最近在 HN 上看到了一个项目 Dapr 发布了 1.0 版本。我花了一点时间读了一下它的文档,觉得挺有趣的,所以用这篇博客来简单介绍一下它以及我对它的第一印象。

Dapr 是什么

Dapr (Distributed Application Runtime) 是一个运行时环境,以 sidecar 的形式和实际的应用程序一起执行。它让开发者可以专注于业务逻辑的开发。而分布式服务的其他常用组件(状态存储,pub/sub)则包含在运行时中,并且可以通过配置文件来一定的个性化。

Dapr 的核心思想

想象一个普通的服务。它为了实现业务逻辑,经常会依赖

  1. 数据库
  2. 消息队列

有经验的开发人员往往会通过封装的方式,根据核心业务来定义接口以隐藏实际的依赖选择(比如数据库选用了 MySQL,消息队列选用 Kafka)。业务逻辑在进程中调用这些接口,来实际使用这些依赖。

Dapr 进一步地推广了这个思路。Dapr 也对这些常见依赖进行抽象,只不过使用了 RPC 的方式,让不同的语言和进程都可以使用。我这样描述可能不够清晰,但是下面这张图一定能让你明白。

Dapr

抽象

为了帮助业务开发,Dapr 提供了很多种抽象,包括以下几种:

  1. statestore:用于持久化,提供了键值存储的抽象,支持常见的数据库,redis,等等。我不确定 dapr 怎么对复杂的查询进行支持。
  2. pub/sub:提供了 publishing 和 subscribing events 的抽象,支持 Kafka,RocketMQ 等等。
  3. binding:提供了对外部系统相应的抽象。比如一个 input binding 可以隐藏 subscribe kafka 这一细节,开发者只需要实现一个 API 来处理 input。Dapr 会负责调用这个 API。

服务调用

除了以上一种抽象,在分布式应用这种特定场景下,多个服务之间往往会有互相调用。随着这种互相调用越来越复杂,流量越来越大,我们往往需要服务发现,负载均衡等等。为此 Dapr 要求服务间的互相调用也需要通过 sidecar 提供的 API 执行。sidecar 根据请求数据,将其转发到对应的服务进程。

可观察性

由于服务之间的调用都需要通过 sidecar,所以实现可观察性非常自然,比如分布式 trace,接口调用监控等等。

总结

Dapr 的思想并不复杂,甚至让我觉得非常自然。它看上去似乎确实能够让业务开发简单很多,但是有一点我不太确定。虽然 dapr 对各种底层组件做了抽象,在应用中我们是不是也应该将 dapr 提供的抽象视作实现细节,比如将 dapr 提供的接口和 mysql 一视同仁。否则业务和底层细节就有了耦合。

按照目前我的理解,我感觉我们的业务逻辑还是应该和 dapr 隔离开,不要让 dapr 侵入到我们的代码中。在下一篇博客里(如果有的话),我可以试着用一个具体的例子来说明我的想法。