Microsoftのプリンシパルエンジニアリングマネージャである Chris Gillum氏は、QCon San Franciscoで"Serverless Programming Models in Azure Functions"と題してセッションを行い、Microsoftのサーバレスコンピューティング実装であるAzure Functionsを使用した2つのステートフルプログラミングモデル — ワークフローとアクタ — について論じた。
Gillum氏のセッションは、Azure Functionsが本質的に"サーバレス"である、という話題から始まった。すなわち、ホスティング環境は自動スケーリングをサポートしており、関数の実行には従量制の課金が行われる。AWS LambdaやGoogle Cloud Functionsなどのファンクション・アズ・ア・サービス(FaaS)プラットフォームと類似したサービスだが、それらと違うのは、データソースやディスティネーションからコードを分離する、"バインディング"という抽象化を備えていることだ。これがAzure Functionsのプログラミングモデルの中心であり、このコンセプトによって、より高度なプログラミングモデルのバインディングが可能になっている。
次にGillum氏は、LambdaやAzure Functionsなどの関数を実行する上で適用すべき原則とベストプラクティスを挙げた。
- ステートレスでなければならない
- 他の関数を呼び出してはならない
- 実行することはひとつだけでなくてはならない
最初の原則である"ステートレスであること"に対してGillum氏は、Microsoftは実際には、Durable Functionsを通じて関数のステートをサポートしている、と述べた。Durable Functionsは、オープンソースのDurable Task Frameworkをベースとした、Azure Functionsのエクステンションである。Durable Functionsを使うことで、長時間実行型の、信頼性の高いサーバレス・ワークフロー・アズ・コードを記述することが可能になる。
例として氏は、いわゆる"オーケストレーション"関数を使って関数のチェーンを可能にする方法を紹介した。この関数内では、開発者が必要とするワークフローステップをコーディングすることができる。例えば、他の関数を呼び出して作業を行うことが可能だ。実際の処理を行う関数は"アクティビティ"関数と呼ばれる。
オーケストレーション関数は、Azure Storageキューへのメッセージの到着によって起動される。メッセージをピックアップすると、適切なオーケストレーションコードが実行されて、新たなメッセージが別のコントロールキューに送出される。アクティビティ関数がそのメッセージを拾うと、オーケストレーション関数はメモリからアンロードされる — 従ってリソースを消費することはなくなる。ステートはイベントソーシング経由で処理される。すなわち、関数のコードがawait
状態になると、Azure Storageテーブルへのイベント書き込みが行われる。アクティビティ関数が実行されると、新たなメッセージが別のコントロールキューに送信されて、新たなイベントがテーブルに記録される。オーケストレーション関数がそのメッセージをピックアップすると、アクティビティ関数の起動までのサイクルが新たに開始されるのだ。
イベントソーシングを採用することで、例えば.NETとJavaScriptのように、さまざまな言語のサポートが可能になった、とGillum氏は述べている。氏はさらに、オーケストレータのコードが遵守しなければならないルールをいくつか紹介している。
- ルール#1: 乱数や現在日付/時刻などに依存するロジックを記述しないこと。
- ルール#2: オーケストレータ関数内でI/Oやカスタムスレッドのスケジューリングを直接行わないこと。
- ルール#3: 無限ループを記述しないこと。
- ルール#4: #1,#2,#3のルールには、組み込みの回避策を使用すること。
次にGillum氏は、別のステートフルパターンとして。複数の関数を並列して実行し、オーケストレータが全関数の終了を待つ"ファンアウトとファンイン(fan-out and fan-in)"を紹介した。すべてに並列タスクが完了すると、最後の集約(aggregation)ステップが直ちに起動される。氏はこのパターンのカスタマユースケースを紹介した後、Durable Functionsの他のワークフローパターンとして、Human InteractionとAggregatorの2つを説明した。
ワークフローの他にも、Durable Functionsでは、アクタプログラミングモデルを活用することも可能だ。Gillum氏は言う。
アクタはオーケストレーションとともに、Durable Functionsのファーストクラスのコンセプトになります。ユーザはこれら2つのステートフルプログラミングモデルを、必要に応じて、同じアプリケーション内で使用することができます。
アクタはいわゆるエンティティ関数として表現されるもので、オーケストレーションと同じように起動することができる。エンティティ関数の記述にはC#や、その他のJavaScriptなどの言語を使用することができる、とGillum氏は説明した。さらに氏は、エンティティのコンセプトとサンプルコードについて解説した上で、仮想アクタとの類似点として、次のものを挙げた。
- エンティティID経由でアドレス可能である。
- 実行は直列的で、一度にひとつである。
- 呼び出し時ないしシグナル時に暗黙的に生成される。
- オペレーションを実行しない場合は、メモリから静かにアンロードされる。
しかしながらGillum氏は、Durable Functionsのエンティティ関数はAkka.NetやOrleansのような"アクタ"フレームワークではない、とも述べている。これらのフレームワークとの違いは、次のようなものだ。
- サーバレスである
- レイテンシよりも堅牢性(durability)重視
- 信頼性が高く、順序を持ったメッセージング
- メッセージタイムアウトがない
- 一方向メッセージである
- デッドロックが発生しない
- オーケストレーションとの統合
この講演を含むカンファレンスの大部分のプレゼンテーションは記録されていて、今後数ヶ月にわたってInfoQで公開される予定である。次のQCon London 2020は、2020年3月2~6日に予定されている。