Daprつかってみた(Web APIのイメージでローカルストレージとGCSを同じように扱ってみる)
この記事は Web API Advent Calendar 2021 の5日目の記事になります
ちなみに4日目は
@sys_zeroさんのPower Automate for desktopの変数に関するTips「JSONにnull値がある場合の選択的置換」でした
今回は、当日まで全く内容について考えられてなかったのですが、ふっと、頭にわいた、個人的に気になっているDaprについて調べて、ローカルストレージとGoogle Cloud Storage(以下GCS)を扱ってみます
なんで今回Dapr?
Daprを使うメリットの1つとして、他のサービスにつなぐ方法をHTTPまたはgRPCにすることができるというのがあります。
この、他サービスとは、Daprのホームページに有る通り、ローカルストレージや、redisやmysqlなどのストレージ、はたまた、クラウド環境になります。
(https://docs.dapr.io/concepts/overview/ にある図です)
つまり、アプリケーション側は接続先が具体的に何であるかを意識しないでHTTPやgRPCで操作できるというのが嬉しいポイントです。
今まではインフラ層として、アプリケーション側で頑張って抽象化していた部分を、Daprが実装してくれていることにより、設計の手間を減らせそうなのが良さそうだと個人的思っています。
また、言語によってあるサービスがちょっと使いにくいライブラリだったり、そもそもライブラリがないなどがあると思いますが、Daprなら、HTTPで接続するようにしようなどとなるかもしれません。
もう一つ面白い点として、Daprの特徴として一つはアプリケーションとして組み込むライブラリとして動くのではなく、sidecarという形で、実際のアプリケーションと一緒に起動するアプリケーションとして起動します。
そのため、sdkも使わないのであれば、ただただhttp clientまたはgRPCのクライアントを入れるだけでローカルファイルや、redisやmysqlの操作ができるということになります。このあたりは今回紹介しませんが、実際にアプリケーションを作ってみるなどして確認するといいかと思います。
(https://docs.dapr.io/concepts/overview/ にある図です)
デメリットとしては、既存で使えるものが限られる点だと思います。
ただ、足りない部分は自分たちで作成して、Daprのinterfaceに合わせることで、アプリケーションを抽象化できるので、その点は小さい問題点な気もします。(結局作らないといけないなら一緒かなと)
実行環境
アプリケーションまたはOS | バージョン |
---|---|
MacOS Monterey(M1) | 12.0.1 |
Docker Desktop | 4.3.0 |
Dapr | 1.5.0 |
インストールについては DaprのGeting Started を参考にしてください。
ローカルストレージを扱う
まずローカルファイルの中身の取得とファイルの作成をやってみます。
Local Storage binding specとだいたい同じ内容です
Daprのコンポーネント作成する
細かい点は説明しませんが、PATHの部分がローカルファイルが置かれる場所になります。
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: storage
namespace: default
spec:
type: bindings.localstorage
version: v1
metadata:
- name: rootPath
value: <PATH>
構成としては以下のようになります。
.
└── my-components
└── test.yaml
上記のアプリケーション起動のコマンドとしては以下です。ファイルを指定せずいけます。
$ dapr run --app-id storage-test --dapr-http-port 3500 --components-path ./my-components
ファイルの作成
ファイルの作成なのでoperationはcreateです。
ちなみに、metadataをつけない場合はuuidでファイルが作成されます
$ curl -i -d '{ "operation": "create", "data": "Hello World", "metadata": {"fileName": "sample.txt"} }' http://localhost:3500/v1.0/bindings/storage
HTTP/1.1 200 OK
Server: fasthttp
Date: Sat, 04 Dec 2021 13:05:16 GMT
Content-Type: application/json
Content-Length: 25
Traceparent: 00-a1f93ae88050c49941bc194378f8bd7d-43cc4ecc7cd8071b-01
{"fileName":"sample.txt"}
コンポーネントで指定した場所に sample.txt
が作成されているはずです。
ちなみに再度実行した場合200が返り、裏書きされます。
ファイルの取得
ファイルの中身取得はoperation getです。
$ curl -i -d '{ "operation": "get", "metadata": { "fileName": "sample.txt" }}' http://localhost:3500/v1.0/bindings/storage
HTTP/1.1 200 OK
Server: fasthttp
Date: Sat, 04 Dec 2021 13:21:38 GMT
Content-Type: application/json
Content-Length: 11
Traceparent: 00-f112a8e70c0cd249d2334935e81520ff-d8622ed38d2bfd3d-01
Hello World
こんな感じで取得できます。
もし対象のファイルがない場合は500が返ります。このあたりはもう少し調査してもいいかもです。
今回紹介ありませんが、deleteとlistもできます。
GCSを扱う
ローカルとは違いgcsへのアクセスが必要になるためGCPのservice accountのjsonの情報を記載してくことになります。
基本はGCP Storage Bucket binding spec同じになります。
今回、bucketとservice accountの作成方法は省略しますが、作成しておく必要があります。
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: storage-2
namespace: default
spec:
type: bindings.gcp.bucket
version: v1
metadata:
- name: bucket
value: <bucketname>
- name: type
value: service_account
- name: client_email
value: <client email>
- name: private_key
value: " "
注意するところは上記のmetadataの値はミスっていても動いて、ファイル作成は動いてしまうという点ですね。また、リファレンス先ではパラメータは必須のものが多いのですが検証していったり、自分の経験上これはいらんだろとなったものは、なくても問題なく動きました。
こちらの、componentですが、先程のlocalと同じファイルに記載していっても問題ありません。(k8sのyamlのイメージ)。
ファイルの作成
ファイルの作成なのでoperationはcreateです。
ローカルと同じようにできます。ただファイルに名前をつける際はkeyに指定することになります。
$ curl -i -d '{ "operation": "create", "data": "Hello World", "metadata": {"key": "sample.txt"} }' http://localhost:3500/v1.0/bindings/storage-2
HTTP/1.1 200 OK
Server: fasthttp
Date: Sat, 04 Dec 2021 14:24:52 GMT
Content-Type: application/json
Content-Length: 79
Traceparent: 00-2c99123f4379b2106fe61daa558762ea-34873aa800a6b22c-01
{"objectURL":"https://storage.googleapis.com/<bucketname>/sample.txt"}
コンポーネントで指定した場所に sample.txt
が作成されているはずです。
ちなみに再度実行した場合200が返り、裏書きされます。
ファイルの取得
ファイルの中身取得はoperation getです。先ほどと同じようにファイルを指定する場合はkeyを使います。
$ curl -i -d '{ "operation": "get", "metadata": { "key": "sample.txt" }}' http://localhost:3500/v1.0/bindings/storage-2
HTTP/1.1 200 OK
Server: fasthttp
Date: Sat, 04 Dec 2021 13:21:38 GMT
Content-Type: application/json
Content-Length: 11
Traceparent: 00-f112a8e70c0cd249d2334935e81520ff-d8622ed38d2bfd3d-01
Hello World
こんな感じで取得できます。
ローカルと同じようにlistも使えます。
まとめ
twitterでも話題に上がっていて気になっていたんですが、実際使ってみると余計に良いものだなと思うようになりました。
今回bindingのstorage系についてでしたが、pubsubなどもあるので、APIとして各サービスを扱うという点において、是非試してみてください。
Discussion