Dapr 能否取代 Spring Cloud?

Dapr 和 Spring Cloud 的区别

很多人都是使用 Spring Boot 和 Spring Cloud 来开发微服务。Dapr 也是开发微服务的框架,它和 Spring Cloud 有什么区别呢,其实这不是一个区别的问题,它是不同的时代需要不同的框架。

Spring Cloud 是一种产品,提供了分布式应用程序所需的所有要素,包括服务发现、消息传递/流处理、分布式跟踪、 以易于处理的形式从 SpringBoot 提供功能, 到目前为止,可能没有其他产品比 Spring Cloud 更易于使用。Spring Cloud 并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 Spring Boot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

Spring Cloud 是分布式应用程序开发中的重要产品,足以影响语言选择。假如你想使用 Java 以外的语言开发微服务,比如 golang,你想用 Spring Cloud + Spring Boot,最终还是选择了使用 Java。

Dapr 的出现是分布式应用程序开发中拥有了语言无关的微服务开发,Dapr 足以替代 Spring Cloud 成为云原生分布式应用开发的选择。熟悉 Azure 的人可能会觉得它其实更像是 Service Fabric 的加强版。

我们将 Spring Cloud 提供的组件与 Dapr 的构建块作一些横向对比:
dc42468eefc5d7bc0ef8725450c1ae0d.png
总的来说无论是 Dapr 还是 Spring Cloud 上述这些项目,都是想帮助开发人员简单快速地构建分布式应用。但是由于时代背景的原因,它们的出发点、实现形式又存在一些差异。

我们从分布式应用程序的三大支柱性功能来比较一下 Dapr 和 Spring Cloud:

  • 服务调用

  • 传递异步消息

  • 分布式追踪

1. 服务调用

首先,比较从应用程序调用另一个应用程序的功能。

Dapr 的调用使用InvokeAPI

源代码如下所示:

@Value("${baseUrl}")private String baseUrl;@GetMapping("/invokeHello")public Map<String, ?> invokeHello() {Map<?, ?> result = restTemplate.getForObject(baseUrl + "/hello", Map.class);return Map.of("baseUrl", baseUrl, "remoteMessage", result);}

baseUrl 可以通过为 Dapr 指定调用 API 的值来通过 Dapr 调用目标应用程序。

http://localhost:${DAPR_HTTP_PORT}/v1.0/invoke/hello-app/method

Dapr 在本地环境中使用 mDNS(多播DNS)从应用程序名称中查找目标服务运行的主机,而 k8s 使用 k8s 本身的名称解析功能(CoreDNS)。在两者都不可用的环境中,您当前必须使用 Consul。

除此之外,Dapr 的优势在于它基本上可以做到开箱即用。

Spring Cloud 服务发现

Spring Cloud 使用 Netflix Eureka 进行名称解析,它具有 Eureka 服务器(等效于上述内容)作为名称解析的服务器,每个应用程序都使用 Netflix 客户端向 Eureka 服务器注册自己,并用它来构建客户端来解决自己的主机。服务注册表非常有用,因为它允许客户端负载平衡,并将服务提供商与使用者隔离开来,而无需 DNS。

  • 服务器端 Eureka 服务器代码如下所示:

@EnableEurekaServer@SpringBootApplicationpublic class ServiceRegistrationAndDiscoveryServiceApplication {public static void main(String[] args) {SpringApplication.run(ServiceRegistrationAndDiscoveryServiceApplication.class, args);}}

只需启动具有注释 @EnableEurekaServer 的应用程序。当然,您可以添加配置文件以进行精细设置或组合群集。

  • Netflix 客户端源代码如下所示:

@Value("${baseUrl}")private String baseUrl;@GetMapping("/invokeHello")public Map<String, ?> invokeHello() {Map<?, ?> result = restTemplate.getForObject(baseUrl + "/hello", Map.class);return Map.of("baseUrl", baseUrl, "remoteMessage", result);}

与 Dapr 端的源代码相同。

baseUrl 只要指定了应用程序名称 ,RestTemplate 就会使用 Eureka 发现客户端自动访问该应用程序。简单地说,它比使用 Dapr 更容易理解。

异构服务通信

传统分布式中间件往往锁定某个语言,比如 Java 体系通常会使用 Feign 或者 Dubbo 实现,但它们并没有提供其他语言的库。

因此如果是多语言的环境,那么就需要基于某种通用协议如 REST 或者 GRPC 进行通信,可能还会需要额外的注册中心和负载均衡器。

当然,现实中的情况往往要比这复杂的多,并且考虑到会引入额外的中间件,带来的运维方面的成本也需要慎重考虑。

Dapr 提供了多语言的 SDK,如 .NET、Java、Go、Rust、Python、PHP 等,可以 使用 HTTP 或者 GRPC 的方式进行异构服务间的调用,能很好地解决这个问题。

Dapr 和 Spring Cloud 的服务调用哪个更好?

虽然 Dapr 不需要单独的 DNS,但它更易于使用,但 Spring Cloud 需要在本地环境中建立Eureka 服务器。当然它不是那么难建立,所以不能说这是一个缺点。

此外,调用时的 URL 在 Spring Cloud 中更易于理解,而 Dapr 的调用 API 会很长。当然这不是一个很大的缺点。

Dapr 和 Spring Cloud 各有千秋,但是在 Kubernetes 环境下,Dapr 直接就利用了Kubernetes 的 Service ,更加贴合云原生环境,异构服务通信的支持更好。

2.传递异步消息

Dapr 的 Pus/sub API

Dapr 使用消息传递的 Pub/sub API 发送消息,只需创建订阅配置文件和 Web API 即可接收消息,采用标准的 CloudEvents 格式。

发送消息的源代码如下所示:

@Value("${pubsubUrl}")private String pubsubUrl;@PostMapping("/publish")public void publish(@RequestBody MyMessage message) {restTemplate.postForObject(pubsubUrl, message, Void.class);}

您可以通过指定名为 pubsubUrl 的大写 Pub/sub API 向消息代理发送消息。

http://localhost:${DAPR_HTTP_PORT}/v1.0/publish/rabbitmq-pubsub/my-message

然后是接收消息的源代码。它看起来像这样:

@PostMapping("/subscribe")public void subscribe(@RequestBody CloudEvent<MyMessage> cloudEventMessage) {System.out.println("subscriber is called");System.out.println(message);}

只需创建一个 Web API 来接收消息。若要利用此 Web API,请创建类似于以下内容的配置文件:

apiVersion: dapr.io/v1alpha1
kind: Subscription
metadata:name: subscription
spec:pubsubname: rabbitmq-pubsubtopic: my-messageroute: /subscribe
scopes:
- subscribe-app
  • metadata.name 值不是特别可用,因此您可以为其指定任何名称。

  • pubsubname 是 pubsub 的名称。使用默认情况下设置的 pubsub。

  • topic 是消息主题。此处指定了发布端应用程序中指定的 my-message。

  • route 是要调用的 Web 应用程序的路径。因为它正在等待的路径SubscribeController/subscribe

  • scopes 是正在等待的应用程序的应用 id。这一次,我将启动一个应用程序(应用程序的应用程序,称为子脚本端的应用程序),所以我指定它 subscribe-app。

如果在此处列出多个应用程序的 app-id,则多个应用程序可以接收相同的消息。

GitHub 示例代码将此文件放在中。如果要使用它,请将其复制到用户指令。

subscribe/.dapr/components/subscription.yaml

Spring Cloud Stream

使用 spring cloud stream 向 cloud 发布信。

在 spring cloud stream 2.x 到 3.x 之间,API 发生了重大变化,现在更特定于流处理。在这里,我将介绍 3.x 版本。

发送消息一方的源代码:

@PostMapping("/publish")public void publish(@RequestBody MyMessage message) {streamBridge.send("my-message-0", message);}

使用类StreamBridge发送消息。

此外,在配置文件中写入要发送到源代码中指定消息的键的消息代理。

spring.cloud.stream.bindings.my-message-0.destination=my-message

此处指定的值用作 RabbitMQ 交换的名称。

然后是接收消息的源代码。

@Beanpublic Consumer<MyMessage> subscribe() {return (map) -> {System.out.println("subscriber is called");System.out.println(map);};}

使用包 java.util.funciton 的 Consumer 和 Function 来实现 ,而不是像 Dapr 这样的标准的 Web API。

然后,创建一个配置文件,以便在收到消息时调用此方法 (Bean)。

spring.cloud.stream.bindings.subscribe-in-0.destination=my-messagespring.cloud.stream.bindings.subscribe-in-0.group=my-message-subscribe

上面的值用作 Exchange 的名称,下面的值用作队列的名称。设置中有一些问题就是很难理解。

然而,有一种令人信服的感觉是,将子脚本端视为 “函数” ,而不是 “API” 并实现它。您可能从未阅读过此版本的 Spring Cloud Stream 的源代码,因此您可能已经将多个调用合并到 WebFlux 的非阻塞中,而不是逐个从消息代理接收和处理消息。这有性能优势。

Dapr 提供了一些基础服务的抽象接口,以消息中间件为例,Dapr 支持以下中间件的 Pub/Sub:

ccea7481f719bf8c762d553898bb4e30.png
用 Dapr 抽象接口来使用基础服务能力的好处是———当你需要更换中间件的时候,可以少动点代码,换句话也可以说是增加了服务的可移植性,在熬小剑的文章里也有相关描述。

Dapr 使用 HTTP 进行消息传递,内部的通信通过 GRPC 进行传递,但 Spring Cloud Stream 使用自己的类进行消息传递。因此,虽然 Dapr 在测试时更容易替换为另一个进程,并使用 curl 命令进行测试。

Dapr 在可操作性方面会更好。

3.分布式追踪

Dapr 的分布式追踪支持

在 Dapr 中,只需编写配置文件即可启用分布式追踪。

配置文件有以下内容。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:name: daprConfig
spec:tracing:samplingRate: "1"zipkin:endpointAddress: http://localhost:9411/api/v2/spans

只需指定分布式跟踪的采样率和 Zipkin 服务器的地址即可启用分布式追踪。

但是,您必须自己传播跟踪 ID,因此您需要编写如下代码:

@GetMapping("/invokeHello")public Map<String, ?> invokeHello(@RequestHeader("traceparent") String traceparent) {HttpHeaders httpHeaders = new HttpHeaders();httpHeaders.set("traceparent", traceparent);HttpEntity<?> request = new HttpEntity<>(httpHeaders);Map<?, ?> result = restTemplate.exchange(helloUrl + "/hello", HttpMethod.GET, request, Map.class).getBody();return Map.of("baseUrl", helloUrl, "remoteMessage", result);}

在 HTTP 标头中接收到的标头值 traceparent 将传递给下一个请求的 HTTP 标头。

Spring Cloud Sleuth

使用 Spring Cloud Sleuth 在 Spring Cloud 中进行分布式追踪。

将 Spring Cloud Sleuth 添加到依赖项并创建配置文件,如下所示:

spring.sleuth.sampler.rate=100spring.zipkin.sender.type=webspring.zipkin.baseUrl=http://localhost:9411

使用此设置,将启用分布式追踪并将追踪信息发送到 Zipkin。

分布式追踪涵盖了从与 RestTemplate 和 WebClient 的 HTTP 通信、与 Spring Cloud Stream 的消息传递等所有内容,并且还自动传播 Dapr 存在问题的跟踪 ID。

分布式追踪上 Dapr 不需要修改应用,通过配置就可以轻松的调整。

综合比较

到目前为止,我们已经比较了 Dapr 和 Spring Cloud 的三个功能,但总的来说,哪个更好?

Dapr 在清晰性和通过 HTTP 的松耦合方面具有优势,另外,不仅考虑到这三个功能,还考虑到其他功能,或者世界信息量的差异,可以说 Dapr 更胜一筹。

与版本升级相关的痛苦

那么我为什么不选择 Spring Cloud 而选择 Dapr 呢?有个重要因素是 “版本兼容性和版本升级问题” 。

例如,如果您的系统运行旧版本的 Java 和 Spring Boot,并且您尝试在新系统上使用更新版本的 Java 和 Spring Boot 进行开发,如果您尝试在每个系统上使用 Spring Cloud,每个 Spring Boot 由于对应的 Spring Cloud 版本不同,有时会失去兼容性。比如随着 Spring Cloud 的版本升级,内部使用的 Eureka 版本升级时协议发生了变化,如前所述,Spring Cloud Stream 是 2.x 中 了API 终端。

如果是这样,最好继续更新 Java 、 Spring Boot 和 Spring Cloud 到最新版本。但是,Spring Cloud 往往是有与版本升级相关的大型工作。

这是因为 Cloud Native 这个领域对应的产品和趋势都发生了变化,Spring Cloud 试图跟风的时候,不得不失去兼容性。

另外,作为一个稍微小一点的问题,如果由于Spring Boot 的提供速度和 Spring Cloud 的提供速度不同,以及依赖的复杂度等原因,尝试升级 Spring Boot 的版本,Spring Cloud 还不支持有时候引用库的版本不一样,会报错。

通过体验这方面的痛苦,而不是 Spring Cloud 不好,“与提供 Web API 的应用程序和支持它的基础设施接壤的层更加松散耦合,并且每个版本都是独立的。最好能够上传吧。”

这就是它被用于 Dapr 而不是 Spring Cloud 的原因。

总结

  • 在服务调用方面,Dapr 和 Spring Cloud 变化不大。

  • 在消息传递方面,Dapr 更简单,并具有更好的性能。

  • 对于分布式跟踪,Spring Cloud 比 Dapr 更复杂、更易于使用。

Spring Cloud 版本升级让你吃不少苦头,有点难以理解 Spring Cloud 文档在哪里以及是什么,随着具有各种功能的历史产品变得更加复杂,文档可能会变得更加复杂。当然,Spring 的好处是有许多指南、博客、Demo 材料等作为该领域的补充。

Spring Cloud 这样的微服务框架,把微服务架构上的很多东西也带到了代码开发上来。虽然 Spring Cloud 做了封装和简化,但开发的时候你还是会分心去处理它,不能完全只关注业务。 Dapr 是微服务的发展方向,它简化微服务的开发,把微服务架构方面的东西都剥离出来成为基础设施,开发只需关注具体的业务实现。

所以 Mecha 架构的 Dapr 完全可以取代 Spring Cloud。而且具备更多优势:

  • 更加云原生,和 Kubernetes 结合更好。

  • 业务代码无需集成 SDK,这样决定了 SDK 升级会更加方便,降低了耦合。

Dapr 通过把一些构建微服务应用所需的最佳实践内置到开放、独立的 Building Block 中,Dapr 还在 Actor 运行时中提供了许多功能,包括并发控制,状态管理,生命周期管理如 Actor 的激活/停用以及用于唤醒 Actor 的 Timer(计时器) 和Reminder(提醒)。Dapr 让开发人员更加专注于业务逻辑代码的编写,即可开发出功能强大的微服务应用。

更为重要的是,Dapr 还抽象了运行环境,避免微服务应用和运行环境强绑定(这也是很多团队“假上云” —— 仅使用VM的原因之一)。并且支撑 Dapr 的运行环境不仅仅限于 Cloud,还有广阔的 Edge。

参考文章:

  • https://xie.infoq.cn/article/aa422c431873fc7b1de3591e1

  • https://xie.infoq.cn/article/047e1ece428ef11350f7a129c

  • https://www.infoq.cn/article/ex3rr5jCByXOCX7mwJbu

  • https://xie.infoq.cn/article/7308df260ebbf5995a1401115

  • https://github.com/dapr/dapr/blob/master/docs/decision_records/sdk/SDK-002-java-jdk-versions.md

  • 通过 K8s 自带技能卸下 SpringCloud 依赖

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288688.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Start vm by command line

为什么80%的码农都做不了架构师&#xff1f;>>> VBoxHeadless -startvm "dcsvr08" 转载于:https://my.oschina.net/kut/blog/1501095

php之生成器

引用手册&#xff1a;一个生成器函数看起来像一个普通的函数&#xff0c;不同的是普通函数返回一个值&#xff0c;而一个生成器可以yield生成许多它所需要的值。当一个生成器被调用的时候&#xff0c;它返回一个可以被遍历的对象.当你遍历这个对象的时候(例如通过一个foreach循…

使用JDBC进行数据库的事务操作(2)

本篇将讲诉如何使用JDBC进行数据库有关事务的操作。在上一篇博客中已经介绍了事务的概念&#xff0c;和在MySQL命令行窗口进行开启事务&#xff0c;提交事务以及回滚事务的操作。 似乎事务和批处理都可以一次同时执行多条SQL命令&#xff0c;但是事务是如果某一条SQL出错&#…

谷歌浏览器之如何快速找到js、css等文件

1 问题 我们分析前端代码的时候&#xff0c;需要快速定位某个js文件&#xff0c;然后查看里面的源代码 2 具体操作 比如我在www.baidu.com这个页面&#xff0c;我们先按下F12, 然后点击到network,然后我们再用快捷键 ctrl p 比如我们要找tu_d03f361.js 效果如下&#x…

HTML5 播放器

随着 HTML5 的普及&#xff0c;越来越多视频网站使用 <video></video> 标签播放直播、点播内容&#xff08;如下图所示&#xff09;。使用 <video> 的好处&#xff0c;主要以下两点。 可以直接在页面中播放&#xff0c;也就是所谓的“区域播放”&#xff0c;…

linux shell之控制台打印各种颜色字体和背景

1 问题 控制台打印各种颜色字体和背景 字体颜色 #30:黑 #31:红 #32:绿 #33:黄 #34:蓝色 #35:紫色 #36:深绿 #37:白色 背景颜色 #40:黑 #41:深红 #42:绿 #43:黄色 #44:蓝色 #45:紫色 #46:深绿 #47:白色 echo -e "\e[43;35m chenyu\e[0m hello word&quo…

修改GIT的user.name和user.email

为什么80%的码农都做不了架构师&#xff1f;>>> $ git config --global --replace-all user.email "输入你的邮箱" $ git config --global --replace-all user.name "输入你的用户名" ----验证是否修改成功---- $ git config --list 转载…

sql distinct 去重复 (mysql)

DISTINCT 去重复 &#xff08;运动扭伤腰。。。悲伤。。。 (▼ _ ▼) &#xff09; 首先&#xff0c;例如我们的表&#xff1a; 首先观察表&#xff1a; 其中第二行和第三行和第八行的name1的只是重复的&#xff0c;但第八行的age1确是12&#xff0c;与第二行和第三行不同…

如何5分钟上手使用OCR

随便打开一个Microsoft Visual Studio&#xff0c;新建一个WinForms项目&#xff0c;从下面列表中随便选择一个NET框架。net35;net40;net45;net451;net452;net46;net461;net462;net47;net471;net472;net48; netstandard2.0;netcoreapp3.1; net5.0;net6.0;创建完窗口后&#xff…

利用Excel VBA批量计算气象数据多个台站多年来春季和冬季降水量和平均气温

气象数据是地理数据的重要组成部分,存储量虽然不大,但是处理过程非常繁琐,长时序数据更不用说。本文总结了一个气象数据的基本处理方法。 如下图所示,气象数据的排列格式是区站号→年→月→降水量→平均气温,时间范围为1983~2012年,每一年都有台站数300多个,下面按区站…

VMware Workstation 12新建虚拟机

1、点击“创建新的虚拟机”2、选择“自定义”(初学选择典型也可以)&#xff0c;下一步3、默认&#xff0c;直接下一步4、通常都是先创建虚拟机&#xff0c;等虚拟机创建完成后再来安装操作系统&#xff0c;若安装过程出现什么问题方便解决&#xff0c;故选择“稍后安装操作系统…

sql count用法_SQL学习笔记3:count(*)函数

1.count(*)函数用法COUNT(*) 函数返回表中的记录数&#xff0c;具体来说&#xff0c;返回值是一个数字。语法&#xff1a;返回表中所有记录的数量&#xff1a;SELECT COUNT(*) FROM table_name返回表中满足一定条件的记录的数量&#xff1a;SELECT COUNT(*) FROM table_name WH…

sql order by,desc和limit使用(mysql)

(&#xff61;ŏ_ŏ) 首先我们来看一个表&#xff1a; 在此我们要进行排序&#xff0c;按降序排序&#xff0c;就是从大到小。然后我们只要查询前2条数据。 意思就是我们需要把这个表从大到小排序后&#xff0c;取前两条&#xff0c;那么我们就需要使用到order by 和desc …

Blazor University (13)组件 — 多线程渲染

原文链接&#xff1a;https://blazor-university.com/components/multi-threaded-rendering/多线程渲染由于 Blazor Server 应用程序中可用的线程不止一个&#xff0c;因此完全有可能不同的组件可以让不同的线程在其上执行代码。这在基于异步任务的操作中最常见。例如&#xff…

sql 之like 和通配符%,_(mysql)

(&#xff61;ŏ_ŏ) like模糊查询&#xff0c;啥叫模糊查询&#xff1f; 例如&#xff1a;我们一个数据库里面存在在一个人叫做李二三四。我们忘记了他的名字&#xff0c;只记得他的姓名&#xff0c;那么我们就可以使用like加上通配符来查询出我们所要的结果&#xff1b;话说…

php邮件代码c语言,C语言实现邮件发送功能(SMTP)源码

【实例简介】C 语言编写的邮件发送器是SMTP协议的源代码和EXE执行程序均在里面使用VS2013开发环境生成&#xff0c;填写对应参数即可成功进行邮件发送&#xff0c;不用配置邮件服务器&#xff0c;只需一个支持SMTP协议的邮箱账号密码即可【实例截图】【核心代码】#include #inc…

【线性筛】【质因数分解】【约数个数定理】hdu6069 Counting Divisors

d(x)表示x的约数个数&#xff0c;让你求&#xff08;l,r<10^12,r-l<10^6,k<10^7&#xff09; #include<cstdio> using namespace std; #define MOD 998244353ll #define MAXP 1000100 typedef long long ll; ll x,y; int T,K; bool isNotPrime[MAXP10]; int num…

C#/.Net 不要再使用Aspose和iTextSharp啦!QuestPDF操作生成PDF更快更高效!

QuestPDFQuestPDF是一个开源的工具库&#xff0c;可以在.NET或者.Net Core中生成pdf文档它提供了一个布局引擎&#xff0c;设计时考虑到了完整的分页支持以及灵活性要求&#xff01;比市面上常见的Aspose和iTextSharp好用太多了&#xff01;GitHub地址安装Install-Package Ques…

C#创建桌面快捷方式

1、添加引用Windows Script Host Object Model,并引用命名空间using IWshRuntimeLibrary; 2、代码 using System; using IWshRuntimeLibrary; using System.Windows.Forms;namespace WindowsFormsApplication1 {public partial class Form1 : Form{public Form1(){InitializeC…