Azure Functions 非同期リクエストの実装と Core Tools

インフラエンジニアにとっては、アプリサンプルの調達が悩ましい…

と、Microsoft 公式ドキュメントから紹介された [サンプル](https://github.com/mspnp/cloud-design-patterns/tree/master/async-request-reply) が分かりやすそうだったので、試してみました。

作成されるもののイメージは下記のとおりです。Azure Functions と Queue および Blob Storage を利用しています。

![azfunc_async_reqres_Architecture_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218221/9bbf1d23-38c4-d4f6-5892-0ebc58563dce.png)

# 環境

* WSL 2 (Ubuntu 20.04)
* Azure CLI
* .NET Core SDK version 2.1
* Azure Functions Core Tools

## 準備

Azure CLI などは Windows 環境でも利用できますが、Azure ドキュメント類において bash 表記になっていたりして環境変数の設定がコピペで実施できなくて面倒だったりするので、WSL 2 の Ubuntu を利用します。

* [Azure CLI のインストール](https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli-linux?pivots=apt)
* [.NET Core SDK 2.1 のインストール](https://docs.microsoft.com/ja-jp/dotnet/core/install/linux-ubuntu)
* [Azure Functions Core Tools のインストール](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=linux%2Ccsharp%2Cbash#v2)

それぞれ紹介される手順を実行していけば問題なくインストールできると思います。

なお、.NET Core SDK については 2.1 をインストールしておく必要があります。最新版のみをインストールしただけだと後の手順でエラーが発生するので、ご注意ください。

```sh
sudo apt-get install -y dotnet-sdk-2.1
```

## デプロイ

[サンプル](https://github.com/mspnp/cloud-design-patterns/tree/master/async-request-reply) の [Deploy the Azure resources](https://github.com/mspnp/cloud-design-patterns/tree/master/async-request-reply#deploy-the-azure-resources) に記載の手順を実行していきます。

### 1. Clone or download this repo.

リポジトリをクローンします。

```sh
git clone https://github.com/mspnp/cloud-design-patterns
```

### 2. Navigate to the async-request-reply folder.

フォルダを移動して

```sh
cd async-request-reply/async-request-reply
```

### 3. Create a resource group.

環境変数を設定します。適宜変更してくださいませ。

```sh
export RESOURCE_GROUP=<resource-group-name>
export APP_NAME=<app-name> # 2-6 characters
export LOCATION=<azure-region>
```

リソースグループを作成します。

```sh
az group create --name $RESOURCE_GROUP --location $LOCATION
```

### 4. Deploy the template.

リポジトリ内にある ARM テンプレートからデプロイします。

```sh
az group deployment create \
--resource-group $RESOURCE_GROUP \
--template-file deploy.json \
--parameters appName=$APP_NAME
```

### 5. Wait for the deployment to complete.

デプロイ完了まで待ちます☕

### Deploy the Functions app

src フォルダへ移動し、アプリケーションをデプロイします。

```
cd src
func azure functionapp publish $APP_NAME-fn --csharp --force
```

Azure Functions Core Tools の実行時にいくつかオプションを付与しないと通らないので、`--csharp` と `--force` を付与して実行しています。

* オプションなし時の実行例

```
$ func azure functionapp publish $APP_NAME-fn
Can't determine project language from files. Please use one of [--csharp, --javascript, --typescript, --java, --python, --powershell, --custom]
You're trying to use v3 tooling to publish to a non-v3 function app (FUNCTIONS_EXTENSION_VERSION is set to ~2).
You can pass --force to force update the app to v3, or downgrade to v1 or v2 tooling for publishing.
```

## 試す

curl で POST すると、

```sh
curl -X POST "https://<app-name>.azurewebsites.net/api/asyncprocessingworkacceptor" --header 'Content-Type: application/json' --header 'Accept: application/json' -k -i -d '{
   "id": "1234",
   "customername": "Contoso"
 }'
```

処理が正しく受理された場合、202 の応答が返ります。

```
HTTP/1.1 202 Accepted
Content-Length: 139
Content-Type: application/json; charset=utf-8
Location: http://<app-name>.azurewebsites.net/api/RequestStatus/4605b288-7abe-405d-962d-3f284d38a42c
Date: Wed, 02 Jun 2021 13:20:29 GMT

"Request Accepted for Processing\r\nProxyStatus: http://<app-name>.azurewebsites.net/api/RequestStatus/4605b288-7abe-405d-962d-3f284d38a42c"
```

ここで返却される URL に HTTP GET でアクセスすると…

```
curl -i "http://<app-name>.azurewebsites.net/api/RequestStatus/4605b288-7abe-405d-962d-3f284d38a42c"
```

処理が完了していれば、302 の応答と一緒に Blob Storage へのリンクが返されます。

```
HTTP/1.1 302 Found
Location: https://<blob-name>.blob.core.windows.net/data/4605b288-7abe-405d-962d-3f284d38a42c.blobdata?sv=2018-03-28&sr=b&sig=opcInn7VlPDcyepgFrhPwWCHx8s2v9KvUX2j4BR3dAw%3D&st=2021-06-02T13%3A16%3A34Z&se=2021-06-02T13%3A31%3A34Z&sp=r
```

さらに、返却された URL へ HTTP GET でアクセスすると…

```
curl -i "https://<blob-name>.blob.core.windows.net/data/4605b288-7abe-405d-962d-3f284d38a42c.blobdata?sv=2018-03-28&sr=b&sig=opcInn7VlPDcyepgFrhPwWCHx8s2v9KvUX2j4BR3dAw%3D&st=2021-06-02T13%3A16%3A34Z&se=2021-06-02T13%3A31%3A34Z&sp=r"
```

無事、JSON の中身を取得することができました。

```
HTTP/1.1 200 OK
... 略 ...
{"id":"1234","customername":"Contoso"}
```

-----

Azure Functions や Queue Storage の検証にも使えるので、色々と使いまわしも効きそうなサンプルですね！