Dapr 和 Spring Cloud 对比分析

5912bfdf6771eb2ee94971e9028a0edf.png

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

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

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

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

我们将Spring Cloud提供的组件与 Dapr 的构建块作一些横向对比:

063a72a44fd13c7160395cce25539e72.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本身的名称解析功能。在两者都不可用的环境中,您当前必须使用 Consul。

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

Spring Cloud 服务发现

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

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

@EnableEurekaServer

@SpringBootApplication

public class ServiceRegistrationAndDiscoveryServiceApplication {

public static void main(String[] args) {

SpringApplication.run(ServiceRegistrationAndDiscoveryServiceApplication.class, args);

}

}

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

客户端源代码如下所示:

@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、Python、PHP 等,可以使用 HTTP 或者 GRPC 的方式进行异构服务间的调用,能很好地解决这个问题。

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

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

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

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

  1. 传递异步消息

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-pubsub

topic: my-message

route: /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 交换的名称。

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

@Bean

public 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-message

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

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

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

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

145abcd0e02c98f59bd355b73aaa5f2c.png

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

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

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

  1. 分布式追踪

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=100

spring.zipkin.sender.type=web

spring.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。

Dapr的设计哲学是集成,而不是替代,Spring Cloud 也可以用Dapr 进行改良变成一个更好的Spring Cloud,dapr sidecar扮演一个类似netflex oss的角色,你可以把dapr Java sdk和dapr sidecar绑起来当成是一种spring cloud实现。

参考文章:

  • 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依赖

54bf2b215e3cbe1899e6cba08a894108.png

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

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

相关文章

【C语言简单说】七:自定义函数(2)

刚刚说了如何自定义函数。那只是最简单的形式&#xff0c;那我们现在开始来说函数的返回值。我们先贴上之前的代码&#xff1a; #include<stdio.h> #include<stdlib.h> //头文件下面 void dy(){printf("这里是dy函数\n");} //main函数上面 int main() …

jdk源码分析书籍 pdf_什么?Spring5 AOP 默认使用Cglib?从现象到源码深度分析

推荐阅读&#xff1a;阿里工作十年拿下P8&#xff0c;多亏了这些PDF陪我成长&#xff08;Spring全家桶源码解析Redis实战等&#xff09;​zhuanlan.zhihu.com从入门到熟悉&#xff0c;一步一步带你了解 MySQL 中的「索引」和「锁」​zhuanlan.zhihu.comSpring5 AOP 默认使用 Cg…

Nginx monitor

为什么80%的码农都做不了架构师&#xff1f;>>> 最近在初步研究了一下nginx的监控&#xff0c;主要是想监控一些和业务相关的信息&#xff0c;发现能用的方案不多&#xff0c;主要有如下&#xff1a; 1 监控解析nginx log&#xff1a;ngxtop 官方的解释是可以…

ASP.NET 6 中间件系列 - 执行顺序

这篇文章是 ASP.NET 6 中间件系列文章的第 3 部分&#xff0c;你还可以阅读第1部分和第2部分。我们通过中间件创建的管道是有执行顺序的&#xff0c;执行顺序与中间件的添加顺序是相同的&#xff0c;接下来我们讨论一下为什么要有执行顺序&#xff0c;以及它的重要性。示例项目…

OSChina 周四乱弹 ——程序员怎么撩外国妹子攻略

2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单&#xff08;2017&#xff09;请戳&#xff08;这里&#xff09; 【今日歌曲】 冬天之雪 &#xff1a;听歌听到苏菲玛索和刘欢演唱《玫瑰人生》。有网友评论&#xff1a;法语专业的刘欢老师等的就是这一刻。…

【C语言简单说】七:自定义函数(3)

前一节说了返回值的内容&#xff0c;那么这一节就说一下参数的内容 手打码了几章内容了。。。。困。&#xff3e;(&#xffe3;&#xff09;&#xffe3;)《(&#xffe3;&#xff09;&#xffe3;)&#xff3e;困.困.困. 相比看过前一节的知道我说自定义函数如果你要做一个运…

WireShare抓包在ssl协议里面提示(Level: Fatal, Description: Protocol Version)

1 问题 在后台访问部分链接的时候抓包&#xff0c;客户端发了client hello包&#xff0c;但是没有收到Server hello包&#xff0c; 提示&#xff1a;Alert(Level: Fatal, Description: Handshake Failure ) 包文如下 2 解决办法 是因为客户端的ssl协议版本和链接地址环境ss…

对于 APM 用户的一次真实调查分析(下)

一.前言 对 APM 用户的一次真实调查分析&#xff08;上&#xff09;中&#xff0c;我们主要聊到了现阶段国外 APM 行业对各个企业的渗透率、大部分使用 APM 工具的企业规模以及 APM 工具在用户心中的地位等问题&#xff0c;有兴趣的朋友可以点击链接观看。 我们本次继续顺着这个…

linux cpu核数查看_Linux日常必备的 8 个小技能

身为一个码农&#xff0c;日常工作中与我们打交道次数较多的操作系统除了Windows和Mac OS 之外&#xff0c;还有一个就是 Linux。今天偶尔有空翻越了之前码代码时期汇总的一些小技巧发现挺实用的&#xff0c;故分享给大家&#xff0c;希望能对大伙有一定的帮助。1. 如何查看系统…

NotificationManagerService使用详解与原理分析(一)

概况 Android在4.3的版本中(即API 18)加入了NotificationListenerService&#xff0c;根据SDK的描述(AndroidDeveloper)可以知道&#xff0c;当系统收到新的通知或者通知被删除时&#xff0c;会触发NotificationListenerService的回调方法。同时在Android 4.4 中新增了Notifica…

【C语言简单说】八:分支结构之if(1)

今天貌似更了很多章了&#xff0c;现在感觉累觉不爱。。。 ┐(—__—)┌ 你说我有啥米办法咧~&#xff08;要不叫别人替我更一下&#xff1f;&#xff09; 继续更。。。 这一节我们来说一下if语句&#xff1b;这个东西可是很常用的呀&#xff1b;在此之前我们来举个例子&…

ASP.NET 6 中间件系列 - 自定义中间件类

这篇文章是 ASP.NET 6 中间件系列文章的第2部分&#xff0c;点击这里可以阅读第1部分。在上一篇文章中&#xff0c;我们讨论了什么是中间件&#xff0c;它的作用是什么&#xff0c;以及在 ASP.NET 6 应用管道中添加中间件的简单方法。在这篇文章中&#xff0c;我们将在这些基础…

如何在IE浏览器里面定位到关键字的位置(页面代码)和这个关键字位置模块的请求

1 问题 比如用IE浏览器,打开一个页面,如何定位到关键字的具体位置,以及这个位置请求是什么?可能这个请求不是主页面的请求,因为我们知道页面html里面可以嵌套很多Frame(框架),把页面分割成很多块,然而每个Frame(框架)里面可以再嵌套一个url,有时候我们需要找到这个请求…

Java并发编程-原子性变量

image.png1. 原子性布尔 AtomicBoolean AtomicBoolean 类为我们提供了一个可以用原子方式进行读和写的布尔值&#xff0c;它还拥有一些先进的原子性操作&#xff0c;比如 compareAndSet()。AtomicBoolean 类位于 java.util.concurrent.atomic 包&#xff0c;完整类名是为 java.…

【C语言简单说】八:分支结构之if...else...(2)

上一节我们说了if的基本用法&#xff0c;这一小节我们来说明if…else…的用法 首先惯例举例子&#xff1a; 你今天早上饿了&#xff0c;打算去吃包子&#xff0c;可是没有包子了&#xff0c;你打算去吃米粉。 你昨天早上下雨了&#xff0c;带伞出门&#xff0c;结果没找到&a…

Java集合之LinkedList

上一篇写的是ArrayList&#xff0c;这一篇写一下LinkedList. 开宗明义&#xff0c;因为Vector已经被废弃了&#xff0c;所以list家族只剩下ArrayList和LinkedList两兄弟了&#xff0c;这里直接对比一下二位&#xff1a; ArrayList基于动态数组的实现&#xff0c;它长于随机访问…

由于开发者通过接口修改了菜单配置_Android SDK开发艺术探索(四)个性化配置...

一、前言本篇是Android SDK开发艺术探索系列的第四篇文章。介绍了通过流式API设计思想优雅地实现SDK的自定义选项配置需求。目录概览&#xff1a;一、前言 二、SDK自定义配置2.1、什么是自定义配置2.2、设计一个配置方法 三、结语系列文章&#xff1a;Android SDK开发艺术探索&…

C#中切片语法糖的使用

例子首先我们看这样一个例子&#xff0c;有这样一个数组string [] lst new string[] { "1", "2", "3", "4", "5", "6", "7" };我们怎么获取它的最后一个值&#xff0c; 传统方法是这样写的&#xff0c…

JavaScript 语言基础知识点总结(思维导图)

1.JavaScript数组 2.JavaScript 函数基础 3.Javascript 运算符 4.JavaScript 流程控制 5.JavaScript 正则表达式 6.JavaScript 变量 7.JavaScript 字符串函数 8.DOM 基本操作 制作工具&#xff1a;Mindjet MindManager 文章摘自&#xff1a;http://m.oschina.net/blog/175426转…

linux之一些比较新但是常用的命令(expr ag tree cloc stat tmux axel)

1 expr命令 介绍:这个命令用来匹配正则表达式,这个命令linux系统自带,不信你自己试下 使用:expr 正则表达式 输出结果 expr http:\/\/www\.baidu\.com http//www.baidu.com 用了这个命令,我们就不需要在网上去搞在线正则表达式匹配 2 tree命令 这个命令需要安装 sudo…