Dapr って何？ - 概要編

この記事は Dapr に関する一連の記事の一部です。

- Dapr って何？ - 概要編
- [Dapr を使ってみる - 入門編](https://qiita.com/takashiuesaka/items/bdae30de41b0daab881f)
- [Dapr を使ってみる - State management 編](https://qiita.com/takashiuesaka/items/713499c531095d5687c2)

# Dapr とは

公式ページからの説明によると Dapr（The Distributed Application Runtime）とは

> 安全で信頼性の高いマイクロサービスを構築するためのAPI

となります。

[Dapr 公式ページ](https://dapr.io/)

API 対応した各種言語用の SDK があるため、.NET だけではなく様々な言語で使用可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/1979baf8-51cf-edbc-ef9f-62c233e7c4f4.png)

[Dapr Software Development Kigs(SDKs)](https://docs.dapr.io/developing-applications/sdks/)

そして機能が少しずつ増加しており、2024/4時点で10+3の機能があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/6be3db93-ebbd-9873-0cef-3906a1702418.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/7ec6be6f-92e7-672e-0d78-59b2ceb7b6e0.png)

[https://docs.dapr.io/concepts/overview/](https://docs.dapr.io/concepts/overview/)

初見ではなんのために存在し、どう便利なのか、そしてどう使うのかさっぱりわからないと思います。誤解を恐れずにいうと、

**Dapr とはインフラレイヤーの抽象化**

です。ここから派生して様々な機能を持つようになっているので、この理解だけでは Dapr 全てを説明しきれないのですが、出発点は間違いなくここです。抽象化、というとわかりにくいかもしれません。別の言い方をすると

**Dapr とはアプリケーションのインフラレイヤーへの依存を排除するもの**

です。アプリケーションがインフラへの依存が無くなると、アプリケーションが使用する特定リソースの切り替え時にアプリケーションを修正する必要がなくなります。例えば DB の種類を変えたり、オブジェクトストレージの種類を変更したとしてもアプリケーションに変更は発生しません。

これによって、例えばローカルと本番との間での環境の差異を Dapr が吸収してくれます。ホスティングするクラウドを変更する場合でも同様です。

難しい言い方をするとインフラレイヤーへの依存が無くなることで、サービス（アプリケーション）の独立性と可搬性が劇的に向上します。

ではどうやって依存を排除するのか、どう使うのかを具体的な例から理解していきましょう。

## Dapr の読み方

ちなみに Dapr の読み方ですが、英語発音ではダパーです。もしくはダーパーです。ダッパーとは読まないように注意しましょう。 [Dapper](https://github.com/DapperLib/Dapper) という歴史ある軽量ORマッパーと誤解します。

# インフラレイヤーを抽象化する具体例

では、例を見ながら Dapr がどういうものなのかを理解していきましょう。

## Dapr によるサービス間の呼び出し

例えばマイクロサービスのように自分たちで構築中のサービスが複数あり、それを呼び出し合っているとします。通常、その呼び出しは　URL などを用いて直接相手を呼び出します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/3d9d3fc3-b858-1856-bcdb-173eade5d53d.png)

ServiceA は ServiceB の URL を知らなければ呼び出すことができません。SerivceA　は ServiceB に依存している、といえます。Dapr を導入するとこの依存を完全に排除することができます。

Dapr を使用する場合は次の構成になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/93f6a796-91a2-bd54-1291-39c0769a78f1.png)

### サイドカーパターン

Dapr はサイドカーパターンを採用しています。

[サイドカー パターン](https://learn.microsoft.com/ja-jp/azure/architecture/patterns/sidecar)

Kubernetes であれば同一 Pod の中に、Azure Container Apps(ACA)であれば同一アプリの中に Dapr のコンテナを立ち上げます（セットアップが必要です）。つまり、ServiceA から見ると同一ホスト内部に別プロセスで Dapr アプリケーションが立ち上がっています。そのため、アプリケーションと Dapr 間の通信は常に localhost:xxxx となります。

### ServiceA からの呼び出し

図のように ServiceA から ServiceB への呼び出し時、送信先を**明示的に** Dapr サイドカーコンテナにします。この時、呼び出し先である ServiceB の　Dapr コンテナに付けておいた appid、**serviceB** を使って呼び出します。すると、Dapr は自動的に名前解決を行ってサイドカーコンテナ間で通信します。

**つまり ServiceA 側の Dapr コンテナは Proxy だと考えれば良いのです。**

### 呼び出される ServiceB

次に呼び出しを受ける側の ServiceB 側の　Dapr コンテナですが、通信を受信したらトラフィックを ServiceB に流します。そのため、ServiceB の Dapr コンテナは立ち上げ時に ServiceB のポート番号 8080 を知っている必要があります。

**つまり ServiceB 側の Dapr コンテナは ReverseProxy だと考えれば良いのです。**

### おさらい

おさらいすると、ServiceA は ServiceB を呼び出す時に、appid が serviceB である Dapr コンテナを呼び出します。実際に ServiceB を呼んでいるかどうかは ServiceA にはわかりません。依存関係がここで完全に排除されます。
ServiceB は Dapr 用の特別な対応は不要です。Dapr コンテナを立ち上げる時に自分のポート番号を Dapr コンテナに渡しておくだけです。

Dapr によるサービス呼び出しはこちらが公式ページです。

[Service invocation overview](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/service-invocation-overview/)

## Dapr による状態保存

Dapr にはアプリケーションの状態を保存することができる State management という機能があります。

[State management overview](https://docs.dapr.io/developing-applications/building-blocks/state-management/state-management-overview/)

セッション情報やキャッシュ、ショッピングカートなど一時的な状態保存や、ワークフローのような比較的長時間に渡るフローの状態保存に用いることができます。

このような場合、通常は次のようにアプリケーションから直接永続化アプリケーションまたはサービスを利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/30712f41-6a86-ebc4-7511-c3546a8842a8.png)

ServiceA は特定の種類の永続化アプリケーション（サービス）に依存しています。これが Dapr を使用すると、次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/94936794-8482-c14a-8a54-c5bc9bc8a016.png)

ServiceA は 自身と同じホストで稼働する Dapr コンテナに対して、POST/GET リクエストします。すると、Dapr コンテナは事前に定義された永続化アプリケーション（サービス）に対して保存・読み出しを実行します。

### おさらい

ServiceA は Dapr コンテナに対してのみ要求を出して、Dapr コンテナが実際にどの永続化アプリケーション（サービス）に対して処理を行っているのかはわかりません。依存関係が完全に排除されています。

### 使用可能な永続化サービス

State management に使用できる永続化サービスはとてもたくさんの種類が用意されています。SQL Database, PostgreSQL, MySQL, MongoDB, Redis などの代表的なデータベース、NoSQLはもちろん、Azure はもちろん AWS や GCP, Oracle Cloud などのサービスにも対応しています。

詳しくはこちらをご参照ください。

[State stores](https://docs.dapr.io/reference/components-reference/supported-state-stores/)

# 改めて Dapr とは

Dapr とはアプリケーションにとって、インフラレイヤーへの依存を完全に排除するところからスタートしました。そしてそれを実現するために Sidecar パターンを採用しています。Sidecar パターンを採用してインフラレイヤーを抽象化することで、実に様々な機能にコードベースで対応できるようになっています。

Dapr では機能のことを Building Block と呼んでいます。以下が2024年4月現在で公開されている Building Block です。

- [Service invocation](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/)
    - 上で説明したサービス呼び出しです。
- [State management](https://docs.dapr.io/developing-applications/building-blocks/state-management/)
    - 上で説明した状態管理のサービスです。
    - [State store component specs](https://docs.dapr.io/reference/components-reference/supported-state-stores/)
- [PubSub](https://docs.dapr.io/developing-applications/building-blocks/pubsub/pubsub-overview/)
    - いわゆる配信・購読モデルです。ブローカーと呼ばれるメッセージ配信サービスへの依存を完全排除できます。
    - [Pub/Sub brokers component specs](https://docs.dapr.io/reference/components-reference/supported-pubsub/)
- [Bindings](https://docs.dapr.io/developing-applications/building-blocks/bindings/bindings-overview/)
    - イベント発火時に呼び出される Input/Output-Binding を実現します。Queue, Messaging, Storage, NoSQL, SMTPなど多種多様なイベントに対応しています。Httpでの呼び出しの場合は Binding ではなく上の　Service invocation を使います。
    - [Bindings component specs](https://docs.dapr.io/reference/components-reference/supported-bindings/)
- [Actor](https://docs.dapr.io/developing-applications/building-blocks/actors/actors-overview/)
    - [Orleans](https://learn.microsoft.com/ja-JP/dotnet/orleans/overview) でも採用されている Virtual Actor モデルを実現します。
- [Secrets](https://docs.dapr.io/developing-applications/building-blocks/secrets/secrets-overview/)
    - クラウドでは接続文字列などのシークレット情報をマネージドのシークレットサービスを使用しますが、Dapr の Secrets を使用することで特定のマネージドサービスへの依存を排除できます。
    - [Secret store component specs](https://docs.dapr.io/reference/components-reference/supported-secret-stores/)
- [Configuration](https://docs.dapr.io/developing-applications/building-blocks/configuration/configuration-api-overview/)
    - 各アプリケーションが参照する構成ストアへの依存を完全に排除できます。構成ストア内のデータが変更されると、新しい変更を読み込むように通知されます。
    - [Configuration store component specs](https://docs.dapr.io/reference/components-reference/supported-configuration-stores/)
- [Distributed lock](https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/distributed-lock-api-overview/)
    - データベースやキューのような状態が変化するリソースに対して、アプリケーションから Lock することで競合が発生しないようにする仕組みを提供します。
    - [Lock components specs](https://docs.dapr.io/reference/components-reference/supported-locks/)
- [Workflow](https://docs.dapr.io/developing-applications/building-blocks/workflow/workflow-overview/)
    - Input/Output Bindings, PubSub, Serivce invocation, Actor など複数の Building Block を駆使してワークフローを実現します。
    - まだベータ版です。(2024年4月現在）
- [Cryptography](https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/)
    - データの暗号・復号を行う際のキーをアプリケーションで保持することなく、マネージドなキーコンテナにアクセスして暗号・復号処理します。これもまた特定のマネージドなキーコンテナーサービスへの依存を排除するものです。
    - [Cryptography component specs](https://docs.dapr.io/reference/components-reference/supported-cryptography/)

# Dapr とはサービスメッシュのこと？

ここまでの説明で、Dapr とは要するにサービスメッシュに近いのでは？と思われた方もいらっしゃるでしょう。

サービスメッシュとは、各マイクロサービスの Sidecar コンテナとして構成され、 Sidecar 同士が通信するアーキテクチャです。Sidecar にサービスディスカバリやサービス呼び出し時の負荷分散、リトライやサーキットブレーカーなどの回復力機能を持たせることで、マイクロサービスが共通して持つ課題に対応しよう、というものです。代表的なものとして [Istio](https://istio.io/), [Envoy](https://www.envoyproxy.io/) などがあります。

Sidecar アーキテクチャを採用して、Sidecar コンテナ間で通信をするという点で Dapr とサービスメッシュは同じです。そして Dapr はサービスメッシュの機能と一部重複します。しかし、方向性が異なります。サービスメッシュはインフラレイヤーでの課題解決を図るものですが、Dapr は開発者に委ねられます。

そのため、トラフィック分割などのネットワークに関する機能を Dapr は持っていません。必要に応じてサービスメッシュと組み合わせて運用することもあります。詳しくは次のページを参照してください。

[Dapr and service meshes](https://docs.dapr.io/concepts/service-mesh/)

# まとめ

Dapr とはアプリケーションからインフラレイヤーへの依存を排除するために Sidecar パターンを採用しており、それをベースに様々な機能が追加された開発者のためのサービスです。一言で言えば、

**Daprとは、インフラレイヤーの抽象化**

です。Dapr をちょっと使ってみようかな、と思っていただけたら幸いです。