何かと(一部?で)話題になる Azure Functions のコールドスタートが非常に遅いという話ですが、App Service Team Blog にてどのような動きとなっているか解説記事が公開されていました。
ぶちぞう RD のアンテナは高いので、フォローしておくと有益な情報が得られます。
https://blogs.msdn.microsoft.com/appserviceteam/2018/02/07/understanding-serverless-cold-start/
曰く 20 分ぐらいアイドルだとインスタンスが落とされて、次からはコールドスタートになるようです。
Azure Functions というか App Service のコールドスタートを早くするために、予め Function Runtime を ngen しておいたり、placeholder を使ってプロビジョニングを短縮してるようです。
常に ping を飛ばしてコールドスタートに落ちないように維持する方法はありますけど、ぶちぞう RD の言う通りスケールした時に問題となるケースが出てきます。
pingとばして落とさないはいいとして結局スパイクしてインスタンス増えるとあかんので起動速度あげる努力はいるのう
— こすもす.えび (@kosmosebi) 2018年2月7日
コールドスタートを早くする努力をしようとしても、Kudu にアクセスした瞬間 Web App はプロビジョニングされてしまうので、コールドスタートを検知するのは地味に難しいという罠があります。
なので今回は Application Insights の Live Metrics Stream を使って試しました。いろいろ試した結論としては、ちゃんとコールドスタートを検知できているように思います。
送られてくるログを確認すると、ロックを取ったり拡張機能を読み込んだりという処理が見えます。
ウォームスタートでは行われない処理なのと、前後でインスタンス ID が変わっているので別のマシンに移動したことが分かります。インスタンスが落ちると Servers から消えるので分かりやすいです。
実際に Application Insights から消えた後に HTTP リクエストを投げると 5-10 秒ぐらいかかるので、コールドスタートになっていると考えられます。w3wp が死んでから、App Service 自体が落ちるまでは多少のタイムラグがありそうです。
.NET Core 版を実行した時のログでは host.ini が読み込まれてから、実際に Function が実行されるまで Application Insights 上の時間で 6 秒ぐらいかかっているので、やはり読み込み周りが辛いみたいです。
まだ .NET Core 版は最適化されていないらしいので、GA 時には改善されているはずですが、結局のところ Azure Functions の Consumption Plan が遅い原因は Azure Files だろうと思っています。
本末転倒ですが App Service Plan で Premium V2 に Azure Functions を作れば劇的に改善しそうです。