谈谈对 Dapr 的一些感想
早在今年 4 月份的时候,就在 Github 的 Trending 榜上看到了 Dapr,当时就对它留下了很深刻的印象。
后来由于工作原因,也只是偶尔关注一下 Dapr 的开发进展,没能持续跟进。最近正好有那么点时间,于是就打算记录一下自己对 Dapr 的一些心得体会。
如有不足之处,欢迎指出。
Dapr 的定位
根据官方文档的介绍,Dapr 是一个可移植的、事件驱动的运行时,能够帮助开发人员轻松构建弹性、无状态和有状态的应用程序。
它包含了以下的构建块:
服务间调用
状态管理
发布和订阅
资源绑定
Actor
可观察性
秘钥管理
Dapr 提供了多语言的客户端以使用其能力,并以sidecar的形式工作,如下图所示,在dapr-go-example
中有两个容器,其中名为daprd
的容器就是 dapr 注入的 sidecar:
在我看来,Dapr 的定位就是一个云原生时代的分布式服务构建框架,熟悉 Azure 的人可能会觉得它其实更像是Service Fabric的加强版,也可以与 Java 生态的Spring Cloud
、MicroProfile
,Go 生态的kit
、go-micro
等等做类比。
以Spring Cloud
为例,我们将它提供的组件与 Dapr 的构建块作一些横向对比:
总的来说无论是 Dapr 还是上述这些项目,都是想帮助开发人员简单快速地构建分布式应用。但是由于时代背景的原因,它们的出发点、实现形式和 Dapr 又存在一些差异,下文会作一些详细的讨论。
Dapr 主要帮助解决什么问题
异构服务通信
传统分布式中间件往往锁定某个语言,比如 Java 体系通常会使用Feign
或者Dubbo
实现,但它们并没有提供其他语言的库。
因此如果是多语言的环境,那么就需要基于某种通用协议如REST
或者GRPC
进行通信,可能还会需要额外的注册中心和负载均衡器,如下图所示是一个简单的实现思路:
当然,现实中的情况往往要比这复杂的多,并且考虑到会引入额外的中间件,带来的运维方面的成本也需要慎重考虑。
Dapr 提供了多语言的SDK,如 Java、Go、Python、PHP 等,可以使用 HTTP 或者 GRPC 的方式进行异构服务间的调用,能很好地解决这个问题。
基础服务的抽象接口
Dapr 提供了一些基础服务的抽象接口,以消息中间件为例,Dapr支持以下中间件的Pub/Sub:
用 Dapr 抽象接口来使用基础服务能力的好处是————当你需要更换中间件的时候,可以少动点代码,换句话也可以说是增加了服务的可移植性,在熬小剑的文章里也有相关描述。
关于是否应该使用 Dapr 的权衡
上面说了使用 Dapr 的好处,但是软件架构始终是关于权衡的,Dapr 也并非是万能良药。
运行环境
首先是 Dapr 的运行环境,尽管它支持在本地运行(Docker 和非 Docker 的slim-init ),但对于生产环境这肯定不是一个好的做法,其中一个很重要的原因是 Dapr 控制平面是高可用问题,也会失去 Dapr 与 AKS、EKS、GKE 的良好集成能力。因此如果你的团队还没有迁移到 Kubernetes 上,或者并没有在 Dapr 官方已经提供了集成的托管集群上,建议将这个因素纳入考量范围。
异构服务通信
提供异构服务的通信能力是 Dapr 的主要能力之一,但如果你非常确定在可预见的很长一段时间内都不会出现多语言环境,那就需要好好衡量下了。
传统的中间件固然有其局限性,但是它们也确实提供了非常完善的功能,这是新生的 Dapr 所不具备的。
抽象接口
Dapr 提供的抽象接口固然能为服务提供良好的可移植性,但前提是你没有大量使用特定于某个中间件产品的能力。比如当你使用Hazelcast
或者Ignite
做了大量的近距缓存时,Dapr 可能并不能帮你增加应用的可移植性,因为它只提供一些所有同类中间件都具备的基本功能接口。
迁移成本
对于过去已经在项目中大量采用传统分布式框架的情况,迁移成本可能会是一个不大但也不小的问题,因为至少你需要替换掉服务间调用的代码。
Dapr 提供的 SDK
目前来看,Dapr 的 SDK 已经能够覆盖到几个主流语言了,但仍然有不在支持列表内的或者正在开发中的,比如 C++、Rust、Javascript 目前就还没有那么完善:
\
版权声明: 本文为 InfoQ 作者【LLLLimbo】的原创文章。
原文链接:【http://xie.infoq.cn/article/aa422c431873fc7b1de3591e1】。文章转载请联系作者。
评论