タイトルに書いたことが言いたいことの8割くらいです。あとは理由と対策を書いておきます。
TL;DR
- Azure Function に31文字以上の名前をつけて、かつスロットを使うとTimerトリガが発火しなくなることがある
- 対策はいくつかある: 名前を短くする、カスタムhost idを設定するなど(後述)
条件と問題
条件
- Azure Function に長い名前、特に31文字以上の長さの名前を付ける
- スロットを1つ以上作る (例: staging)
起きる問題
どこかのスロットの、TimerTrigger定義されたfunctionが一切起動しなくなる。ログを見ても何もない。
これはかなり怖いです。問題なく動いているコードを、スロットを作ってデプロイしたらそっちはなぜか動かない、という状態になります。アプリ自体は正常に起動しているようにしか見えず、でもtrigger historyに何も表示されません。他のトリガー(QueueTriggerなど)は問題なく動いており、Timerだけが止まった状態です。
何が問題か
Functionホストはストレージアカウント上のblobリースを使ってシングルトン管理をしており、各Functionごとにユニークである必要があります。このホストIDはデフォルトで以下の文字列になります。
- FunctionName/ListenerName (Productionスロットの場合)
- FunctionName-SlotName/ListenerName (Productionスロット以外の場合、半角ハイフンのあとにスロット名)
FunctionNameにはAzure Function名、ListenerNameはFunctionHost (WebJobsかHost.Functions) とメソッド名から作成されます。ただし、半角スラッシュより手前は最大で32文字までしか認められていないため、頭の32文字よりあとは切り捨てられます。しかもスラッシュ手前最後の文字はハイフン以外の英数字のみです。この制約により、Function名が31文字以上の場合、ホストIDがProductionスロットと競合します。Functionホストはリースを獲得できない場合はTimerトリガを一切起動しないので、いつまで経っても発火しないのです。
対策
30文字以下のFunction名に抑えることで上記の問題が起きる可能性は著しく下がりますが、問題に気が付いたときってもうFunction名変えられる状態ではないことが多いんじゃないかなと推測します(経験談)。組織ごとに命名規則があったりしますしね。なので、そういうときには環境変数 AzureFunctionsWebHost__hostid にスロット毎にユニークな文字列を設定することで問題を回避できます。要するに自動で作成されるホストIDを上書きするわけですね。わかれば簡単です。
参考資料
だらだらと書きましたが、上記はすべて公式ドキュメントに書いてあります。書いてあるんですが、知らないとたどり着けないんですよねぇ…
おまけ
個人的にこの問題にハマったので、Functions用のDiagnose & Solveがこの問題を検出できるように改善しておきました。ポータルメニューの Diagnose & Solve > Functions that are not triggering を選択すると、この問題が起きていたら見つけてくれるはずです。
Views: 0