本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーはPerlとAzureが好きなわいとんさんで、テーマは「サーバレスでもPerl」です。
サーバレスという言葉が出てきて数年が経過しましたが、Perlとは縁のないものだと思っていませんか? 本稿では、Microsoft Azure Functions(以下、Functions)上でPerlスクリプトを使って顔認識を行います。動作するまでの流れを通じ、その可能性を感じていただければ幸いです。
本稿のサンプルコードは、本誌「WEB+DB PRESS Vol.109」のサポートサイト から入手できます。
Microsoft Azure Functions ── AzureにおけるFaaS
Microsoft Azure(以下、Azure)は、Microsoftが提供するクラウドプラットフォームです。Amazon Web ServicesやGoogle Cloud Platformと同様に、IaaS(Infrastructure as a Service )としてVM(Virtual Machine 、仮想マシン)やネットワークをクラウド上で構成し、動作させたいソフトウェアを設定して利用できます。また、DBaaS(Databaseas a Service )のAzure Cosmos DBや検索サービスのAzure Searchなど、一通りのSaaS(Software as a Service )もあります。
今回紹介するFunctionsは、AzureにおけるFaaS(Function as a Service )です。
サーバレスの中心にFaaSあり
サーバレスとはサーバレスアーキテクチャのことを指し、フルマネージドなクラウドサービスを利用して、システム稼働に必要なリソースを動的に確保するよう構築し、運用する方法となります。サーバレスを構成する要素の中心がFaaSです。
FaaSの特徴
FaaSとは、プログラム実行環境を提供するクラウドサービスで、関数と呼ばれる単位でプログラムを管理します。FaaSは次の特徴を持ちます。
関数が稼働した分だけ課金
FaaSでは関数が稼働した分だけ課金されます。特に、時間あたりのCPU、メモリ使用量が増えるほど、課金額が高くなる傾向にあります。
常時課金されるIaaSやPaaS(Platform as a Service )と比べ、関数自体の処理時間や、CPUやメモリの使用量を減らすとお得になります。
OS/VMの管理は不要
FaaSはオンプレミスやIaaSと違い、OSやVM、ネットワークを自分で管理する必要がありません。
OSのアップデートやセキュリティパッチ、VMやネットワークはクラウドベンダーが管理してくれますので、関数の開発に意識を集中できます。作成した関数のパフォーマンスは、利用者の責任において監視、管理する必要があります。
関数の起動にはトリガが必要
FaaSのもう一つの大きな特徴として、イベントドリブンであることが挙げられます。FaaSでは、関数の起動にはクラウドベンダーが提供する各種トリガの中から1つ指定する必要があります。トリガが引かれるというイベントが発生しない限り、関数は起動されません。
FunctionsのPerlサポート
Functionsは、ランタイムのバージョンに応じてv1とv2に大別され、それぞれサポート言語が異なります 。言語のバージョンや後述するトリガの仕様、バインディングの仕様にも違いがあります。
しかし、v1とv2ともにPerlはサポートされていません。では、どのようにPerlを実行させるのでしょうか。実は、FunctionsにはPerl(執筆時点2019年1月ではx86_64-msys-thread-multi v5.26.2)が付属しています。Functionsはgit
に対応しており、git
をインストールするためにはPerlが必要だからです。
筆者が検証した限り、Functions v1ではbash経由でPerlプログラムを関数として実行できていますが、v2ではPerlの動作を確認できていません。そのため、ここからはv1を前提に解説します。
プロジェクトのファイル構成
Functions v1でPerlプログラムを関数として利用する場合、プロジェクトのファイル構成は次のとおりです。
./プロジェクト名
├── host.json
├── proxies.json
└── 関数名
├── function.json
├── run.sh
└── task.pl
1つのプロジェクトには複数の関数を定義できます。複数定義する場合、関数ごとに関数名フォルダを用意します。
各関数名フォルダには、関数のトリガとデータ入出力を定義するfunction.json
、関数本体となるrun.sh
、そして関数本体から呼び出されるPerlスクリプトのtask.pl
が必要となります。
また、関数名フォルダと同階層に、Functions内すべての関数に対する設定ファイルhost.json
と、HTTPプロキシ設定ファイルproxies.json
を配置できます。
なお、本稿ではhost.json
とproxies.json
は利用しません。これらのファイルについて知りたい人は、公式ドキュメントのhost.jsonのリファレンス とAzure Functionsプロキシの操作 をご確認ください。
関数起動のためのトリガ
Functionsでは、関数の起動トリガをfunction.json
で指定します。トリガには、以降で紹介するHTTPトリガ、Timerトリガ以外に、Cosmos DBトリガやBlobトリガ、Queueトリガなどがあります。
HTTPトリガ ── 関数がWeb APIとして動作
HTTPトリガを指定すると、FunctionsはHTTPリクエストを受け取ったときに関数を起動します。その際、HTTPリクエストボディはファイルとして、クエリパラメータとHTTPヘッダは環境変数として、それぞれ関数に引き渡されます。
起動された関数は、出力ファイルに対してHTTPレスポンスをJSON形式で書き込みます。それを受けてFunctionsは、出力ファイルの内容をHTTPレスポンスとしてクライアントに返します(図1 ) 。
図1 HTTPトリガ
HTTPトリガで起動される関数では、function.json
は次のようになります。
HTTPトリガで起動される関数のfunction.json
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"authLevel": "anonymous"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
],
"disabled": false
}
Timerトリガ ── 時間指定バッチとして定期的に起動
Timerトリガは、cron式で指定されたタイミングに基づき関数を起動します(図2 ) 。このcron式は通常のcron式に加え、秒単位での起動指定ができます。Timerトリガで起動される関数では、function.json
は次のようになります。
Timerトリガで30分おきに起動される関数のfunction.json
{
"bindings": [
{
"type": "timerTrigger",
"direction": "in",
"name": "timer",
"schedule": "0 */30 * * * *"
}
],
"disabled": false
}
図2 Timerトリガ
データの入出力を行うためのバインディング
Functionsではバインディングというしくみで入出力に対応できます。バインディングは、トリガと同様にfunction.json
で設定します。
先ほどHTTPトリガのfunction.json
を示しましたが、クライアントに対してHTTPレスポンスを返す必要があるため、HTTPバインディングを使ってレスポンスを出力するよう定義してあります。バインディング入出力の向きはdirection
で指定され、in
なら入力、out
なら出力となります。バインディングにはHTTP以外に、Cosmos DBやBlob Storage、Queue Storageなどがあります。
Functions v1のトリガとバインディングに関する詳細は、公式ドキュメントのAzure Functionsのトリガとバインドの概念 を参照してください。
<続きの(2)はこちら 。>
特集1
イミュータブルデータモデルで始める
実践データモデリング
業務の複雑さをシンプルに表現!
特集2
いまはじめるFlutter
iOS/Android両対応アプリを開発してみよう
特集3
作って学ぶWeb3
ブロックチェーン、スマートコントラクト、NFT