.NET 6 と Daprを使った分散サービス開発 その7 Rabbit MQ と Input Binding

# Input Binding (入力バインディング)による連携

今まで、以下の流れで作業を行ってきました。今回はDaprに備わっているInput Binding (入力バインディング)の中で、Rabbit MQにenqueueしたらトリガされる実行に触れていきたいと思います。

**今までの前提の上で入力バインディングの機能を追加しますので、このページから読まれている方は、前提として以下を読んできてください。**

----
https://qiita.com/kazumihirose/items/45b0ea36dd50d63f1d86

https://qiita.com/kazumihirose/items/701fcbfb397fe8670bf7

https://qiita.com/kazumihirose/items/016dde8ca9b35d1030cc

https://qiita.com/kazumihirose/items/e996e3cc34c511bc1124

https://qiita.com/kazumihirose/items/f7811bf3e5abe405a551

https://qiita.com/kazumihirose/items/57e3aeaab65a1a68977b

## Input Bindingについて

前回の記事の再掲となりますが、Input Binding (入力バインディング)は、例えば5分毎(イベント)でサービスをコール（トリガ）してほしい、Azure Storage Queue / Amazon SQS / Apache Kafkaなど所謂キューに、enqueue（イベント）されたら、サービスをコール（トリガ）してほしいなどのケースで用いる事ができます。

イベントに対して、トリガされた処理を行う、Azure Functions や AWS Lambdaなどが、馴染み深いと思いますが、これらと同じような感じでイベントに対して処理を行う仕組みを構成する事ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/c069d68e-5783-ed7c-b900-6e84208c27a9.png)

バインディングの一覧は、Input Binding (入力バインディング)、Output Binding (出力バインディング)共に以下に記載があります。

https://docs.dapr.io/reference/components-reference/supported-bindings/rabbitmq/

## Rabbit MQ バインディングを試す

これらのInput Binding (入力バインディング)で、今回はキューにメッセージがenqueueされたら、指定されたAPIがトリガリングされる仕組みを試していきます。

### Rabbit MQの準備
まず、ローカルの環境でRabbit MQが動作する環境を準備します。以下のようなコマンドでロードしました。TCPポート 5672,5673,15672をEXPOSEしています。

```bash
docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 5673:5673 -p 15672:15672 rabbitmq:3-management
```

以下のようにDokcerでロードされていれば、大丈夫です。今回は管理コンソール付きでロードしています。

```bash
$ docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED         STATUS                  PORTS                                                                                                                   NAMES
097a36fc518b   rabbitmq:3-management   "docker-entrypoint.s…"   9 minutes ago   Up 9 minutes            4369/tcp, 5671/tcp, 0.0.0.0:5672-5673->5672-5673/tcp, 15671/tcp, 15691-15692/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp   some-rabbit
ba8a9bdb62ab   daprio/dapr:1.6.0       "./placement"            2 weeks ago     Up 12 hours             0.0.0.0:6050->50005/tcp                                                                                                 dapr_placement
808b6358b4e7   openzipkin/zipkin       "start-zipkin"           2 weeks ago     Up 12 hours (healthy)   9410/tcp, 0.0.0.0:9411->9411/tcp                                                                                        dapr_zipkin
bed085e54a77   redis                   "docker-entrypoint.s…"   2 weeks ago     Up 12 hours             0.0.0.0:6379->6379/tcp                                                                                                  dapr_redis
````

### Rabbit MQ管理コンソールへのアクセスとQueueの準備

ローディングされたら、 http://localhost:15672/ の管理コンソールにアクセスしてください。デフォルトユーザとパスワードは guest / guest でアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/59249da3-5da0-2537-863f-fc691ba6effd.png)

次にExchangeを作成します。確認したところ、現時点ではExchangeを作成する事をこのコンポーネントでは前提としているようです。はまりやすい所ですが、Queueでは無く、上部のタブからExchange を選択し、daprexchangeという名称で、新たにExchangeを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/64bbd51a-8aca-e966-d4bd-f3207870bcf3.png)

Exchange作成後、Queueタブからも作成したExchangeが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/4443966e-6da4-4f21-e0a6-109ab33be76f.png)

### componentフォルダにrabbitmq.yamlファイルを追加

statestoreを扱った際に、statestore.yamlを追加したと思いますが、同じようにrabbitmq.yamlを追加します。

```YAML:rabbitmq.yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: Rmq
spec:
  type: bindings.rabbitmq
  version: v1
  metadata:
  - name: queueName
    value: daprexchange
  - name: host
    value: amqp://guest:guest@localhost:5672
  - name: durable
    value: true
  - name: deleteWhenUnused
    value: false
  - name: ttlInSeconds
    value: 60
  - name: prefetchCount
    value: 0
  - name: exclusive
    value: false
  - name: maxPriority
    value: 5
  - name: contentType
    value: "application/json"
scopes:
- worker-service
```

また、仕様を確認してみた所、POSTメソッドでの呼び出し固定となっています。(おそらく変更方法がありますが、いったんデフォルト）つまり、この場合/Rmq へPOSTの実装をRmqControllerに行えばOKとなります。

### 前回用いたプロジェクトをそのまま利用します。

今回は、前回用いたWorkerServiceプロジェクトにコントローラーを追加します。
前回の記事はこちらから確認ください。

https://qiita.com/kazumihirose/items/45b0ea36dd50d63f1d86

### プロジェクトの変更

リクエストのモデルをプロジェクトに作成しておきます。RmqRequest.cs をプロジェクトに追加しておきます。

```csharp:RmqRequest
namespace WorkerService;

public class RmqRequest
{
    public String Message { get; set; }

}
```

RmqController.cs を新規にControllersに追加します。POSTされたら、リクエストをコンソールに表示するだけのコードです。

```csharp:RmqController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace WorkerService.Controllers;

[ApiController]
[Route("[controller]")]
public class RmqController : ControllerBase
{
    private readonly ILogger<RmqController> _logger;

    public RmqController(ILogger<RmqController> logger)
    {
        _logger = logger;
    }

    [HttpPost(Name = "PostRmqQueue")]
    public void Post(RmqRequest request)
    {
        Console.WriteLine((string)request.Message);

        return;
    }
}

```

### 起動と確認

編集を終えたら、tye runで起動しましょう。

```bash
$ tye run
Loading Application Details...
Launching Tye Host...

[14:44:48 INF] Executing application from tye.yaml
[14:44:48 INF] Dashboard running on http://127.0.0.1:8000
[14:44:48 INF] Build Watcher: Watching for builds...
...
```

今までと同じ要領で、Tye ダッシュボード http://127.0.0.1:8000 をブラウザで開きましょう。まず、worker-serviceのLogを開いておきます。

まずは、マッピングされたworker-serviceでSwaggerを起動して、プロジェクト単体で動作テストを行いましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/217518b3-b65a-30cd-38c0-38b94cf97355.png)

スクリーンショットの例では、 http://localhost:57810/swagger で起動しています。
ここから、POSTしてみて・・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/67dcb1e1-ae7d-1bda-9dc1-7d86f96183a8.png)

Tyeのダッシュボードからログにもメッセージ string が表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/fff8f148-0a6d-1a77-7bc0-8d06a5c189e0.png)

次にRabbiq MQの管理コンソールからMessageを追加しましょう。管理コンソールでは、以下のようにDaprからのconsumer接続も確認できます。

http://localhost:15672/#/queues/%2F/daprexchange

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/0336494d-e529-e6ed-078f-87fae07f02c0.png)

以下のようなJsonをメッセージとして発行します。

```json:Rabbit MQから送るメッセージ
{
  "message": "DaprDaprDaprDaprDaprDaprDaprDaprDaprDaprDapr"
}
```

Tyeのダッシュボードのworker-serviceのログにもメッセージが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/a79eb837-2c6b-430a-36b2-979c4b10a3a4.png)