轻量级分布式应用运行时Dapr,你值得拥有!
立即解锁
发布时间: 2025-08-25 02:30:41 阅读量: 1 订阅数: 4 

# 轻量级分布式应用运行时Dapr,你值得拥有!
## 一、Dapr简介
Dapr被设计成构建块的中心,并非一个从头开始包含所有功能的自成体系的框架。这种开放设计使Dapr核心运行时非常轻量级,仅占用约40MB磁盘空间和4MB内存,使用0.1 vCPU核心,对服务调用的额外开销不到一毫秒。这使得Dapr适用于物联网和大数据应用等动态扩展、高密度的场景。
### (一)统一编程模型
不同类型的服务有不同的编程模型,如无状态服务、有状态服务、函数、参与者等。Dapr不严格区分这些服务类型,将所有服务视为处理单元,接受输入并产生输出。开发者可以用一致的方式编写所有服务,并在后续重新配置服务的行为。
例如,可将无状态的Web服务重新配置为具有输入/输出绑定的函数,并部署在无服务器环境中;也可通过引入状态存储将其转变为有状态服务;还能让服务具备身份感知能力,使其充当参与者。
Dapr通过标准化的HTTP/gRPC协议提供统一编程模型。开发者在设计服务时无需针对特定服务类型,当需要某些功能(如状态管理或绑定)时,只需调用应用边车(sidecar)上的相应API。同一服务的不同路由可以承担不同角色并呈现不同特性。此外,通过绑定,Web服务可以由流行云服务的事件触发,而无需开发者学习特定服务的API。
### (二)Dapr架构
Dapr由Dapr CLI、运行时和多个控制平面服务组成,还附带一个可扩展的构建块库,包含状态存储、消息骨干、绑定和可观测性等常见构建块。
- **Dapr CLI**:跨平台命令行工具,用于配置、管理和监控Dapr实例,还可访问Dapr仪表板等有用工具。
- **Dapr主机**:托管Dapr运行时实例,常见形式是Docker容器,可注入到Kubernetes的Pod中与用户代码并行运行,也可在独立模式下作为服务进程或守护进程运行。它实现了HTTP和gRPC等通信协议。
- **Dapr API**:定义了Dapr运行时的可编程接口。
- **Dapr运行时**:实现Dapr API,是Dapr功能的核心。
- **Dapr Operator**:Kubernetes特定组件,支持Dapr的Kubernetes模式,管理配置和绑定。
- **Dapr Sidecar Injector**:在Dapr以Kubernetes模式运行时,处理Dapr边车容器的注入。
- **Dapr Placement Service**:管理Dapr实例或服务分区的路由,维护路由表,将请求定向到特定参与者ID或分区ID的同一Dapr运行时实例。
- **Dapr Sentry**:内置证书颁发机构(CA),用于证书颁发和管理。
### (三)构建块
1. **状态存储**:Dapr将参与者和有状态服务的状态保存到可配置的状态存储中。默认本地状态存储是Redis,也可接入其他存储,如Azure Cosmos DB、Cassandra等。
2. **发布/订阅**:默认提供至少一次消息传递,并将Redis Streams配置为可靠消息传递的消息骨干。
3. **绑定**:用于将应用代码连接到不同的输入和输出通道,定义了简单的绑定接口,以单线程方式调用,编写新绑定相对容易。
4. **可观测性**:与OpenTelemetry集成,用于收集应用指标和分布式跟踪。
### (四)语言支持
Dapr是语言无关的,通过HTTP或gRPC提供分布式应用构建块。同时,它提供了一些支持参与者的流行语言(如C#、Python和Java)的SDK,未来社区有望贡献更多编程语言的SDK。即使选择基于Dapr的特定语言参与者框架,参与者也能与其他Dapr参与者框架或纯Dapr运行时实现的参与者进行互操作。Dapr运行时实现和绑定使用Go语言开发,理论上可能会出现其他编程语言的Dapr API实现。
## 二、快速开始使用Dapr
### (一)独立模式下的Hello, World应用
#### 1. 在本地安装Dapr
要在独立模式下安装Dapr,请按照以下步骤操作:
1. 确保机器上的Docker正在运行,Dapr CLI使用Docker运行Redis状态存储和Dapr Placement服务。
2. 从GitHub(https://oreil.ly/TeRug)下载发布二进制文件:
- Windows:dapr_windows_amd64.zip
- Linux:dapr_liux_amd64.zip
- macOS:dapr_darwin_amd64.zip
- Linux ARM设备:dapr_linux_arm.zip
3. 将Dapr CLI二进制文件提取到所选文件夹。
4. 可选步骤:为方便访问CLI,在macOS和Linux上将二进制文件移动到 /user/local/bin 文件夹,或在Windows上将步骤3中的文件夹添加到PATH环境变量。
5. 运行以下命令初始化Dapr:
```bash
dapr init
```
该命令将启动两个容器:一个用于可靠消息传递和默认状态存储的Redis容器,以及一个管理参与者和分区服务放置的Dapr Placement服务容器。如果出现“failed to launch the container”错误消息,可能是现有容器占用了所需端口(Redis为6379,macOS/Linux上的Placement服务为50005,Windows上的Placement服务为6050),需要关闭占用这些端口的容器并重新运行 `dapr init` 命令。初始化成功后,可使用以下命令检查当前CLI版本和Dapr运行时版本:
```bash
dapr --version
```
#### 2. 创建Hello, World应用
这里使用Go语言创建一个新的 `main.go` 文件,内容如下:
```go
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
type incomingEvent struct {
Data interface{} `json:"data"`
}
func main() {
http.HandleFunc("/greeting",
func(w http.ResponseWriter, r *http.Request) {
var event incomingEvent
decoder := json.NewDecoder(r.Body)
decoder.Decode(&event)
fmt.Println(event.Data)
fmt.Fprintf(w, "Hello, World!")
})
log.Fatal(http.ListenAndServe(":8088", nil))
}
```
此代码在端口8088启动一个Web服务器,当收到 `/greeting` 路由的请求时,打印请求体(假设包含一个 `data` 字段)并返回字符串 “Hello, World!”。
#### 3. 通过Dapr边车进程启动应用
在命令行或终端窗口中,启动一个新的Dapr运行时实例作为应用的边车进程。使用 `dapr run` 命令并在后面附加启动应用的命令(这里是 `go run main.go`):
```bash
dapr run --app-id hello-dapr --app-port 8088 --port 8089 go run main.go
```
该命令的输出表明Dapr运行时以独立模式启动,连接到端口8088的应用,使用Redis作为状态存储和消息骨干,监听指定端口8089的HTTP流量和随机端口的gRPC请求。Dapr和应用的日志将显示在同一终端窗口中,方便跟踪Dapr边车和应用之间的交互。
以下是 `dapr run` 命令的常用开关:
| 开关 | 用途 | 默认值 |
| ---- | ---- | ---- |
| app-id | Dapr边车ID | N/A |
| app-port | 应用端口 | N/A |
| config | Dapr配置文件 | N/A |
| enable-profiling | 通过HTTP端点启用pprof分析 | false |
| grpc-port | Dapr gRPC端口 | -1(随机) |
| log-level | 设置日志详细程度:debug, info, warning, error, fatal, panic | info |
| max-concurrency | 控制允许的并发调用数量 | -1(无限制) |
| port | Dapr HTTP端口 | -1(随机) |
| profile-port | 分析服务器监听的端口 | -1(随机) |
| protocol | 告知Dapr使用HTTP或gRPC与应用通信 | http |
#### 4. 测试应用
Dapr边车提供了 `/<version>/invoke/<action-id>/method/<methodname>` 路由,客户端可使用该路由直接调用应用上的方法。例如,对 `/v1.0/invoke/hello-dapr/method/greeting` 路由的请求将传递到Go应用中的 `/greeting` 处理程序。
要测试此功能,打开浏览器并访问以下地址:
```
http://localhost:8089/v1.0/invoke/hello-dapr/method/greeting
```
你应该会收到 “Hello, World!” 消息,这表明你已通过Dapr成功调用了应用上的Web方法。
### (二)使应用具有状态
#### 1. 定义Redis状态存储
在独立模式下,通过在应用运行目录下的 `components` 文件夹中添加状态存储描述文件,告知Dapr边车状态存储可用。运行 `dapr init` 命令时,Dapr CLI会自动创建 `components` 文件夹,并包含默认的Redis状态存储配置和Redis消息骨干配置。以下是默认的 `redis.yaml` 配置文件示例:
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.redis
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""
```
如果使用不同的Redis服务器,需要更新此文件以匹配Redis设置。
#### 2. 更新应用以处理状态
应用可通过 `/<version>/state/store name<key>` 路由从Dapr边车请求状态,并通过将状态对象发布到边车的 `/<version>/state/store name` 路由来保存状态。发布状态时,Dapr允许以JSON数组形式发布多个键/值对,示例如下:
```json
[
{
"key": "key-1",
"value": "some simple value"
},
{
"key": "key-2",
"value": {
"field-a": "value-a",
"field-b": "value-b"
}
}
]
```
请求状态时,如请求 “key-1” 的值,将以JSON对象形式返回该值。
更新后的应用代码如下:
```go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strconv"
)
type stateData struct {
Key string `json:"key"`
Value int `json:"value"`
}
func main() {
http.HandleFunc("/greeting",
func(w http.ResponseWriter, r *http.Request) {
resp, err := http.Get("http://localhost:8089/v1.0/state/statestore/mystate")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
strVal := string(body)
count := 0
if strVal != "" {
count, _ = strconv.Atoi(strVal)
count++
}
stateObj := []stateData{stateData{Key: "mystate", Value: count}}
stateDataJSON, _ := json.Marshal(stateObj)
resp, err = http.Post("http://localhost:8089/v1.0/state/statestore", "application/json", bytes.NewBuffer(stateDataJSON))
if err != nil {
log.Fatal(err)
}
if count == 1 {
fmt.Fprintf(w, "I’ve greeted you " + strconv.Itoa(count)+" time.")
} else {
fmt.Fprintf(w, "I’ve greeted you " + strconv.Itoa(count)+" times.")
}
})
log.Fatal(http.ListenAndServe(":8088", nil))
}
```
每次调用 `/greeting` 处理程序时,它会通过发送GET请求到 `http://localhost:8089/v1.0/state/statestore/mystate` 请求 `mystate` 键的状态值,然后递增该值并将其发布到 `http://localhost:8089/v1.0/state/statestore` 进行保存。
#### 3. 测试有状态应用
使用以下命令通过Dapr边车启动应用:
```bash
dapr run --app-id hello-dapr --app-port 8088 --port 8089 go run main.go
```
启动Dapr边车后,终端窗口会显示状态存储已找到并初始化的信息。打开浏览器并访问 `http://localhost:8089/v1.0/invoke/hello-dapr/method/greeting`,刷新页面时,问候计数应会增加。
按下Ctrl - C停止Dapr边车和应用,模拟应用(以及Dapr边车)的完全崩溃。然后再次通过Dapr边车启动应用,你会发现应用状态得以保留,因为Dapr边车将状态保存到了外部Redis存储中。
如果你想检查Redis中保存的状态,可以使用Docker的 `exec` 命令连接到Redis服务器并查询键(可使用 `docker ps` 获取Redis容器的名称)。
### 三、总结
通过以上步骤,你已经了解了Dapr的基本概念、架构和使用方法。Dapr的统一编程模型和轻量级设计使其成为构建分布式应用的强大工具,无论是在开发环境还是生产环境中都能发挥重要作用。希望你能在实际项目中尝试使用Dapr,体验其带来的便利和高效。
以下是整个过程的mermaid流程图:
```mermaid
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([开始]):::startend --> B(安装Dapr):::process
B --> C(创建Hello, World应用):::process
C --> D(通过Dapr边车启动应用):::process
D --> E(测试应用):::process
E --> F{是否使应用有状态}:::decision
F -->|是| G(定义Redis状态存储):::process
G --> H(更新应用以处理状态):::process
H --> I(测试有状态应用):::process
F -->|否| J([结束]):::startend
I --> J
```
通过这个流程图,你可以更清晰地看到使用Dapr开发应用的整个过程,从安装到测试,再到添加状态管理功能,每个步骤都紧密相连。希望这篇文章能帮助你快速上手Dapr,开启分布式应用开发的新旅程!
### 四、Dapr的优势分析
#### 1. 轻量级与资源高效性
Dapr核心运行时仅占用约40MB磁盘空间和4MB内存,使用0.1 vCPU核心,对服务调用的额外开销不到一毫秒。这使得它在资源受限的环境中,如物联网设备和高密度的云计算场景下,能够高效运行,减少资源消耗,提高资源利用率。与传统的大型框架相比,Dapr的轻量级特性使其部署和扩展更加灵活。
#### 2. 统一编程模型的便利性
传统开发中,不同类型的服务(如无状态服务、有状态服务等)往往需要不同的编程模型,开发者需要花费大量时间学习和适应。而Dapr的统一编程模型打破了这种限制,开发者可以用一致的方式编写所有服务,并根据需求灵活配置服务的行为。例如,将无状态的Web服务轻松转换为有状态服务或函数,大大提高了开发效率和代码的可维护性。
#### 3. 组件可扩展性
Dapr附带的可扩展构建块库,如状态存储、发布/订阅、绑定和可观测性等,为开发者提供了丰富的功能选择。而且,这些组件可以根据需求进行定制和扩展,社区也在不断贡献新的组件。例如,除了默认的Redis状态存储,还可以接入Azure Cosmos DB、Cassandra等其他存储,满足不同场景的需求。
#### 4. 语言无关性与SDK支持
Dapr是语言无关的,通过HTTP或gRPC提供分布式应用构建块,开发者可以使用自己熟悉的编程语言进行开发。同时,它提供了一些支持参与者的流行语言(如C#、Python和Java)的SDK,未来社区有望贡献更多编程语言的SDK,进一步降低开发门槛。
### 五、Dapr在实际项目中的应用建议
#### 1. 从简单场景入手
对于初次接触Dapr的开发者,建议从简单的场景开始,如独立模式下的Hello, World应用。通过这个过程,熟悉Dapr的安装、配置和基本使用方法,理解Dapr的核心概念和工作原理。
#### 2. 逐步引入复杂功能
在掌握了基本使用方法后,可以逐步引入更复杂的功能,如状态管理、发布/订阅等。例如,将无状态的Hello, World应用转换为有状态应用,体验Dapr状态管理的便利性。
#### 3. 结合实际业务需求选择组件
根据实际业务需求,选择合适的构建块组件。例如,如果需要可靠的消息传递,可以使用发布/订阅组件;如果需要存储数据,可以选择合适的状态存储组件。同时,要注意组件之间的兼容性和配置。
#### 4. 利用社区资源
Dapr有一个活跃的社区,开发者可以利用社区的资源,如文档、示例代码、论坛等,解决遇到的问题,学习他人的经验。
### 六、常见问题及解决方案
#### 1. Dapr初始化失败
- **问题描述**:运行 `dapr init` 命令时,出现 “failed to launch the container” 错误消息。
- **原因分析**:可能是现有容器占用了所需端口(Redis为6379,macOS/Linux上的Placement服务为50005,Windows上的Placement服务为6050)。
- **解决方案**:使用 `docker ps` 命令查看占用端口的容器,然后使用 `docker stop <container_id>` 命令停止这些容器,最后重新运行 `dapr init` 命令。
#### 2. 应用状态未保存
- **问题描述**:在有状态应用中,刷新页面时问候计数没有增加,或者应用重启后状态没有保留。
- **原因分析**:可能是Redis状态存储配置不正确,或者应用代码中状态请求和保存的逻辑有误。
- **解决方案**:检查 `redis.yaml` 配置文件,确保Redis主机和密码配置正确。同时,检查应用代码中状态请求和保存的URL是否正确。
#### 3. Dapr边车无法启动
- **问题描述**:运行 `dapr run` 命令时,Dapr边车无法启动,出现错误消息。
- **原因分析**:可能是Dapr CLI版本与运行时版本不兼容,或者配置文件有误。
- **解决方案**:使用 `dapr --version` 命令检查CLI版本和运行时版本,确保它们兼容。同时,检查 `dapr run` 命令的参数和配置文件是否正确。
### 七、总结与展望
#### 1. 总结
Dapr作为一个轻量级的分布式应用运行时,具有统一编程模型、组件可扩展性、语言无关性等诸多优势。通过本文的介绍,我们了解了Dapr的基本概念、架构、使用方法和常见问题的解决方案。在实际项目中,Dapr可以帮助开发者更高效地构建分布式应用,提高开发效率和代码质量。
#### 2. 展望
随着云计算、物联网等技术的不断发展,分布式应用的需求将越来越大。Dapr作为一个新兴的技术,具有很大的发展潜力。未来,我们可以期待Dapr社区贡献更多的组件和SDK,支持更多的编程语言和应用场景。同时,Dapr可能会与其他技术(如Kubernetes、微服务框架等)进行更深入的集成,为开发者提供更强大的工具和解决方案。
以下是Dapr开发过程中常见步骤的表格总结:
| 步骤 | 操作内容 | 命令示例 |
| ---- | ---- | ---- |
| 安装Dapr | 下载二进制文件,初始化Dapr | `dapr init` |
| 创建应用 | 使用喜欢的编程语言编写代码 | Go语言示例:创建 `main.go` 文件 |
| 启动应用 | 通过Dapr边车启动应用 | `dapr run --app-id hello-dapr --app-port 8088 --port 8089 go run main.go` |
| 测试应用 | 调用应用方法 | 浏览器访问 `http://localhost:8089/v1.0/invoke/hello-dapr/method/greeting` |
| 添加状态管理 | 定义状态存储,更新应用代码 | 定义 `redis.yaml`,更新 `main.go` |
| 测试有状态应用 | 检查状态是否保存 | 刷新页面,重启应用检查状态 |
以下是Dapr问题解决流程的mermaid流程图:
```mermaid
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([遇到问题]):::startend --> B{问题类型}:::decision
B -->|初始化失败| C(检查端口占用):::process
C --> D(停止占用端口的容器):::process
D --> E(重新运行dapr init):::process
B -->|应用状态未保存| F(检查Redis配置):::process
F --> G(检查应用代码逻辑):::process
B -->|Dapr边车无法启动| H(检查版本兼容性):::process
H --> I(检查配置文件和参数):::process
E --> J{问题是否解决}:::decision
G --> J
I --> J
J -->|是| K([问题解决]):::startend
J -->|否| L(寻求社区帮助):::process
L --> K
```
通过这个流程图,当遇到Dapr使用过程中的问题时,可以按照流程逐步排查和解决问题。希望本文能帮助你更好地理解和使用Dapr,在分布式应用开发中取得更好的成果。
0
0
复制全文
相关推荐










