Azure Central Azure Functions入門[PR]
サーバーレスアーキテクチャとは? Azure Functionsで初めての開発[PR]
最近、注目を集めている「サーバーレスアーキテクチャ」の概要と、Azure Functionsを使ったサーバーレス開発の基礎をコンパクトに解説。トリガーや入力/出力のバインディングを作成してみよう。
サーバーレスアーキテクチャとは
サーバーレスアーキテクチャ(Serverless Architectures)というキーワードが使われるようになったのは、AWSのLambdaがリリースされたことが発端だろう。Martin Fowlerのブログ記事(英語)から引用すると、サーバーレスアーキテクチャには2つの意味合いがある。
- Backend as a Service(BaaS): SPA(Single Page Application)形式のWebアプリケーションやモバイルアプリケーションから利用する、クラウド上のバックエンドサービス(ストレージや認証など)
- Function as a Service(FaaS): 自分で書いたコードがイベント駆動で実行されるステートレスなサービス
AWSのLambdaを含め、GCP(Google Cloud Platform)のCloud FunctionやIBM BluemixのOpenWhiskなど、クラウドベンダー各社が相次いでリリースしたサーバーレス環境は、後者のFaaSのことを指している。
サーバーレスといっても、「サーバーがない」という意味ではない。「自分でサーバーを管理する必要がない」というとPaaSのように思えるかもしれないが、それよりも高いレベルのアーキテクチャである。PaaSはWebアプリケーションをデプロイするので常にサーバーを意識するが、サーバーレスではロジックだけをアップロードしておけば、それがイベント駆動で実行される。
どんなシナリオにも適用できるわけではないが、ちょっとした定期実行ロジックやマイクロサービス(Microservices)アーキテクチャの実現手段として、知っておいて損のないアーキテクチャといえるだろう。
Azure Functionsとは
Azure Functionsの概要
Azure Functionsは、前述したサーバーレスと呼ばれるサービスであり、アプリケーションを実行させるサーバーの構築や保守を行う必要がない。このため開発者は、「何らかのトリガーが発火した時に実行されるロジック」の開発だけに集中することができる。
APIを作ってクラウド上で公開する場合、.NETであればASP.NETのアプリケーションを開発してAzure Web Appsにデプロイする方法が一般的である。この場合、公開するAPIの数にかかわらず、アプリケーション自体の開発や運用のコストはそれほど変わらない。しかしマイクロサービスアーキテクチャを適用してサービスを分割した際には、稼働するサーバー数が増えていくことで運用や利用料金のコストが高くなってしまうことが課題となる。
また、1日に1回だけ実行するような定期実行のAPIを作る場合には、サーバーを24時間365日保守して料金を払うことに無駄を感じることも多いだろう。
このような課題を解決してくれるのが、イベント駆動型サービスのAzure Functionsである。2016年3月の開発者カンファレンス「Build 2016」(マイクロソフト主催)でプレビュー版が発表され、2016年11月のオンラインカンファレンス「Connect(); // 2016」(マイクロソフト主催)でGA(正式リリース)した。よって、実案件で今すぐ利用開始することが可能だ。
トリガーとバインディング
イベント駆動型サービスは、何かしらのアクションをきっかけに処理が実行され、その結果を何かしらの方法でアウトプットするサービスである。このような一連の処理において本質となるロジック以外の部分(=きっかけをハンドルする部分や、入力を受けたり、出力したりする部分)をそれぞれ独自に実装する手間を省く機構として、Azure Functionsではトリガーとバインディングが提供されている。
例としていくつかのシナリオを考えてみよう。
- スケジュールを設定して定期実行する
- Azure StorageのQueueメッセージが追加されたら、BLOBにファイルを作成する
- HTTP(WebHook)リクエストを受けて、メールを送信する
トリガーは緑色の背景色、出力へのバインディングはオレンジ色の背景色で示している。このようなシナリオにトリガーと入力/出力のバインディングを活用することで、実行されるロジックの開発に注力できるというわけだ。
Azure Functionsでは、多数のトリガーとバインディングをサポートしているので(表1.1)、さまざまなシナリオで活用できるだろう。
種別(Type) | サービス(Service) | トリガー(Trigger) | 入力(Input) | 出力(Output) |
---|---|---|---|---|
スケジュール(Schedule) | Azure Functions | ○ | - | - |
HTTP(REST / WebHook) | Azure Functions | ○ | - | ○ |
BLOB | Azure Storage | ○ | ○ | ○ |
キュー(Queues) | Azure Storage | ○ | - | ○ |
キュー(Queues) | Azure Service Bus | ○ | - | ○ |
トピック(Topics) | Azure Service Bus | ○ | - | ○ |
テーブル(Tables) | Azure Storage | - | ○ | ○ |
No-SQLデータベース(DB) | Azure DocumentDB | - | ○ | ○ |
ストリーム(Streams) | Azure Event Hubs | ○ | - | ○ |
プッシュ通知(Push Notifications) | Azure Notification Hubs | - | - | ○ |
SaaSファイル(File) | Dropbox、Google Driveなど | - | ○ | ○ |
SaaSテーブル(Table) | DB2、Salesforceなど | - | ○ | ○ |
メール(Mail) | SendGrid | - | - | ○ |
SMS | Twilio | - | - | ○ |
対応言語
Azure Functionsは、複数の開発言語をサポートしているが、メインはC#とJavaScript(Node.js)の2つとなる。
F#、Python、PHP、Batch*1、Bash、PowerShellなどの開発言語もサポートしているが、一部のトリガーやバインディングしか対応していないので注意してほしい。
- *1 Batch(バッチもしくはバッチコマンド)とは、複数のコマンド列を記載したWindows用のシェルスクリプトのこと。ちなみに「Batch」の後に記載されている「Bash」や「PowerShell」も同様にシェルスクリプトである。
課金モデル
Azure Functionsには、2種類の課金モデルがある。
1Consumption Plan:
Azure Functions専用の課金モデルであり、サーバーレスアーキテクチャらしいモデルである。実行時間と実行回数の両方が課金対象となり、毎月の無償枠を超えると課金される。
2Classic App Service Plan:
Azure App Serviceにある従来の課金モデル(Free/Basic/Standard/Premium)である。Azure Functions自体には課金されないので、Azure WebJobs(Webジョブ)に似た使い方となる。Azure Web Appsにデプロイしたアプリケーションと共存させたいときに選択するとよいだろう。
課金モデルの詳細については、公式サイトを参照してほしい。
Azure Functionsで初めてのサーバーレス開発
さて、サーバーレスアーキテクチャとAzure Functionsの概要が一通り分かったところで、実際に開発を試してみよう。
Azure Functionsを作成する
Azureポータルを開き、左側のハブメニューから[新規]を選択して、[Compute]から[Function App]を選択する。図1のブレードが表示されるので、アプリ名やリソースグループを入力して作成しよう。
Azure Storage キューをトリガーとする関数を作成する
まずは、シンプルで分りやすいAzure Storage キュー(Queue)をトリガー(Triggers)とする関数(=ファンクション、Function)を作成してみよう。
先ほど作成したFunction Appのブレードを開き、左側のハブメニューから[新しい関数]を選択し、[言語]欄で「C#」、[シナリオ]欄で「データ処理」を選択してテンプレートを絞り込む。「QueueTrigger-CSharp」のテンプレートを選択し、以下のような内容で新しい関数を作成する。
- [関数名の指定]欄: 任意の名前を指定(本稿の例では「QueueTriggerCSharp1」)
- [構成]-[Azure Storage キュー trigger (myQueueItem)]の、
- [キュー名]欄: 任意の名前を指定(本稿の例では「myqueue-items」)
- [ストレージアカウント接続]欄: 右横の[新規]リンクボタンをクリックして「function~~」のような既存のストレージを選択する(これにより、そのストレージへの接続文字列がFunction Appのアプリケーション設定に登録される)
これにより、次のようなコードが作成される。
using System;
public static void Run(string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
}
|
この関数のコード(=メインとなるロジック)では、キューに追加されたメッセージを加工して、ログに出力している。
Azure Functionsの左側のハブメニューから[<関数名(例:QueueTriggerCSharp1)>](以下、[関数項目])-[統合]を選択すると、[トリガー]と[入力]/[出力]のバインディングを変更するためのエディターが表示される。このエディターは、標準(図2)と詳細(図3)の2種類が提供されており、詳細エディターを使うとJSON形式で直接編集できる。なお、[詳細エディター]と[標準エディター]の切り替えは、右上のリンクボタンから行える。
詳細エディターを開いて内容を確認してみよう。トリガーと関数の引数は、次のような構成となっていることが分かる。
関数の実行を試してみよう
それでは、この関数を実行して、期待通りの結果になるかを試してみよう。先ほどのロジックによると、myqueue-items
というキューにメッセージを追加してやれば、トリガーが発火して関数が実行され、加工されたメッセージがログ出力されるはずだ。
Azure Storageの操作(ここではキューへのメッセージ追加)は、Microsoft Azure Storage Explorerなどのツールを使うとよいだろう。対象となるAzure Storageに新規キュー(本稿の例では「myqueue-items」)を作成して、任意のメッセージを追加してみよう。
もしくは、ブラウザ上で[関数項目]-[開発]の[実行」ボタンからテスト実行することも可能だ。図5は実際にテスト実行して、キューに「sample queue data」というメッセージを追加した際に出力されたログの例である。キューのメッセージは、上部の[テスト]ボタンをクリックした後の[要求本文]で変更できる。
ログの内容は、図5のように[関数項目]-[開発]の[ログ]ボタンで確認できる。ただし、このログ表示機能は開発用なので、本番時には、基本的に[関数項目]-[モニター]から確認することになる。
Azure Storage キューの出力のバインディングを追加する
次に、Azure Storage キューの出力(アウトプット、Output)のバインディングを追加してみよう。
[関数項目]-[統合]の[標準エディター]で、上部の[+新しい出力]を選択し、テンプレート一覧から「Azure Storage キュー(Queue)」を選択して、[選択]ボタンをクリックする。これにより図6の画面となるので、以下のような内容で出力バインディングを設定する。
- [Azure Storage キュー output (outputQueueItem)]の、
- [メッセージ パラメーター名]欄: 任意の名前を指定(本稿の例では「outputQueueItem」)
- [キュー名]欄: 任意の名前を指定(本稿の例では「outqueue」)
- [ストレージアカウント接続]欄: 任意のストレージ接続文字列を選択(本稿の例では「function~~」)
出力のバインディングと関数の引数は、次のような構成となっている。
キューに出力するには、out
キーワードを付けたoutputQueueItem
の引数を関数のRun
メソッドに追加して、この引数に出力したい文字列をセットすればよい。ブラウザ上で[関数項目]-[開発]を開き、リスト2のようにコードを変更して[保存]ボタンをクリックすると、「Compilation succeeded.」とビルドが成功したことがログに表示されるはずだ。
using System;
public static void Run(string myQueueItem, out string outputQueueItem, TraceWriter log)
{
outputQueueItem = myQueueItem + "(next step)";
}
|
このコードでは、キューに追加されたメッセージに「next step」の文字を付加して、出力用のキューにメッセージを追加している。
関数の実行を試してみよう
それでは、出力のバインディングを設定した関数を実行して、期待通りの結果になるかを試してみよう。
Microsoft Azure Storage Explorerを使って、「myqueue-items」というキューに「sample queue data」というメッセージを追加すると、「outputqueue」というキューにメッセージが追加されることを確認できる(図8)。
【コラム】Azure FunctionsのC#エクスペリエンス
Azure Functionsでは、.NETコンパイラープラットフォーム(Roslyn)のScripting APIが利用されているため、ブラウザ上でC#のコードをビルドしたり実行したりできる。
ここで紹介するシンプルな実装以外にも、自分が作成したアセンブリを参照できたり、NuGetのライブラリをインストールしたりと、実運用を想定した使い方ができる。
詳細については、公式サイトを参照してほしい。
Azure Storage BLOBの入力のバインディングを追加する
最後に、Azure Storage BLOBの入力(インプット、Inputs)のバインディングを追加してみよう。
[関数項目]-[統合]の[標準エディター]で、上部の[+新しい入力]を選択し、テンプレート一覧から「Azure Storage BLOB」を選択して、[選択]ボタンをクリックする。これにより図9の画面となるので、以下のような内容で入力バインディングを設定する。
- [Azure Storage BLOB input (inputBlob)]の、
- [BLOB パラメーター名]欄:任意の名前を指定(本稿の例では「inputBlob」)
- [パス]欄: BLOBから読み込むファイル名をトリガーとなるキューのメッセージで指定させたいので、「incontainer/{name}」→「incontainer/{queueTrigger}」に変更しておこう。この
{queueTrigger}
(QueueTrigger)とは、関数作成時のテンプレートで選択したトリガー種別で、図4のJSON設定コードでは「"type": "queueTrigger"」と表現されている。ちなみにこの{queueTrigger}
のような、パスの名前パターンについては「Azure Functions Storage blob bindings | Microsoft Docs(英語)」を参考にしてほしい - [ストレージアカウント接続]欄: 任意のストレージ接続文字列を選択(本稿の例では「function~~」)
入力のバインディングと関数の引数は、次のような構成となっている。
関数のRun
メソッドの引数にinputBlob
を追加することで、BLOBから読み取ったデータを取得できる。今回の例では、BLOBのファイルから読み取った文字列を、出力用のキューに追加するようにしてみよう。これには、[関数項目]-[開発]を開き、リスト3のようにコードを変更して[保存]ボタンをクリックすればよい。
using System;
public static void Run(string myQueueItem, string inputBlob, out string outputQueueItem,TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
outputQueueItem = inputBlob;
}
|
関数の実行を試してみよう
それでは、入力のバインディングを設定した関数を実行して、期待通りの結果になるかを試してみよう。
あらかじめ、「incontainer」というBLOBコンテナー(Container)に「Demo.txt」というテキストファイルをアップロードしておく。このテキストファイルには、「Hello Azure Functions!」という文字を記載しておこう(図11)。
キューに「Demo.txt」というメッセージを追加すると、BLOBからファイルが読み込まれ、「outqueue」にメッセージが追加される(図12)。
まとめ
Azure Functionsを活用したサーバーレス開発は、これからのクラウド開発で押さえておきたいアーキテクチャの一つである。
簡単で便利なサービスは、細かい部分の調整ができずに実案件で採用することが難しいものも多いが、Azure Functionsは便利かつ自由度が高い。その理由は、Azure App Serviceに追加されたサービスであり、WebJobsを拡張したサービスだからである。
Azure Functionsの実行環境は、Azure Web Appsと同じなので、
- App Settings/Connection Strings
- Advanced Tools/App Service Editor
- Remote Debug
などの同じ機能を使うことができる。
どんなシナリオにも適用できるわけではないが、ちょっとした定期実行ロジックやマイクロサービスアーキテクチャの実現手段として、活用を検討してみることをお勧めしたい。
※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
1. 【現在、表示中】≫ サーバーレスアーキテクチャとは? Azure Functionsで初めての開発[PR]
最近、注目を集めている「サーバーレスアーキテクチャ」の概要と、Azure Functionsを使ったサーバーレス開発の基礎をコンパクトに解説。トリガーや入力/出力のバインディングを作成してみよう。
2. 写真で年齢判定するサーバーレスなLINE Botを作ろう(Face API使用)[PR]
画像認識サービスを提供するCognitive Servicesと、低予算で手軽にプログラムが動かせるAzure Functionsを組み合わせれば、面白いLINE Botが手軽に作成できる。その開発方法を一通り説明する。
3. Visual Studioで始めるサーバーレス「Azure Functions」開発入門[PR]
最近注目されているサーバーレスの開発をVisual Studioで行おう! 環境準備から、Function App(関数アプリ)の作成、Azureへのデプロイと実行、さらに外部ライブラリや自作ライブラリの活用まで、基本的な開発方法を解説する。
4. サーバーレス「Azure Functions」をスケジュール実行する方法(cronジョブ構文)[PR]
バッチジョブなどでスケジュール実行したいというニーズは多いだろう。サーバーレスでFunctionをスケジュール実行する方法を解説。cron構文によるスケジュールの指定方法も説明する。
5. 設計時に使えるAzure/AWSサービス・アイコン集とダウンロード方法[PR]
クラウド上のシステムやサービスを設計する際には、視覚的に分かりやすいアイコンを使おう。アイコンセットのダウンロード方法を示し、各アイコンを用いてAzure/AWSサービスの対応一覧表をまとめる。