Skip to main content

Dapr

Dapr 提供云服务抽象,让实现底层解耦可替换。 虽然 Dapr 看似提取了很多常用的服务功能,但都是对标云平台服务的。 因为 Dapr 是 微软 和 阿里 联合开发的,也就是为了把 Azure 和 Aliyun 的功能集成进来。

不适用场景

  • self-host - 不依赖云平台功能
  • 业务功能明确 - 抽象无意义

Tradeoff

  • sidecar 模式
    • 更好支持多语言 - 前提是涉及到那么多语言
    • 使用额外的资源
    • 开发体验会有影响

  • dapr/dapr 是什么?
    • 云原生开发工具集
    • 支持多语言 - sidecar 暴露 http 和 grpc 接口
    • 支持多环境 - 不限制在 kube 集群
    • Sidecar 模式 - 轻 sdk 重 sidecar
    • CNCF 孵化项目
caution
  • http-max-request-size 默认限制 4m
    • 因此单个 gRPC/HTTP 请求最大 4mb
tip
# macOS 安装 dapr 命令行
brew install dapr/tap/dapr-cli

# 本地启动 Go 应用
dapr run --app-id example-service \
--app-protocol grpc \
--app-port 50001 \
go run main.go

# 启动 JS 应用
dapr run --app-id nodeapp --app-port 3000 --dapr-http-port 3500 app.js

SDK

LanguageStatusClientServerActor
.NETStableASP.NET Core
PythonStablegRPCFastAPI
Flask
JavaStableSpring Boot
GoStable
PHPStable
  • Client
    • 服务方法请求
    • 状态存储
    • PubSub
    • 绑定操作
    • Secret 获取
    • Virtual Actor 交互
  • Server 扩展 - Dapr 服务扩展
    • 能被其他服务调用
    • 订阅主题
  • Actor
    • 方法被请求
    • 状态保存获取
    • Timer 回调
    • 持久化 reminder
  • SDKs

Sidecar

  • 默认端口 3500
  • 元数据 - /v1.0/metadata
    • 应用自省
  • 健康 - /v1.0/healthz
  • 服务调用 - /v1.0/invoke
    • gRPC, HTTP
    • /v1.0/invoke/<appId>/method/<method-name>
      • 例如 /v1.0/invoke/nodeapp.production/method/neworder
        • production 为 namespace
    • NameResolution - consul, kubernetes, mdns
  • 状态管理 - /v1.0/state
    • 支持 Redis, PostgreSQL, MySQL, Hazelcast, Consul, MongoDB, Zookeeper
  • PubSub - /v1.0/publish, /v1.0/subscribe
    • 支持 Kafka, Hazelcast, MQTT, NATS Streaming, Pulsar, RabbitMQ, Redis
  • Binding - /v1.0/bindings
    • 支持 APN, Cron, HTTP, Kafka, MQTT, MySQL, PostgreSQL, RabbitMQ, Redis, SMTP, Local Storage, AliOSS
    • 绑定外部服务为 REST 接口 - 外部服务交互
    • 根据服务不同提供不同操作接口 - 输入输出
    • 输入 POST /<binding>
    • 输出 POST /v1.0/bindings/<bidning>
      • { "data": {}, "operation": "create" }
  • Actor - /v1.0/actors
    • 依赖 state - etag, tx 支持
    • /v1.0/actors/<actorType>/<actorId>/<method/state/timers/reminders>
  • Observability
  • 密钥管理 - /v1.0/secrets
    • Env, File, Vault, Kubernetes Vault

Actor

  • Actor - lowest-level “unit of computation”
  • Virtual Actors
  • actor
    • 支持 state
    • 不支持 sub - 可以 pub

Notes

  • 组件
    • dapr - 命令行
    • daprd - sidecar
    • dashboard - 面板
    • placement
      • distributed hashing - distribute the actor instances across various pods of the user service
      • 只用于 actor
  • SDK - Go, Java, PHP, Python, .NET - WIP JS, Rust, C++
  • Middleware
    • 限流、OAuth2、OAuth2 client credentials、Bearer、OPA
    • Uppercase - 测试使用
  • ~/.dapr/
    • config.yaml
    • components/
      • pubsub.yaml
      • statestore.yaml
    • bin/
      • daprd
      • dashboard
      • web/
  • 参考
# self-host 初始化 - docker - placement :50005, redis :6379, zipkin :9411
# --network 指定 docker network
dapr init
# 不需要 docker
# 可手动启动 $HOME/.dapr/bin/placement
dapr init -s # slim self-hosted - 不启动 placement service, Redis, Zipkin

# k8s 初始化
# --enable-ha
# --enable-mtls - 默认开启
# -n dapr-system
dapr init -k
dapr init -k --wait --timeout 600 --runtime-version 1.3.0 # 指定版本、超时、等待完成

# 面板 - 目前功能比较简单
dapr dashboard -p 9999

# 实验 sidecar
dapr run --app-id myapp --dapr-http-port 3500
# 存储状态
curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "Bruce Wayne"}]' http://localhost:3500/v1.0/state/statestore
docker exec -it dapr_redis redis-cli keys '*'
# hash "myapp||name"

# 实验定义 secret 组件
echo '{"my-secret" : "Secret here"}' > mysecrets.json
mkdir my-components
cat << CONF > my-components/localSecretStore.yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: my-secret-store
namespace: default
spec:
type: secretstores.local.file
version: v1
metadata:
- name: secretsFile
value: $PWD/mysecrets.json
- name: nestedSeparator
value: ":"
CONF
dapr run --app-id myapp --dapr-http-port 3500 --components-path ./my-components
# 请求 json 中的内容
curl http://localhost:3500/v1.0/secrets/my-secret-store/my-secret

配置

  • CDR Configuration
  • 通过 dapr.io/config: "zipkin" 使用
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: zipkin
namespace: default
spec:
tracing:
samplingRate: "1"
zipkin:
# 可以 selfhost
endpointAddress: "http://localhost:9411/api/v2/spans"
# k8s
endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"

# API ACL
api:
allowed:
- name: state # state, invoke, secrets, bindings, publish, actors, metadata
version: v1.0
protocol: http # http, grpc

# 服务访问控制
accessControl:
defaultAction: deny
trustDomain: "public"
policies:
- appId: app1
defaultAction: allow
trustDomain: 'public'
namespace: "default"
- appId: app1
defaultAction: deny
trustDomain: 'public'
namespace: "default"
operations:
- name: /op1 # /op1/*
httpVerb: ['POST', 'PUT'] # ['*']
action: allow

# 预览特性
features:
- name: Feature1
enabled: true