Azure Functionsを業務利用する時の勘所
2018年9月29日
JAZUG札幌支部 第20回勉強会登壇
自己紹介
2
・名前 : 木下 裕之
・HN:kingkino
・Twitter:@kingkinoko
・FaceBook:kino.king.37
・Azure暦:7年
・Microsoft MVP for Microsoft Azure
・MCSE : Cloud Platform and Infrastructure 2017
・Azureもくもく会@東京 主催
・好きなAzureサービス
Azure Storage、Azure MediaService
Azure Functions
注意事項
3
※この資料は2018年9月29日時点での情報を元に作成しています
更新が早いのですぐに古い情報になりますため予めご了承ください
謝辞
4
※本スライドは文字多めです
Azure Functions使ってますか?
5
Azure Functionsの歴史を振り返ってみましょう。
・2016年4月のbuildでPublic Previewとして公開
・2016年11月16日にGA(General Available)
・2017年1月Precompiled Functionsをサポート
・2017年8月VS2017 PreviewでIDEによる開発サポート
・2018年8月にAzure Functions Runtime2.0の大幅更改
・2018年9月にAuzre Functions V2がGA
GAしてから約2年、お仕事で使う機会も増えてきたと思いま
す。V2もGAしたので、ここでV1の機能を振り返りつつ業務
利用した時の話をしようと思います。
本日お話する機能について
6
タイプ トリガー 入力 出力 備考
Blob Storage ○ ○ ○
Cosmos DB ○ ○ ○
Event Grid ○
Event Hubs ○ ○
外部ファイル ○ ○ DropBoxやGoogleドライブなどのファイル管理システム ※V2には移行されない模様
外部テーブル ○ ○ MySQLやDB2等のDBシステム ※V2には移行されない模様
HTTP ○ ○
Mobile Apps ○ ○
Notification Hubs ○ ※V2には移行されない模様
Queue Storage ○ ○
SendGrid ○
Service Bus ○ ○
Table Storage ○ ○
Timer ○
Twilio ○
Webhook ○ ○ ※V2には移行されない模様
C#でPrecompiled版をメインに下記の表の赤い部分について話します
AzureFunctionsとBlob
7
タイプ トリガー 入力 出力 備考
Blob Storage ○ ○ ○
[FunctionName("Function1")]
public static void Run(
[BlobTrigger("samples/{name}",Connection = "AzureStorage")]Stream myBlob,
string name, TraceWriter log)
{
log.Info($"C# Blob trigger function Processed blobn Name:{name} n Size: {myBlob.Length} Bytes");
}
■ BlobTriggerの入力バインド種類
・string
・TextReader
・Stream
・ICloudBlob
・CloudBlockBlob
・CloudPageBlob
・CloudAppendBlob
・Byte[]
・JSON としてシリアル化可能な POCO
■ BlobAttributeのバインド種類
・string
・TextReader
・Stream
・ICloudBlob
・CloudBlockBlob
・CloudPageBlob
・CloudBlobContainer
・CloudBlobDirectory
・IEnumerable<CloudBlockBlob>
・IEnumerable<CloudPageBlob>
■ BlobTriggerの出力バインド種類
・TextWriter
・out string
・out Byte[]
・CloudBlobStream
・Stream
・CloudBlobContainer
・CloudBlobDirectory
・ICloudBlob
・CloudBlockBlob
・CloudPageBlob
・CloudAppendBlob
AzureFunctionsとBlob
8
[FunctionName("Function1")]
public static void Run(
[BlobTrigger("samples/{name}",Connection = "AzureStorage")]Stream myBlob,
string name, TraceWriter log)
■ AzureStorageの接続文字列
下記の接続文字列を直接埋め込むかアプリ設定に外出しして設定します
DefaultEndpointsProtocol=https;AccountName={ストレージアカウント名};AccountKey={Key}
[FunctionName("Function1")]
[StorageAccount("AzureStorage")]
public static void Run(
[BlobTrigger("samples/{name}")]Stream myBlob,
string name, TraceWriter log)
StorageAccountAttributeで設定することも可能です。
この場合は設定した関数全体で利用することができます。
AzureFunctionsとBlob
9
■ AzureStorageの接続文字列
[FunctionName("Function1")]
[StorageAccount("AzureStorage01")]
public static void Run01(
[BlobTrigger("samples/{name}",Connection = "AzureStorage02")]Stream myBlob,
[Blob("samples-demo-out/{DateTIme}")]CloudBlockBlob outBlob,
string name, TraceWriter log)
StorageAccountAttributeとBlobTriggerAttributeやBlobAttributeに別々にConnectionを設定した場合
は個別に設定したほうが優先されます。
上記の例だとBlobTriggerAttributeは[AzrueStorage02]のAzureStorageを参照します。
BlobAttributeはConnectionを設定していないので[AzrueStorage01]のAzureStorageを参照します。
AzureFunctionsとBlob
10
[FunctionName("Function1")]
[StorageAccount(“AzureStorage01”)]
public static void Run(
[BlobTrigger("samples/{name}")]Stream myBlob,
[Blob("samples-in/temaplate.xlsx")]CloudBlobStream inBlob
string name, TraceWriter log)
■ Blobインプットバインディングとフィルタ
上記の例で①はAzrueStorage01ストレージにあるSamplesコンテナにblobが作成されたタイミングで
Triggerし作成されたファイルをStream形式で取得しています。
②はBlobAttributeを利用してsamples-inコンテナにある[template.xlsx]blobをのCloudBlobStream形式
で取得しています。
ファイル名にフィルタしてTriggerする条件をファイル名でコントロールすことが可能です。
例えば“samples/{name}.jpg”と設定しておけば拡張子がjpgのファイルの時にTriggerされます。
Blobのインプットバインディングは対象コンテナにBlob数が多くなると起動が遅くなるため注意が必要で
す。トリガー用のコンテナと保存用のコンテナを別に用意して、トリガー用コンテナから保存用コンテナ
にBlobを移動させるようにしましょう。
①
②
AzureFunctionsとBlob
11
[FunctionName("Function1")]
[StorageAccount("AzureStorage")]
public static void Run01(
[BlobTrigger("samples/{name}")]Stream myBlob,
[Blob("samples-out/{DateTime}")]CloudBlockBlob outBlob,
string name, TraceWriter log)
{ outBlob.UploadFromStream(myBlob); }
■ Blobアウトプットバインディング
上記の例ではAzureStorageのSamplesコンテナに任意のBlobが作成されたらStream形式で取得し
samples-outコンテナに現在日付でBlob名を置き換えて保存します。
アウトプットバインディングを設定すると出力先の情報がバインドされます。
{DateTime}の個所は{rand-guid}と置き換えると現在日付ではなくGUIDになります。
{DateTime} : 2018-09-20T18-00-00Z
{rand-guid} : 62473a8d-e1f5-4c35-8841-5dad1f67075b
AzureFunctionsとBlob
12
■ バインディングのメリット
通常では上記のように記載しないとAzureStorageBlobにはアクセス出来ませんがバインディングを利用す
れば上記のコードを1行で表現してBlobにアクセスできます。
バインディングを利用することで記述量が少なくなるのはメリットです。
var accountName = "teststorage";
var accessKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var credential = new StorageCredentials(accountName, accessKey);
var storageAccount = new CloudStorageAccount(credential, true);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("samples");
CloudBlockBlob blob = container.GetBlockBlobReference("name");
AzureFunctionsとBlob
13
■バインディングのデメリット
AzureFunctionsのV1はWindowsAzureStorageバージョン7.2.1が設定されているため、このバージョン
を越えるAzureStorageをNugetするとバインディングが正常に起動しなくなります。
下記のようなエラーが出たときはAzureStorageのバージョンを確認しましょう。
因みにFunctionsのV2は8.6.0に設定されています。
またAttributeと型の組み合わせによって同じようなエラーがでます。
その時はエラー内容をよく読んでAttributeと型の組み合わせを確認しましょう。
AzureFunctionsとQueueStorage
14
タイプ トリガー 入力 出力 備考
Queue Storage ○ ○
[FunctionName("Function2")]
public static void Run(
[QueueTrigger("myqueue-items", Connection = "AzureStorage")]string myQueueItem,
TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
}
■ QueueTrigger
QueueTriggerはAzrueStorageQueueにキューイングされるとトリガーされます。
上記の例ではAzureStorageのmyqueue-itemsキューにキューイングされるとトリガーされキューに入力
されている情報を取得します。
QueueStorageにキューイングされた情報はランダムに処理されるために順序制約がありません。FIFO
を実現したい場合はServiceBusQueueを利用するのが通例ですが費用が高くなります。また、
ServiceBusQueueでもエラーが起きたときは順序保証がされません。
AzureFunctionsとQueueStorage
15
■ QueueTriggerとアウトプットバインディング
[FunctionName("Function1")]
[return: Queue("myqueue-items", Connection = "AzureStorage")]
public static string Run([QueueTrigger("myqueue-items", Connection = "AzureStorage")]string myQueueItem,
TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
return myQueueItem;
}
アウトプットバインディングできるのはJsonとしてシリアル化可能なオブジェクト、string、Byte[]、
CloudQueueMessageになります。上記の例ではmyqueue-itemsにキューイングした値をmyqueue-
itemsにアウトプットする内容になっています。これは悪い例でキューイングの無限ループになります。
別のストレージのQueueに出力するようにすればQueueによるDurableFunctionsでいうところの
FunctionChainのような動きを実現できるますが、Functionsで実装するのは大変なので
DurableFucntionsを利用したほうが良い場合の方が多いです。
AzureFunctionsとTimer
16
タイプ トリガー 入力 出力 備考
Timer ○
■ Cronの設定
LinuxのCrond式と違って秒単位まで明示的に記述する必要があります。
Cron式は[TimerTrigger(”%TimerCron%”)]と記述することで外出しすることが可能です。
例) “TimerCron” : “0 */5 * * * *”
Cronの設定に不慣れな場合はCheatSheetがあるので参考にしながら設定しましょう。
Azure Functions – Time Trigger (CRON) Cheat Sheet
https://codehollow.com/2017/02/azure-functions-time-trigger-cron-cheat-sheet/
[FunctionName("TimerTrigger")]
public static void Run(
[TimerTrigger("0 */5 * * * *")]TimerInfo myTimer,
TraceWriter log)
{
log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
}
AzureFunctionsとTimer
17
■ 実行時間のローカライズ
Cronの実行時間は基本的にUTC時間で実行されます。
TimeZoneを設定すればローカライズ時間で実行することが可能です。
TimeZoneの設定を利用する場合は「WEBSITE_TIME_ZONE」を利用します。
例)日本時間に合わせる場合 ”WEBSITE_TIME_ZONE” : “Tokyo Standard Time”
TimeZoneの種類については下記のサイトを参照してください。
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc749073(v=ws.10)
実行時間の設定時に-9時間して設定するという労力を減らせるので便利ですが、
きちんとWEBSITE_TIME_ZONEが設定されていないとUTC時間で実行されて障害の元になるので注意し
ましょう。
Disable Attributeのお話
18
Disable Attributeを利用することでトリガーの実行制御を行うことができます。
但し、トリガーによってはDisable Attributeが効かないトリガーもあります。
タイプ Disable 備考
Blob Storage 有効
HTTP 無効 HTTPトリガーはDisableがTrue,False限らずに有効にならない。
Queue Storage 有効
Timer 一部有効
Azureポータルからの実行はDisableが効かない。
逆に効かない方が検証がしやすいのでありがたい。
TimerトリガーのAuzreポータル実行やHTTPトリガーの実行から、明示的に実行する場合はDisable
Attributeが効かないと推測されます。
[FunctionName(“Function1")]
[Disable(“FunctionDisable”)] (アプリ設定に外出し 例 “FunctionDisable” : true)
public static void Run02(...
Disable Attributeのお話
19
Disable Attributeが効果を発揮するのはバージョニングの時です。
Deploy用SlotのFunctionsをDisable Attributeでコントロールして非稼働状態にします。
アプリ設定に外出しにしておくとコントロールが容易になります。
Deploy Slot Production Slot
Disable : True (非稼働) Disable : False (稼働)
Version2.0 Version2.0 Version1.0
Version1.0 Version2.0
Deploy
SWAP
デプロイ後に非稼働のた
めProduction SlotのV1と
同時に実行されない
スワップ後に非稼働のた
めProduction SlotのV2と
同時に実行されない
Disable Attributeのお話
20
Precompiledの場合、AzurePortal側での表示がすべて無効になる現象があります。
アプリ設定に外出しにするためのKEY名がfunction.jsonに記載されますが、Disabledプロパティがbool
型のためTrue/False以外の値を設定されるとポータル上では無効と表示されるようです。
機能に影響はないので問題はありません。
実際に業務で作成して運用している
Excel帳票を定期的に出力するFunctionsのお話
21
今時Excel帳票と思われるかもしれませんがまだまだ要望としてはあります。
要件としては定期バッチで出力タイミングの異なる7種類のエクセルを出力するです。
今回の要件をFunctionsで実現するために考慮したのは下記の項目です。
■FunctionsはV1を採用
■TimerTriggerで出力エクセル帳票毎にFunctionsを作成
■Cron式はアプリ設定でコントロールするために外出し
■バージョニングを行うためDisable Attributeを実装
■Disableの設定はアプリ設定でコントロールするために外出し
■エクセルテンプレートはAzureStorageで更新管理を行う
■エクセルテンプレートはBlobのインプットバインディングで読み込む
■出力するエクセル帳票は条件によって出しわけるためアウトプットバインディングは使用しない
■VisualStudio2017を利用しPrecompiled Functionsで実装
■CI/CDをVSTS(Azure DevOps)で運用
■メモリの使用量を考慮してFunctionsはAppServiceプランを採用
実行は深夜が多いのでリソースの効率化も考慮して管理画面で利用しているAppServiceに相乗り
実際に業務で作成して運用している
Excel帳票を定期的に出力するFunctionsのお話
22
TimerTrigger TimerTrigger TimerTrigger
OutputA OutputB OutputC
TemplateA TemplateB TemplateC
TimerTrigger TimerTrigger TimerTrigger
DeploySlot
SWAP
VSTSで
CI/CD
Azure Storage
Explore
VSで実装
管理画面からダウンロード
Template用ストレージ
出力用ストレージ
業務データストア
ProductionSlot
Input Binding
まとめ
23
Functionsは使い方を知れば知るほど便利になっていきます。
MSDNを熟読し実装に工夫をすれば幸せになれます。
V2もGAしたのでガンガン使っていきましょう!

Azure Functionsを業務利用する時の勘所