本記事はFIXERが提供する「cloud.config Tech Blog」に掲載された「覚えておきたい!Azure Functionsを使う際のTips」を再編集したものです。
こんにちは。半年前に買った車がぶっ壊れたりした石川です。無料で修理してもらいました。
車はどうでもいいんで今回はAzure Functionsを使うときに覚えておきたいことの話です。
Functions便利ですよね。便利が故になんでもFunctionsで処理させたくなります。
Timer Triggerを使ってバッチ処理とか、Http Triggerを使って軽いAPIとか、Queue Triggerを使って大量データの処理とか。
ともかくいろんな使い道があります。
とても便利なのですが、サーバーレス特有の “覚えておいた方がいいこと” というものがあるので紹介します。
Timer Triggerの起動時の挙動
Timer Triggerは時間をトリガーとして動き出すトリガーです。
例えば
・朝9時に動き出す
とか
・朝10時と夕方17時に動き出す とか。
さっくり日時を起点に動き出すものを作るにはとても便利なのですが、以下の場合にはちょっとした注意が必要です。
・アプリをデプロイする
・停止してあるFunctionsを起動する
・再起動する
Azure Functionsは作成時にStorage Accountが自動で作成され、そこで実行に必要なファイルを配置/保持します。
ちょっと見てみましょう。
Azure FunctionsはTimer TriggerがあるとTriggerごとにファイルを生成し、そこで前回実行日時、次回実行日時、ファイルの最終更新日時を保持します。
見やすくしたものは↓のような感じ。
{
"Last": "2021-01-01T00:00:00.0000000+00:00(最終実行日時UTC)",
"Next": "2021-01-01T00:00:00.0000000+00:00(次回実行日時UTC)",
"LastUpdated": "2021-01-01T00:00:00.0000000+00:00(最終更新日時UTC)"
}
Timer Triggerは起動時にこのファイルがあればこの情報を使い、動き出します。また、起動時に関数の引数として渡されるTimerInfo型の変数にはこのファイルから読んだ情報が入っています。
もし仮に、起動時にLastの時間を過ぎていた場合、当該のFunctionsが起動したタイミングで動き出すようになっています。
RunOnStartup
起動時に無条件で実行するかどうかを決める設定値です。
function.jsonかコード内で定義します。開発中には便利な機能ですがtrueでセットしたままデプロイすると起動時に動き始めます。
想定してない動きをしているときには真っ先に疑いましょう。
処理中の再起動
Azure FunctionsはFaaSサービスであるため、不定期に基盤の更新が行なわれます。
過去に遭遇したものだと、”基盤の更新により環境変数が変更され自動で再起動された”というものがあります。
環境変数の大文字スネークケースで定義されているものなど、Azureで自動設定されるものは動作中に変更されることがあるようです。
これが起きてしまうと、もちろんですが実行中のものは全て強制終了扱いとなり、処理が行なわれません。
Http Triggerなど数ms~数秒程度で済む処理ではリトライ実装などを行なえば問題ありませんが、Timer Triggerで1時間かかるようなものを動かしていた場合にはそうもいかないのでそういったことに使おうとしている場合には注意が必要です。
強制的な再起動 + Timer Triggerの前回実行チェックが働いて2回目が動き出した! なんてこともありえるので気をつけましょう。
(できるならデカい処理はもっと別のサービスを使うか細かく刻んであげましょう)
Timer Triggerの精度
Timer Triggerは基本的に指定した時間通り動きますが、偶発的に数ms~1s程度の誤差が生じる場合があります。
これまた、過去に遭遇した事例なんですが、“午前9時に実行するようにしていたら08:59:99.96xxxxに動き出し、想定外の挙動をした”といったことも起こり得ます。
時間基準で動くものをベタ書きするなって話でもありますが、遭遇してわかることもあるということで紹介させていただきました。
これの対策としては、
・当該関数をHttp Triggerに変更し、時間が担保できるものからHTTP経由で呼び出しを行なう
・トリガー時間を少しずらして設定する
ひとつめは少し使用していて、実際にHttp Triggerに変更し、Logic AppのHTTPコネクタで呼び出すといったことをしています。
ちなみに、Logic AppのHTTPコネクタには2分のタイムアウトがあるため、バッチのようなデカい処理をこれでやろうとするとLogic Appからは全て“失敗”表示になります。さらに、HTTPコネクタにはデフォルトでリトライが設定されてますので4回くらい叩かれます。愉快ですね。
2つめはあまりおすすめできないですね。これ。結局誤差起きますし。割と悪ノリで書いてます。
余談ですが、時間基準で動くものは、いい感じにHTTPのリクエストボディで動きを変えるように書き換えました。
Functionsのタイムゾーン
Azure FunctionsのデフォルトのタイムゾーンはUTC(+00:00)となっています。
これはアプリが取得できる時間にも関わってきます。
例えば、以下のコードを日本時間の午前9時に実行したときに出力される値は00:00:00です。
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
変更するには環境変数(Functionsブレード -> 構成)にWEBSITE_TIME_ZONEという名前でTokyo Standard Timeと設定してあげると良いです。
おわり
という感じで、Functionsを使ってきて遭遇したことの紹介みたいになってしまいましたが、覚えておくと嬉しいことの紹介でした。
それでは~~~~~~
・Azure Functions の概要 | Microsoft Docs
・Azure Functions のタイマー トリガー | Microsoft Docs
・再思考の一般的なガイダンス – Best practices for cloud applications | Microsoft Docs
石川 順平/FIXER
九州のとある高専卒のFIXER3年目。すき間時間でbotを作ったりAZ系の資格の勉強をしたりしています。まだまだAzure初心者です。趣味はゲームやったりバイクで出かけたりすること。