谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

Dapr Advent Calendar 2日目 - DaprでHello World

こんにちは、Dapr Advent Calendar 2日目です。3日坊主まであと1日です。

Hello Worldを動かしてみよう

前回はDapr CLIをインストールして動かしてみただけですが、今回はDaprとともにWebアプリケーションを起動して呼び出すところまで説明します。

動かすアプリケーションは、もちろん、プログラミング界で最も著名なアプリケーション「Hello World」です。

f:id:cero-t:20211202051328p:plain
今回作るアプリケーション

Webアプリケーションの作成

まずはWebアプリケーションの作成です。Hello Worldをサクッと作りましょう。

Spring BootでこのようなControllerクラスを作りました。

HelloController.java(抜粋)

@RestController
public class HelloController {
    @GetMapping("/hello")
    public Map<String, String> hello() {
        return Map.of("message", "Hello, world!");
    }
}

ソースコードgithubに置いてあります。

https://github.com/cero-t/dapr-advent-2021

このソースコードの例ではMavenのマルチモジュール構成で、次のように作ってあります。

  • dapr-advent-2021
    • mvnw
    • pom.xml (親モジュール)
    • hello
      • pom.xml (子モジュール)
      • src

まずはWebアプリケーション「hello」を単体で起動します。

../mvnw spring-boot:run

アプリケーションが起動したらcurlコマンドでアクセスします。

curl localhost:8080/hello

無事に実行結果が表示されました。

{"message":"Hello, world!"}

f:id:cero-t:20211202051454p:plain
ここまでで作ったアプリケーション

Daprとともにアプリケーションを起動

続いて、Daprを使ってアプリケーションを起動します。

上で起動したアプリケーションを一旦停止させた後、次のコマンドで起動します。

dapr run --app-id hello-app --app-port 8080 --dapr-http-port 18080 ../mvnw spring-boot:run

コマンドの引数についての詳しい説明はあとで行います。

起動に成功すると、WebアプリケーションのログとDaprのログが両方ともコンソールに表示されるはずです。

(前半部分は割愛)
== APP == 2021-12-02 00:00:00.000  INFO 58739 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
== APP == 2021-12-02 00:00:00.000  INFO 58739 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
== APP == 2021-12-02 00:00:00.000  INFO 58739 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
INFO[0003] application configuration loaded              app_id=hello-app instance=macmini.local scope=dapr.runtime type=log ver=1.5.0
INFO[0003] actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s  app_id=hello-app instance=macmini.local scope=dapr.runtime.actor type=log ver=1.5.0
INFO[0003] dapr initialized. Status: Running. Init Elapsed 3540.333ms  app_id=hello-app instance=macmini.local scope=dapr.runtime type=log ver=1.5.0
INFO[0005] placement tables updated, version: 0          app_id=hello-app instance=macmini.local scope=dapr.runtime.actor.internal.placement type=log ver=1.5.0

ここまで表示されれば起動は完了です。

もしここで次のエラーが出た場合はDaprの初期化が済んでいない可能性が高いので dapr init コマンドを実行してください。

ℹ️  Starting Dapr with id hello-app. HTTP Port: 18080. gRPC Port: 60117
❌  fork/exec /Users/(ユーザ名)/.dapr/bin/daprd: no such file or directory

それでは起動したDapr経由で、Webアプリケーションにアクセスしてみましょう。curlコマンドでアクセスします。

curl localhost:18080/v1.0/invoke/hello-app/method/hello

URLが少しややこしいのですが、このURLの詳細についてもあとで説明します。

ふつうにアクセスした時と同じ実行結果が表示されました。

{"message":"Hello, world!"}

dapr list コマンドで、起動中のDaprアプリケーションを確認することができます。

dapr list

先ほど起動した hello-app が表示されます。

  APP ID     HTTP PORT  GRPC PORT  APP PORT  COMMAND               AGE  CREATED              PID    
  hello-app  18080      61164      8080      ../mvnw spring-bo...  1m   2021-12-02 00:00.00  59584  

なお dapr run コマンドで起動したアプリケーションは、特にコンテナの中で動いているなどではなく、普通のプロセスとして起動しているだけなので、Daprを経由せずにアクセスすることもできます。

curl localhost:8080/hello
{"message":"Hello, world!"}

Dapr経由でアクセスしようとしたけどなぜかアクセスできない、という時にはアプリケーションに直接アクセスして正常に動作しているかを確認してみてください。

f:id:cero-t:20211202051829p:plain
Daprを経由したアクセス

やったことの解説

それでは打ったコマンドなどについて説明します。

起動オプション

今回はDaprを次のコマンドで起動しました。

dapr run --app-id hello-app --app-port 8080 --dapr-http-port 18080 ../mvnw spring-boot:run

dapr run コマンドが、Daprの起動コマンドです。このコマンドでアプリケーションを起動します。ちなみに何の引数も指定せずに dapr run だけ実行してもDaprのプロセスを立ち上げることができます。

--app-id がアプリケーションのIDです。任意の名前を指定することができます。Daprはアプリケーションをこのapp-idで識別していて、アプリケーションをinvokeする時などに利用します。省略すると自動的にIDが発行されます。

--app-port がWebアプリケーションのポート番号です。Hello Worldアプリケーションは8080番ポートで起動しているため、そのポート番号を指定します。省略すると0番ポートが指定されてしまってアプリケーションにアクセスできなくなるため、必ず指定してください。

--dapr-http-port がDapr側のポート番号です。任意のポート番号を指定できます。Daprにアクセスする際にはこのポートを利用します。省略するとランダムなポート番号が指定されます。

../mvnw spring-boot:run の部分がアプリケーションの起動コマンドです。

アプリケーションの起動コマンドに引数を渡す場合は、起動コマンドの前に -- を追加する必要があります。たとえばアプリケーションの起動を java -jar コマンドで行う場合は次のようなコマンドになります。

../mvnw clean package
dapr run --app-id hello-app --app-port 8080 --dapr-http-port 18080 -- java -jar target/hello-1.0.0.jar

javaコマンドの前に -- をつけているところがポイントです。

その他のコマンド一覧

もちろんコマンド引数は他にもあり、このページに一覧が掲載されています。

https://docs.dapr.io/reference/arguments-annotations-overview/

また dapr run --help コマンドを実行すると、dapr run コマンドに対する引数の一覧を見ることができます。

Daprからアプリケーションへのアクセス

Dapr経由でWebアプリケーションにアクセスする際に、次のコマンドを用いました。

curl localhost:18080/v1.0/invoke/hello-app/method/hello

18080 がDaprのポート番号です。

/v1.0 がDaprのAPIバージョンで、今のところ v1.0 しかありません。

/invokeInvoke APIで、起動したWebアプリケーションにアクセスするAPIになります。他にもデータを保存する /state や、エンキューを行う /pubsub などのAPIがあります。

Invoke API/invoke/(app-id)/method/(アプリケーションのパス) という形式になります。今回は app-idhello-app を指定し、アプリケーションのパスは /hello を指定しました。これで localhost:8080/hello にアクセスするのと同じになります。

その他のアクセス方法

DaprのInvoke APIは、Dapr CLIを用いて実行することもできます。

dapr invoke --app-id hello-app --method hello --verb GET

このCLIはverbを指定しないと POST となるため、GETリクエストしたい場合は --verb GET を指定します。

また、Daprのv1.4からInvoke APIを別のURLでも起動できるようになりました。

curl -H 'dapr-app-id:hello-app' localhost:18080/hello
curl dapr-app-id:hello-app@localhost:18080/hello

Daprを運用する際に「パスの書き換えはできないけど任意のヘッダを付けることができる」ようなミドルウェアを利用している場合には、この形式のURLを用いてアクセスすることができるようになりそうですが、実際に使ったことがないのでどれくらい便利になるかはちょっと説明できません。てへぺろ

まとめ

それでは今回の内容を簡単に振り返りましょう。

  • dapr run コマンドでDaprとともにWebアプリケーションを起動することができます
  • Invoke APIを用いてDapr経由でWebアプリケーションにアクセスができます
  • WebアプリケーションそのものもローカルPC上で起動しているため、直接アクセスすることができます

今のところDaprの良さは何も引き出していませんが、次回からはDaprの便利な機能を利用していきます!