初めに
以前書いた「AzureCLIでAzureFunctionsの構築」の続きのようなものです。
本記事の目標は、「コンテナーAに画像をアップロードした際に、コンテナーBにコピーする」ことです。
コンテナーへのアップロードのイベントの起因として、AzureFunctions
を動かします。
イベントの起因には以下のような方法が考えられます。
-
BLOB Storage Trigger
の利用 -
Event Grid Trigger
の利用 -
Queue Storage Trigger
の利用
今回は BLOB Storage Trigger
の利用を試します。
先に結論を書いてしまいますが、Event Grid Trigger
の方が方法としてはいいようです。
注意
BLOB 専用ストレージ アカウントの場合、高スケールの場合、または待機時間を短縮する場合は、Blob ストレージ トリガーではなく、Event Grid トリガーを使用してください。 詳しくは、「トリガー」セクションをご覧ください。
環境
Windows10 / Powershell / python3.6.8 / .NET Core SDK 2.1.x
.NET Core SDK のインストール
以下 Trigger を利用する際に必要なためインストールします。
[URL]https://dotnet.microsoft.com/download/thank-you/dotnet-sdk-2.1.802-windows-x64-installer
以降の前提条件
- Azureアカウント作成済
- Resouse Groupe 作成済
- Storageアカウント作成済
- Storage Container を input用 output用で2つ構築済
- .NET Core SDK インストール済
BLOB Storage Trigger
の利用
まず、BLOB Storage Trigger を利用する場合の手順を記載します。
プロジェクトの作成
# 1. プロジェクトの作成
func init blobTriggerPj
# 2. pythonを選択
# 3. フォルダ移動
cd blobTriggerPj
# 4. 関数アプリの作成
func new
# 5. Azure Blob Storage trigger を選択
# 6. 関数名を「blobTrigger」に設定
Select a template: Azure Blob Storage trigger
Function name: [BlobTrigger] blobTrigger
設定ファイルの更新
自動作成された各種ファイルを今回の目標に合わせた形へと修正します。
host.json
の更新
BLOBストレージバインディングは、拡張機能を登録する必要があるようです。公式情報
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
function.json
の更新
デフォルトでは、inputのバインディングのみ記載されているので、outputのバインディングを追加します。
また、それに合わせてinputの名称を調整します。
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "myblob",
"type": "blobTrigger",
"direction": "in",
"path": "samples-workitems/{name}",
"connection": ""
}
]
}
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "inputblob",
"type": "blobTrigger",
"direction": "in",
"path": "container-a/{name}",
"connection": ""
},
{
"name":"outputblob",
"type":"blob",
"direction":"out",
"path":"container-b/{name}-Copy",
"connection":""
}
]
}
connection
は、不要ではなく空文字の指定が必要です。
connectionは、このバインドに使用するストレージ接続文字列を含むアプリ設定の名前です。
空文字に設定した場合は、Functionsランタイムは、アプリ設定内の AzureWebJobsStorage という名前の既定のストレージ接続文字列を使用するためです。
接続文字列に関しては以前の記事を参考。
__init__.py
の更新
構築したての__init__.py
には、ログを出力する機能のみ記載されているので、ファイルを出力するコードを記載します。
引数には、function.json
のbindingsで指定したinとoutのnameを用います。
import logging
import azure.functions as func
def main(inputblob: func.InputStream,outputblob: func.Out[func.InputStream]):
logging.info(f"Python blob trigger function processed blob \n"
f"Name: {inputblob.name}\n"
f"Blob Size: {inputblob.length} bytes")
outputblob.set(inputblob)
関数アプリのデプロイ
上記の修正した関数アプリをデプロイします。
func azure functionapp publish <作成済関数アプリ名> --build remote
関数アプリの動作確認
デプロイ完了後、作成しているコンテナーAにファイルをアップし、コンテナーBにコピーされることを確認します。
ここが時間がかかります。(5 ~ 10分ほど)
関数アプリで正しく処理がされていることが確認できました。
コンテナーBにファイルがコピーされていることも確認できました。
終わり
BLOB Storage Trigger は、上記のような流れで作成できました。
ただ、BLOB Storage へのアップロードから関数アプリ起動までにだいぶ時間がかかりました。
[公式情報]には以下場合には、Event Grid を利用するように勧めています。
・BLOB ストレージ アカウントを利用する場合
→ BLOB Storage Trigger は、汎用のStorageアカウントのみ利用可能なため
・高スケール(1秒あたり100を超えるBLOBの更新が発生する場合)
・待機時間の最小化を目指す場合
→ 関数アプリを従量課金プランで使用しているときに、関数アプリがアイドル状態になっている場合、新しい BLOB の処理が最大で 10 分間遅延する可能性がある
解決方法:「従量課金プランからApp Serviceプランへ変更する」または「Event Grid Triggerを利用する」
構築方法としては、後述のEvent Gridを利用するパターンよりも楽なため、速度にこだわりのない要件であればこちらを選択しても良いのかもしれません。