Azure Central Azure逆引きリファレンス[PR]
Visual Studioで始めるサーバーレス「Azure Functions」開発入門[PR]
最近注目されているサーバーレスの開発をVisual Studioで行おう! 環境準備から、Function App(関数アプリ)の作成、Azureへのデプロイと実行、さらに外部ライブラリや自作ライブラリの活用まで、基本的な開発方法を解説する。
今、サーバーレスに注目が集まっている。開発者間での人気を裏付けるように、ここ数年の間にAWS Lambda/Google Cloud Functions/IBM Bluemix OpenWhisk/Azure Functionsと、メジャーなクラウドプラットフォームベンダーが次々とサーバーレス対応の新サービスを投入している。
「サーバーレスもしくはサーバーレスアーキテクチャ(Serverless Architectures)が何か」についての説明はこちらのの記事に譲るが(ちなみに筆者はざっくりと「イベント駆動型のプログラム実行環境」と認識している)、何がそんなに開発者の関心を引き寄せているのだろうか?
その良さは、一般的なクラウドプラットフォームのコンピューティングサービス(Amazon EC2やAzure Virtual Machines/App Serviceなど)のように、わざわざサーバーを立ち上げてプログラムを実行する必要がなく、Function(関数、プログラムの一機能)を動かしたいときだけ実行できることだ。その結果、開発者は運用作業から解放されて開発に集中できるだけでなく、(Azure Functionsの場合は)実行時間や実行回数に課金されるだけなので非常に安価になる。これらは開発者にとって非常に大きなメリットである。
筆者自身もAWS Lambdaが2014年11月に登場してその内容を知ったときに、とても興奮して社内でそのメリットを宣伝したことを覚えている。毎日動かすバッチ処理型のプログラムを社内(や個人)でたくさん持っているが、それらを動かすためだけにクラウド上のVM(仮想マシン)インスタンスを1つ借りるのもお金がもったいない気がして、社内にコンピューターを用意してできるだけお金をかけずに(※もちろん電気代はかかっている)運用していた。そういったプログラム類は、ほぼタダみたいな料金でAWS Lambdaに持っていけるのではないかと思ったからだ。
ただ、当初のAWS LambdaにはC#のサポートがなく、またAzureをメインに使っていたため、AWSのC#対応待ちか、AzureのLambda対抗サービス待ちとなっていた。2016年5月、ついにAzure Functionsが発表されたので、最近になってまずは手始めに個人ブログのバッチ処理プログラムの一つ(毎日1回実行)をAzure Functionsに移してみた*1(※ちなみに2016年12月よりAWS LambdaもC#をサポートしている)。移行したプログラムでは、Visual Studioを活用して開発・デプロイでき、多数の外部/自作ライブラリをインポートすることにも成功している。「ここまでできるのか、これはいい(料金は月間2円程度と激安)」と思った半面、(プレビュー版ということもあり)使い勝手がまだ洗練されておらず苦労した点もいくつかあったのも事実だ。
Azure FunctionsをVisual Studio(+C#)で開発する(図1参照)のはまだまだ発展途上の部分も多いと感じているが、「早くその組み合わせで開発したい」と考えている人も少なくないのではないだろうか。本稿では、筆者が体験したものをベースにそのノウハウを公開しようと思う(といっても今回は、Visual Studioを使用した場合のごく基本的な開発方法の部分について紹介する)。
- *1 例として示した「筆者によるAzure Functionsの使い方」は非常にシンプルなジョブ実行に過ぎないが、もちろんより高度かつ複雑なアーキテクチャの構築で活用することも考えられる。Azure Functionsの使い方や利用範囲は人によってさまざまに異なるので、示した事例だけが利用用途ではないことには留意してほしい。
Visual Studioを活用したAzure Functionsのローカル開発
本稿で紹介するのは「Visual Studioを活用したローカル開発」であり、Azure Functions開発の方法としては少し特殊なものと思っていただいた方がよい。基本的な開発手順では、下記のリンク先で示されているように、オンライン上で開発を完結させることができる。まずは基本を押さえたうえで本稿を読んでいただけるとうれしい。Azure Functionsの概念やAzure管理ポータルでの操作方法については、リンク先の記事が分かりやすい(本稿では説明を割愛する)。
- サーバーレスアーキテクチャとは? Azure Functionsで初めての開発(以下、「前回」と呼ぶ)
Visual Studio Tools for Azure Functionsのインストール
本稿では最新(※執筆時点)のVisual Studio 2015環境を使用する。Visual Studio 2015 Update 3以降の最新アップデートと最新の.NET向けAzure SDKも事前にインストールしておく必要がある。これらの準備が済んだら、下記のリンク先からインストーラーをダウンロードして、Visual Studio Tools for Azure Functions(※執筆時点でプレビュー版)のセットアップを行う。
- Azure Function Tools for Visual Studio 2017の公式ページ(※2017/06/25追記: 追記時点でプレビュー版)
- Visual Studio Tools for Azure Functionsの直接ダウンロード
セットアップが完了すると、Visual StudioでAzure Functionsのプロジェクトテンプレートが使えるようになる。
Azure Functionsテンプレートによるプロジェクト作成(Visual Studio)
Visual Studioで[新しいプロジェクト]ダイアログを開くと、「Azure Functions (Preview)」テンプレートがあるので(図2)、これを使ってFunction App(関数アプリ)の新規プロジェクトを作成する。
※「Azure Functions (Preview)」テンプレートが表示されない場合はターゲットフレームワークが「.NET Framework 4.5」以降になっているかを確認してほしい。
Function AppへのFunctionの追加
プロジェクトの作成が完了したら、まずはFunction(関数)を1つ追加してみよう。これには、[ソリューション エクスプローラー]でプロジェクト項目を右クリックして、表示されるコンテキストメニューから[追加]-[New Azure Function]を選択する(図3の上)。すると、[New Azure Function]ダイアログが表示される(図3の下)。そこで、さまざまなタイプのテンプレートから選択して任意のFunctionのひな型ファイル群を追加できるようになっている。
本稿の目的は、Azure Functionsの機能解説ではなく、あくまでVisual Studioでの開発方法紹介なので、ここでは前回、Azure管理ポータル上で選択したものと同じ、「QueueTrigger - C#」(キューをトリガーにするC# Function)テンプレートを選択しよう(※ちなみにC#以外にも、Bash、Batch、F#、JavaScript、PHP、PowerShell、Pythonが選択可能だ)。入力項目も以下のように前回とほとんど同じにした。
- [Name]欄: 任意のFunction名を指定(本稿の例では「QueueTriggerCSharp1」)
- [Bindings](構成)-[Azure Storage Queue trigger (myQueueItem)]の、
- [Queue name]欄: 任意のQueue名を指定(本稿の例では「myqueue-items」)
- [Storage account connection]欄: 「AzureWebJobsStorage」という接続名を指定(Function Appが自動的にデフォルトで作成する接続文字列なので、これを指定しておくと便利なため)
これにより、QueueTriggerCSharp1
フォルダーが作成され(図4)、その中に以下のような必要最小限のファイルが生成される。
- function.json: Functionのトリガーや入力/出力のバインディングを定義。管理ポータルの[統合]タブに相当(前回の図4に相当)
- project.json: インポートするNuGetパッケージ(依存関係ライブラリ)のリスト
- readme.md:テンプレートにより生成されたサンプルFunctionの説明が記載されているMarkdownファイル
- run.csx: 実行するC# Functionのコード。管理ポータルの[開発]タブに相当(前回のリスト1に相当)
- sample.dat: サンプルのQueueデータ。本稿の例では未使用
ついでにプロジェクト項目直下のファイル群も簡単に紹介しておくと、以下のようになっている。今回はこれらのファイルは何も編集しない。
- appsettings.json: アプリ設定情報。接続文字列などといった秘密の構成情報を保存する場所なので、このファイルはソース管理の対象から外しておいた方がよい
- host.json: Function Appのホストの挙動を構成するためのファイル。こちらのページ(英語)を参考にされたい
- Project_Readme.html: サンプルプロジェクトを活用するためのReadMe(説明)ファイル
今回はいったんここでリリースビルドして、それを実際にAzure上にデプロイしてみよう。
Azure管理ポータルでFunction Appの新規作成
Visual Studio側からAzureのFunction Appを自動作成することも不可能ではないが、細かな機能は先に管理ポータル側に実装されることが多く、Azure管理ポータル上で手動作成した方がよりよい(と筆者は試行錯誤した結果で感じている)。実際に手動作成するには、以下の図5の手順を実施すればよい。
図5の[Function App]ブレードには以下のように入力する。
- [アプリ名]: 本稿の例では「FunctionApp1Hosting」を入力しているが、Azure全体で一意のため、これとは違う名前を指定する必要がある
- [サブスクリプション]: 各自で契約しているサブスクリプションに合わせて選択
- [リソース グループ]: [既存のものを使用]を選択するか、[新規作成]を選択する場合はグループ名を入力する。本稿の例では「FunctionApp1ResourceGroup」という名前を指定している
- [ホスティング プラン]: 費用を必要最小限とするために「従量課金プラン」を選択する
- [場所]: 日本国内であれば「東日本」か「西日本」を選択する。本稿の例では「東日本」を選択して作成したが、この場合、App Serviceプラン*2の名前は自動的に「JapanEastPlan」となった(後述の表1を参照)
- [ストレージ アカウント]: 項目をクリックして[ストレージ アカウント]ブレードを表示し、既存のものを選択するか、[新規作成]ボタンをクリックする。新規作成の場合は、次に表示されるブレードの[ストレージ アカウント]欄で任意のストレージアカウント名(本稿の例では「functionapp1storage」)を指定して[OK]ボタンをクリックすればよい
最後に[作成]ボタンをクリックすると、デプロイ先となるFunction App(実体はApp Service)と、それに付随するストレージアカウントやApp Serviceプラン*2が作成される。
- *2 App Serviceプランとは、ホスティングプラン/場所(=価格レベル/リージョン)などの課金方法を管理するためのリソースである。
以上でAzure側の準備は完了だ。それでは実際にデプロイしてみよう。
AzureへのFunction Appのデプロイ
アプリをデプロイするには、[ソリューション エクスプローラー]でプロジェクト項目を右クリックして、表示されるコンテキストメニューから[公開]を選択すればよい。あとは以下の図6の手順に従って入力していく。これにより、正常にデプロイされるはずだ。
デプロイされたFunction Appの確認と、Functionの実行
Azure管理ポータルを開いてみよう。作成したリソースグループ(本稿の例では「FunctionApp1ResourceGroup」)のブレードを表示すると、図7と表1に示すように、先ほど設定した内容で3つのリソースが作成されていることが分かる。
名前 | 種類 | 場所 |
---|---|---|
FunctionApp1Hosting | App Service | 東日本 |
functionapp1storage | ストレージ アカウント | 東日本 |
JapanEastPlan | App Service プラン | 東日本 |
このうち、Function Appの「FunctionApp1Hosting」を開くと、図8のようにブレードが表示され、前回説明した内容と同じ方法で操作できる。[開発]タブを開いて[実行]ボタンをクリックすると、確かにデプロイしたFunction Appに含まれるFunction(関数)を実行できるはずだ。
あとは、前回説明した内容を基に開発していくだけだ(これに関しては説明を割愛する)。
Azure Functionsでのライブラリの利用(Visual Studio活用)
ここまでに説明した内容で開発&デプロイしていけるわけだが、せっかくVisual StudioとC#を使えるのであれば、既存のライブラリや自作ライブラリを含めたいというニーズが多くあるだろう。筆者自身も既存のC#コンソールアプリの1つをAzure Functionsに移行したわけだが、その際に学んだノウハウについて簡単にまとめておきたい。
run.csxファイルの中で外部ライブラリのクラスを利用する方法
前述の通り、run.csxファイルこそが、Function App内で実行されるC# Functionのコードである。この中で外部ライブラリのクラスなどを利用したい場合は、当然ながら、それをインポートする必要がある。これは、NuGetパッケージとして公開されているものであれば、容易に実施できる。その手順を、ここではJson.NETのNuGetパッケージを利用する例で示そう。
前述したように、インポートするNuGetパッケージ(依存関係ライブラリ)はproject.jsonファイルに記述する必要がある。このファイルへの書き込みをVisual Studioの[NuGet パッケージの管理]で手軽に実施したいところなのだが、残念ながら執筆時点では対応していない……。よって、必要なNuGetパッケージのバージョン(.NET Frameworkのバージョンにも注意)と依存関係ファイルを何とかして調べてから手動で記述する必要がある。
これは、もちろんNuGetのサイトを見て自力で調べていくことも不可能ではないが、それよりも一時的なコンソールアプリ(.NET)*3を作成して、そのアプリ内で[NuGet パッケージの管理]で目的のNuGetパッケージをインストールし(※当然ながら.NET FrameworkのバージョンがAzure Functionsプロジェクトと一致している必要があるので注意)、作成されたpackages.configファイルの中身からNuGetパッケージのリストを抜き出してFunction App用の内容を書き起こした方が(もしくは置換して作成した方が)楽だし間違えがないだろう。
- *3 ちなみに.NET Coreのコンソールアプリのプロジェクトであれば、XML形式のpackages.configファイルではなくJSON形式のproject.jsonファイルを使用しているので、これが活用できるかもしれない。だが筆者が試した限りでは、依存関係にあるライブラリが自動的に記載されないなど[NuGet パッケージの管理]の機能にまだ問題があったので、本稿では採用しなかった。Visual Studio 2017が登場した段階で、もろもろの機能が正常になることを期待したい。
次のリスト1は実際にJson.NETのNuGetパッケージをインストールした場合のpackages.configファイルの内容である。
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net46" />
</packages>
|
このpackages.configファイルの内容を、project.jsonファイルに書き直すと次のようになる。
{
"frameworks": {
"net46":{
"dependencies": {
"Newtonsoft.Json": "9.0.1"
}
}
}
}
|
Json.NETパッケージの場合は、他のライブラリに全く依存していないので1つだけだが、例えばWindowsAzure.Storageパッケージであれば多数のライブラリに依存している。リスト3とリスト4がその例だが、このように存関係数が多くなってくると、ここで紹介したコンソールアプリのpackages.configファイルから書き起こす方法でproject.jsonファイルを記述した方がよりよいと感じられるだろう。
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net46" />
<package id="Microsoft.Data.Edm" version="5.7.0" targetFramework="net46" />
<package id="Microsoft.Data.OData" version="5.7.0" targetFramework="net46" />
<package id="Microsoft.Data.Services.Client" version="5.7.0" targetFramework="net46" />
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net46" />
<package id="System.Spatial" version="5.7.0" targetFramework="net46" />
<package id="WindowsAzure.Storage" version="8.0.1" targetFramework="net46" />
</packages>
|
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.Azure.KeyVault.Core": "1.0.0",
"Microsoft.Data.Edm": "5.7.0",
"Microsoft.Data.OData": "5.7.0",
"Microsoft.Data.Services.Client": "5.7.0",
"Newtonsoft.Json": "6.0.8",
"System.Spatial": "5.7.0",
"WindowsAzure.Storage": "8.0.1"
}
}
}
}
|
ちなみに、Newtonsoft.Jsonライブラリをインポートしておけば、リスト5のようにしてライブラリのJsonConvert
クラスを使ったりできる。
using System;
using Newtonsoft.Json;
public static void Run(string myQueueItem, TraceWriter log)
{
var json = "{ 'Name': 'Bad Boys' }";
var m = JsonConvert.DeserializeObject<Movie>(json);
log.Info(m.Name); // Bad Boys
}
public class Movie
{
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
}
|
自作ライブラリのクラスを利用する方法
外部ライブラリが使えることは分かったが、自作のコードを使うにはどうすればよいだろうか? これを行うには、.NETのクラスライブラリ(.dllファイル)に自作コードをまとめて、そのクラスをrun.csxファイル内で利用すればよい。その手順を示すために、ここではリスト5にあるMovieクラスを自作ライブラリの中に移して、それをrun.csxファイル内で利用することにしよう。
まずソリューション内にクラスライブラリ(.NET)のプロジェクトを(本稿の例では「MyLibrary1」という名前で)追加し、自動生成されたClass1.csファイルの中にリスト6のコードを記述する。
using System;
namespace MyLibrary1
{
public class Movie
{
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
}
}
|
このライブラリをリリースビルドして、.dllファイルを生成する。これをFunction App(本稿の例では「FunctionApp1」)のプロジェクトのQueueTriggerCSharp1\bin
フォルダー内にコピーして配置する。※このbin
フォルダーは[ソリューション エクスプローラー]上で手動で作成する必要がある。
なお、ビルドするたびに常に最新の.dllファイルを配置したい場合には、コンソールアプリのプロジェクトプロパティの[ビルド イベント]タブで、[ビルド後イベントのコマンドライン]欄にxcopy /y "$(TargetPath)" "$(SolutionDir)FunctionApp1\QueueTriggerCSharp1\bin\"
と記載すればよい(この場合、ライブラリを先にビルドする必要があるので、[ソリューション エクスプローラー]のFunction Appプロジェクト項目を右クリックして、コンテキストメニューから[ビルド依存関係]-[プロジェクトの依存関係]を選択し、それにより表示されるダイアログで[依存先]欄にある自作ライブラリにチェックしておくことも忘れないように)。
追加した.dllファイルをrun.csxファイルで参照するには、リスト7に示すように#r "<アセンブリ名>"
ディレクトリを指定すればよい。このディレクティブを含めて、.csxファイルの書き方は「csi.exeコマンド登場! C#スクリプト(.csx)やREPLを動かそう」で紹介しているので参考にしてほしい。
#r "MyLibrary1.dll"
using MyLibrary1;
using System;
using Newtonsoft.Json;
public static void Run(string myQueueItem, TraceWriter log)
{
var json = "{ 'Name': 'Bad Boys' }";
var m = JsonConvert.DeserializeObject<Movie>(json);
log.Info(m.Name); // Bad Boys
}
|
今回の例では自作ライブラリ側で何もNuGetパッケージを使っていないが、自作ライブラリでNuGetパッケージを参照した場合には、Function App側のproject.jsonファイルにも同じNuGetパッケージのリストを記載することを忘れないように注意してほしい(Azure上で実行する際に、自作ライブラリから参照する必要があるため)。
■
以上、ここまでに説明した機能を活用すれば、ほとんどの開発が思い通りにできるのではないだろうか。ぜひ本稿をきっかけに、まずは手軽な、既存のコンソールアプリ/バッチ処理などのAzure Functionsへの移行を試してみてほしい。ただし、まだプレビュー段階であり実際に開発するうえでは面倒な部分も残っている。これについては今後、Visual Studio 2017の登場やアップデートで改善されていくことに期待したい。
※以下では、本稿の前後を合わせて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サービスの対応一覧表をまとめる。