微服务框架Dapr为何如此简洁?


Dapr、Express.js、Spring Boot构建微服务的对比分析微服务世界彻底改变了软件的构建和部署方式。已经出现了大量的框架和平台来支持这种架构模式,每个框架和平台都有自己独特的特性和功能。

作为一个团队,我们(Aman Chauhan、Vishal Singh和Pushkar Kumar)有机会使用各种微服务堆栈,例如 Express.js 和 Spring Boot。

Dapr 是我们最近的痴迷技术,直到现在,它的简单性和它为我们的开发过程增加的速度给我们留下了深刻的印象。

在这篇文章中,我们深入研究了 Dapr 的世界,并将它与其他流行的堆栈、Express.js和 Spring Boot 进行了比较,使用代码片段来说明主要区别。

Dapr:微服务平台无关的运行时
Dapr(分布式应用程序运行时)是一种可移植的、事件驱动的运行时,用于在云端和边缘构建微服务。它提供了一组构建块,可简化开发人员在构建微服务时面临的最常见挑战,例如状态管理、服务到服务调用和发布/订阅消息传递。

Dapr 最引人注目的功能之一是其与平台无关的特性。它可以在任何基础设施上运行,包括 Kubernetes、虚拟机,甚至您的本地开发环境。这使开发人员可以专注于编写代码,而不必担心底层基础设施。

from dapr.clients import DaprClient

with DaprClient() as d:
    req_data = {
        'orderId': 1
    }
    resp = d.invoke_service('cart', 'add', data=req_data)
    print(resp.text, flush=True)


Express.js:用于 Node.js 的快速且极简的 Web 框架
Express.js 是一种流行的 Web 框架,用于使用Node.js构建微服务。它以其简单性、灵活性和极简主义而闻名。Express.js 提供了一个薄层的基本 Web 应用程序功能,使其成为单页应用程序、网站和 A PI 的绝佳选择。

Spring Boot:基于 Java 的微服务框架
Spring Boot 是一个基于 Java 的框架,可简化独立的生产级 Spring 应用程序的开发、部署和管理。它提供了一种自以为是的方法来配置 Spring 应用程序、减少样板代码并提供嵌入式服务器支持。

比较:Dapr vs. Express.js vs. Spring Boot
虽然这三个框架都使开发人员能够构建和部署微服务,但 Dapr 因其与平台无关的特性、广泛的构建块以及对事件驱动架构的关注而脱颖而出。Express.js 是重视简单性和极简主义的 Node.js 开发人员的热门选择,而 Spring Boot 是基于 Java 的应用程序的强大且固执己见的解决方案。

Dapr 通过抽象掉与分布式系统相关的复杂性来简化微服务的开发,使开发人员能够专注于编写业务逻辑。它具有跨平台和基础设施扩展的能力,使其成为一个多功能的解决方案。相比之下,Express.js 和 Spring Boot 更针对各自的语言和生态系统。

现在,让我们更深入地比较 Dapr、Express.js 和 Spring Boot 的发布/子组件、可观察性、跟踪和可维护性。

发布/订阅组件
Dapr 为发布/订阅消息提供统一的 API,支持多种消息系统,如 Redis、RabbitMQ 和 Azure Service Bus。这种抽象简化了消息驱动的微服务的实现,促进了服务之间的松散耦合。

# Publishing a message
with DaprClient() as d:
    d.publish_event('orders', 'newOrder', data={'orderId': 1})

# Subscribing to a topic
from dapr.ext.grpc import App

app = App()

@app.subscribe(pubsub_name='orders', topic='newOrder')
def new_order(data: bytes):
    print(f'Received new order: {data}')

在 Express.js 和 Spring Boot 中,您需要使用额外的库来实现发布/订阅消息传递。例如,您可以将amqplib库与 Express.js 和 RabbitMQ 一起使用,或者将 Spring Cloud Stream 与 Spring Boot 和 RabbitMQ 一起使用。

可观察性
Dapr 提供内置的可观察性功能,如日志记录、指标和分布式跟踪。它集成了流行的监控工具,如 Prometheus、Grafana 和 Jaeger,使微服务监控和故障排除变得更加容易。

相比之下,Express.js 和 Spring Boot 需要额外的中间件或库来实现类似的可观察性功能。例如,您可以使用morganandwinston登录 Express.js,或使用 Spring Boot Actuator 进行 Spring Boot 中的指标和健康检查。

由于 Dapr 的可观察性功能是内置的,因此不需要额外的代码。Dapr 自动收集指标和日志,可以使用 Prometheus 和 Grafana 等监控工具进行可视化。

创建dapr.yaml配置文件:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: custom-logging
spec:
  tracing:
    samplingRate: "1"
  logLevel: debug

此配置文件将日志级别设置为debug100%,并启用采样率为 100% 的跟踪。您可以根据需要选择不同的日志级别,例如info、warning或error。

要应用此配置,请在启动应用程序时将--config标志传递给命令:dapr

dapr run --app-id myapp --config ./dapr.yaml python app.py

配置 Dapr 后,日志和指标将自动收集,并可以使用 Prometheus 和 Grafana 等监控工具进行可视化。对于分布式跟踪,您可以将跟踪导出器配置为使用 Jaeger 或 Zipkin 等工具,如之前的响应中所示。

Node.js

const express = require('express');
const morgan = require('morgan');
const winston = require('winston');

const app = express();
app.use(morgan('combined'));

const logger = winston.createLogger({
    level: 'info',
    format: winston.format.json(),
    transports: [
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});

app.get('/hello', (req, res) => {
    logger.info('Hello endpoint was called');
    res.send('Hello, World!');
});

SpringBoot
将以下依赖项添加到您的pom.xml:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

在您的中启用指标和健康检查端点application.properties:

management.endpoints.web.exposure.include=health,info,metric

跟踪
Dapr通过与 OpenTelemetry 集成简化分布式跟踪,实现跨服务的自动跟踪上下文传播。这提供了一种一致的方式来可视化服务依赖性和识别性能瓶颈。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: tracing-config
spec:
  tracing:
    samplingRate: "1"
    zipkin:
      endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"

对于Express.js,您可以使用 OpenTelemetry JavaScript SDK 手动实现分布式跟踪。在 Spring Boot 中,您可以使用 Spring Cloud Sleuth 和 Zipkin 来实现类似的功能。

const api = new opentelemetry.NodeSDK({
  resource: new Resource({
    [ResourceAttributes.SERVICE_NAME]: 'express-service',
  }),
  spanProcessor: new SimpleSpanProcessor(new ZipkinExporter({
    serviceName: 'express-service',
    url: 'http://localhost:9411/api/v2/spans',
  })),
});

api.start();

// Add OpenTelemetry middleware for Express.js
app.use(opentelemetry.express.middleware());

SpringBoot
将以下依赖项添加到您的pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

在你的配置 Zipkin application.properties:

spring.zipkin.baseUrl=http://localhost:9411
spring.sleuth.sampler.probability=1

为什么 Dapr 简单?
Dapr 以其与平台无关的特性、内置功能和促进可维护性和清洁架构的标准化 API 脱颖而出。虽然 Express.js 和 Spring Boot 是各自语言的强大选择,但它们在某些功能上更依赖于额外的库和中间件。

作为一个团队,与不同的微服务堆栈一起工作,我们亲身体验了使用各种框架和平台的好处和挑战。Dapr 凭借其与平台无关的方法和对发布/订阅消息传递、可观察性和分布式跟踪等关键功能的内置支持,已成为微服务领域的游戏规则改变者。其清晰的关注点分离和对事件驱动架构的关注使其成为现代可扩展应用程序的引人注目的选择。

Express.js 和 Spring Boot 继续分别成为 Node.js 和 Java 开发人员的热门选择。但是Dapr的抽象和标准化API的优势也不容忽视。

通过选择 Dapr,开发团队可以随着应用程序的增长实现更大的灵活性和可维护性,并可以在不同的基础架构组件和服务之间轻松切换,而对应用程序代码的影响最小。

我们对 Dapr 的见解和经验告诉我们,它不仅简化了微服务的开发,还简化了部署、扩展和监控。这使开发人员可以专注于最重要的事情:交付高质量、高性能和可靠的软件。对于希望采用微服务架构的组织而言,Dapr 代表了一种强大、多功能且面向未来的选择,可以简化开发并促进创新。