セミナー レポート:Azure Functions と キューで構築する NoOps スケーラブルバッチ処理基盤

クロスワープの大鷲です。

先日、渋谷ヒカリエ内の Azure Antenna で開催されたセミナー「Azure Functions と キューで構築するNoOpsスケーラブルバッチ処理基盤」に参加してきました。*1
今回はそのレポートをお届けします。
azure.connpass.com
スライド資料はこちらです。
slideship.com
ハンズオン資料はこちらにあります。
github.com

動機

これまで何本ものバッチ処理を書いてきました。
そうしたバッチの多くは、モノリシックなコンソール アプリとして作られています。
昨今、サーバーレス コンピューティング的な分野が隆盛する中で、そうした技術・知識を仕入れて、バッチ処理を刷新して行きたいと思い、参加しました。

MODD では現在、AWS を中心に*2利用しているので、バッチを刷新する際に Azure Function が選ばれる可能性は、実はあまり高くはありません。
おそらく AWS Lambda や AWS Batch 等の利用がまず候補に挙がるとは思うのですが、考え方としては応用可能だと思います。

縦と横

これまで作ってきたバッチは、スケジュールに従って起動すると、SQL でドカッとデータを取ってきて、それをループで処理していくという感じでした。
当日は、こうした従来型バッチ処理を「ループによる縦のイメージ」とし、対して、Functions を使うものを「ループさせずに横に広げるイメージ」と紹介されていました。

クラウド・PaaS のメリット

縦のイメージですと、処理にかかる時間は、処理するデータ件数に依存します。
バッチの実行スケジュールは余裕をもって設定してあり、現実に問題になったことはありませんが、急なデータ量の増大などがあった場合は、処理が間に合わないことも懸念されます。
クラウド サービスを使う場合ですと、そのようなことがあっても、ワンクリックで並列度を上げることが出来たり、(当日のハンズオンの範囲ではやりませんでしたが)処理負荷やキューの消化ペースなどに応じて動的・自動的に設定を変更できるのは強みだと思います。

また、ループや入出力処理を無くすことができる(プログラム内に処理コードとして記述することもできますが、Function のパラメーターの属性として宣言的に書くこともできます)ため、プログラム本体はビジネス ロジックだけに集中することができ、見通しが良くなります。

処理中にエラーになった場合、その起因となったキュー アイテムは、元のキュー名に -poison をつけたキューに自動的に移されます。
そこから元のキューに戻すだけで再度処理を実行できますので、リトライも容易とのことです。

Function のプラン

Functions には「従量課金プラン」と「App Service プラン」という2つのプランがあります。
従量課金プランは処理量が少ない場合は安いですし、自動スケールしてくれるので便利ですが、実行時間制限(最大10分まで)がありますし、コールド スタート問題もあります。
App Service プランですと、月額は固定で、実行時間制限はなく、コールド スタート問題もありません。性能に関しては、作っただけで自動的にとは行きませんが、ちゃんと設定してやれば自動スケーリングは可能です。

なお、App Service プランというは Azure Web Apps 等でも登場するワードですが、App Service プラン1つ=仮想マシン1台という理解でよいそうです。

CosmosDB

いわゆる NoSQL データベースです。
よく、複数の形式(SQL、MongoDB、グラフ DB など)をサポートしていると紹介され、それは事実ではあるのですが、データベースの作成時にどのタイプを使用するかは固定されるので、複数の形式を併用できるわけではありません。
複数リージョンへのレプリケーションといった一般的な特性はもちろんのこと、並列処理に強く、Function 等との相性が良いとのことでした。

Function を利用する場合、プロセスが極めて短命になるため、データベース アクセスにおいてはコネクション プーリングが効かないことが問題になると聞きます。
それも一因となって、Functions には CosmosDB バインドは標準で用意されていますが、SQL Database バインドはありません。
CosmosDB は Functions と相性が良いので、データベースとしては第一選択になります。

なお、CosmosDB は事前に「スループット」という値を設定する必要があり、処理はこの範囲内で行えるように設定・設計する必要があります。
処理コストは要求単位(Request Unit)という量で表現されます。クエリごとに消費する RU は異なります。
スループットは1秒当たりの RU で表されますので、あらかじめ計算しておく必要があります。

モニタリング

Function を作ると、関数のログは自動的に Storage に出力されるように設定されます。
これは、開発中はよいですが、実稼働環境で並列度を上げていくと、Storage へのアクセスがパフォーマンスのネックになってくるそうです。
そのため、運用に入る前に、Application Insights を使ったログ記録に移行すべきとのことでした。

全体の感想

タイトルに「NoOps」というワードが入っていましたが、これには違和感がありました。
質問したところ、開発だけでなく、監視まで Azure の仕組みを利用して可能だということを指して「NoOps」と称したとのことでした。
本来は「DevOps」の発展形として、インフラの調達から設定、スケールの調整、トラブル時の対応等が自動化されることによって、開発者がそれらを行うことが出来るようになり、Dev とは別の Ops という部隊が不要になるということを指した言葉だったはずです。
とはいえ、ハンズオンの範囲でこそやりませんでしたが、Azure はそうしたことを実現しようと思えばできるだけの機能を備えたものだということはわかりました。

*1:2か月も経ってしまいました。申し訳ありません。

*2:Azure もちょっと