2016年12月5日更新
ちゃんと書いてなかった気がするのと、某所で喋ったのでスライドの中身を適当にコピペします。そのうち動画・スライドが公開される気もしますが。→ されました
※2016年12月5日現在の情報です。
※だらだら長くなってしまった…
Azure Functionsって?
イベント駆動の”機能”実行プラットフォームです。だいたいは何かしらのデータを処理したいというのと、何かしらアクションがあって処理を実行したいという2点が実現したい何かだと思いますが、アクションを受ける部分とかわざわざ作りたくないですよね。もっと処理そのものをサクッと構築して実行したいと思います。
Azure Functionsではそのための機構が提供されてて、スクリプトベースで処理に関する記述だけに注力できます。またアクションを受ける部分、アクションしたい先についてはトリガーとバインディングという機構が提供されててその部分の開発をかなり省くことができるようになっています。
- トリガー:スケジュール、HTTP (Webhook)、キュー、ファイル作成時などを受けて処理を開始できる
- バインディング:ファイル作成やPush通知など連携先を簡単に設定できる
バインディングはかなり強力で、例えばBlobファイルへの読み書きやPush通知の細かい処理などわざわざ書く必要はありません。データの読み書きだけ行えば済むようになっています。
またトリガーとバインディングをうまく設定することでFunctionを(イベントを)連鎖させたり、他のシステムと受け渡ししたりすることができます。(あまりやりすぎるとLogic Appsなどのほうが良いケースになったりしますが)
あとオープンソースです。(後述)
よく言われるのはServerlessという言葉ですが、「OSレイヤー以下を抽象化しサーバーを意識させない」という点でAzure FunctionsはServerless Compute Platformとも言えます。
PaaSとして提供されている他のサービスや概念を拡張して、OSレイヤー以下のスケールとかパッチ、メンテナスなどインフラストラクチャ部分を抽象化して意識する必要がありません。
実はAzure Functionsに似たような機能はWebJobsとしてApp Service Web Apps上で実行できていました。これはこれでバインディングだったりトリガー機構は持っててAzure Functionsの原型ともいえるサービスでしたが、扱うためにはWeb Appsなりをある程度知ってないと構成したり管理するのが難しいところでした。
Azure Functionsでは基本的にAzure Functionsの画面(実際にはAzure Portalの一部ですけど)だけでだいたい完結するので他の余計な部分に煩わせられることなく処理に注力できるようになります。
はじめるには
https://functions.azure.com/signin にアクセスします!
Azure サブスクリプションが複数ある場合は選択して、あとはCreateするだけ!1つ1つのスクリプトはFunction Appという呼び方でまとめたものをFuncions Containerと呼ぶようです。で、既にFunctions Containerがある場合はOpenで開くこともできます。※Azure Portal上からでも作成はできます。
作成後は以下のような画面になります。(実際はAzure Portal内です)
Function Appの作成や設定など基本的にここから行います。Web AppsとかAzureだとかあまり意識せずに触れそうですね(まだまだな点はもちろん多いですけど)
あとはトリガーと言語を選んで作成すればテンプレートに従って作成することができます。もしGitHubなどのリポジトリから取得する場合は右下の「Start from source control」リンクからWeb Appsと同じように連携設定を行うことができます。(後からでも可)
また、他のテンプレートや言語を選択したい場合は左上の「New Function」か「Create your own custom function」リンクを選択します。もう少し詳しいテンプレート一覧が表示されるのでこちらから選びましょう。
現状、選べる言語としては以下の通りとなります。
- メインサポート
- node.js / JavaScript
- C# (.NET Compiler Platform Scripting API) * .cs / .csx
- 実験的なサポート
- F# / Python / PHP / Batch (.bat) / Bash (.sh) / PowerShell (.ps1)
作成すればメインの画面(ブレード)でコードを編集したり、バインディングの設定をしたりすることができるようになります。
左側の一覧に作成されたFunction Appの一覧が表示されます。選択することでそれぞれのコードやバインディングの情報を編集することができます。
- Develop メニュー
- コードの編集、出力確認、テスト実行が行えます。
- Integrate メニュー
- トリガーやバインディングの設定が行えます。
- Monitor メニュー
- 実行状況や呼び出しログなどを参照できます。(後述のモニタリング/ログあたりを参照)
- Manage メニュー
- 現在の状態(有効/無効)確認とAPIキーの確認などが行えます。
- 現在の状態(有効/無効)確認とAPIキーの確認などが行えます。
Function App全体(Functions Container)の設定等については一覧下部のリンクから行えます。
- Function app settings
- Function App全体の設定が行えます。(後述)
- Quickstart
- functions.azure.com から遷移したときに表示されるQuickstart画面を表示します。
開発
実際に処理されるスクリプトを編集する画面です。Developタブで行います。
Codeのテキストエリアで直接コードを編集します。編集が終わったらSaveしましょう。(C#の場合、Saveした後コンパイルが行われます)
コンパイル結果や実行結果はLogsの領域に出力されます。ログの実体は別途保存されているのでこの領域はClearしたりPauseしたりしても問題ありません。
Runのところではトリガーに渡す情報を入力して「Run」ボタンで実際に実行することができます。(入力する内容はトリガーなどによってプレーンテキストだったりJSON形式だったりといろいろです)
また一部トリガーではここからRunしてもエラーになったりうまく実行できないので注意しましょう。(Blobトリガーとか)
HTTPのレスポンスが返ってくる場合など、FunctionによってはOutputテキストエリアに実行後の応答が表示されます。
また一部トリガー(HTTPトリガーなど)を選択している場合は上部にAPI Keyが付いた状態の呼び出し用URLが表示されます。(後述)
基本的にこの画面と次のバインディングなどがメインで操作する箇所になるかと思います。ゴリゴリ書いていきましょう。
バインディングとトリガー
いつ/何によって実行するか(トリガー)と、入出力する他のサービス群をどう紐づけるかはIntegrateタブで行います。
内部的にはトリガーもInputなバインディングの一種です。(タイプがトリガーという感じ)
トリガーは1つ、InputおよびOutputのバインディングは複数指定可能です。またこれらの設定の実体はfunction.jsonファイルとして保存されているので直接編集することも可能です。(右下にあるAdvanced Editorのリンクから編集することもできます)
現時点でサポートしているバインディング・トリガーの種類は以下のようになります。
* HTTPのアウトプットはHTTPトリガー使用時のみ利用可能です。
* 上記以外にもTwillio(SMS送信、Output用)やSendGrid(Eメール送信、Output用)、Bot Framework(Input/Output用)など増えてきています。
テンプレートから作成したときはスクリプトに予め記述されていますが、後からバインディングを編集した場合、スクリプト(コード)にバインディングした値を受け取るようなコードを追記する必要があるので注意してください。
C#だと特に型が間違ってたりするとコンパイルエラーになったり、実行時エラーになります。(このあたり細かいドキュメントは後述。まだまだ足らない)
料金
料金プランは2種類あります。基本的に他のAzureのサービスと似てますがプランによって実行される環境のスペックだったりも決まる感じです。
- App Service Plan
- 通常のApp ServiceのPlanを使用する方法です。他のユーザー(テナント)と実行環境を共有しないという点である意味(Functionsにとって)占有プランとも言えます。
- 最大インスタンス数などスペック、機能はApp Serviceと同等になります。
- Azure Portal上で作成するときはClassic といった表記になります。
- Consumption Plan
- 詳細はこちら
- functions.azure.com から作成すると自動的にこのプランになります。
- App Service Planと異なり、こちらはAzure Functions専用のプランですね。また課金の対象は次の2種類あります。
- Consumption: 実行された時間と使用されたリソース使用量(メモリ領域サイズ)に応じて課金
- リソース使用量(GB-秒単位)* 実行時間(100ミリ秒単位)を基に計算
- 実行時間は100ms単位で丸められるようです
- 月間40万 GB-Secまで無料(128 MB 設定で約37日間フルで実行可能) ※超えたときの価格は価格表通り
- リソース使用量(メモリ領域サイズ)が想定以上にならないようにリミットを設定できます。
- Executions: 実行された回数に応じて課金
- 月間100万回まで無料 ※超えた時の価格は価格表通り
- Consumption プランはper アカウント per month なので同じアカウント(サブスクリプションかな?)で複数のAzure Functions コンテナーを作ったとしても共通になります。(アカウント単位で40万GB-Sec / 月、100万実行まで無料ということかと)※たぶん。
価格についてはGA価格は2017年1月1日より反映です。また無料枠は有償サブスクリプション(Pay-as-you-goなど)のみあるようです。
ここまでがざっくりな概要です。後は(誰得な)詳細とか細かなTipsを羅列していきます。
設定
基本的な設定は「Function app settings」から行います。
- 日ごとの使用量クォータ(GB-秒)(Daily Usage Quota) (Consumption Plan指定時のみ設定可)
- Function App全体で使用するGB-秒を指定します。料金に関わるので指定には注意しましょう。
- スクリプトの挙動が不安定だったりする場合、メモリ不足が原因の場合もあるので大き目に設定するとよかったりするかもしれません。
- 継続的インテグレーションの構成 (Configure Continuous Integration)
- CIに関する設定です。GitHubなどのSCMと連携して自動的にFunction Appが展開されるようにすることができます。Web Appsとかと同じですね。
- 認証の構成 (Configure authentication)
- HTTPトリガーを使ったFunction AppにWeb Appsで用意されている認証・認可の機能を設定することができます。
- HTTPトリガーで用意されているAPI Keyを使った認証とはまた別で前段で処理されます。
- CORSの構成 (Configure CORS)
- ブラウザからHTTPトリガーなFunction Appを呼び出したりする場合、CORSの設定が必要になります。
既定値の3つはAzure Functions UXのブランチ等と対応してますので参考までに。- functions.azure.com … 本番環境
- functions-staging.azure.com … master
- functions-next.azure.com … dev
- ブラウザからHTTPトリガーなFunction Appを呼び出したりする場合、CORSの設定が必要になります。
- APIメタデータの構成 (Configure API metadata)
- HTTPトリガーなどWeb APIとして公開されるようなFunction Appについてより利用されやすいようにSwaggerの定義ファイル(JSONなど)を指定します。
- Kuduに移動 (Go to Kudu)
- Kuduに移動してKuduのデバッグコンソールを表示できます。
- 開発者コンソールを開く (Open dev console)
- KuduのデバッグコンソールをAuzreポータル内でブレードとして表示します。
- App Service エディターに移動 (Go to App Service Editor)
- App Service Editor(旧称Visual Studio monaco)に移動してコードの編集などを行うことができます。
- App Serviceの設定に移動 (Go to App Service Settings)
- Function AppをホストしてるApp Serviceの情報をブレードで表示します。
- アプリケーション設定の構成 (Configure app settings)
内部的な話
Azure Functions Runtime (Webjobs.Script.Host)がスクリプトであるFunction Appを動かす実体となります。
通常、Azure Functionsを作ると1つのリソースグループ配下にApp Service PlanとWeb Apps、あとAzure Storageアカウントが作成されます。(※ポータル上から作成した場合はApplication Insightsも作成されます)
また実際にはWeb Apps上でいろいろ動作しています。もうちょっとそのあたりを詳しく書くと
こんな感じの構造になってます。※SiteExtensionsにFunctionsが入ってるのと、Azure Filesの共有フォルダをマウントしてるのがWeb Appsとちょっと違うところかもです。
ランタイムのバージョンは一応細かく指定できます。普通に作ると最新版の~1になります。もし今後新しいバージョンが出てきた場合はFunction AppのSettingsから簡単にUpdateできます。
実際は FUNCTIONS_EXTENSION_VERSION 設定で~1 などを指定してるだけですが。細かい話をするとこんな感じです。
* D:\Program Files (x86)\SiteExtensions\Functions\
** 2016年5月25日現在の推測値 https://github.com/Azure/azure-webjobs-sdk-script/releases
修正内容などはGitHubのページ見ればいいですね。(Kuduとかでも同様です)
- data\secrets フォルダー
- HTTPトリガー等で使用するAPIキーを格納
- site\wwwroot フォルダー
- 各 Function App のスクリプト等を格納
- フォルダー名 = Function App 名
- Function App 名フォルダー
- Function App に関する定義と実行スクリプト(コードファイル)を格納
- function.json = バインディングなどの定義情報
- * function.json が存在しないフォルダーは Function Appとして認識されない
各Function App内に含まれるファイル等は言語によっても少し異なります。
- C#
- NuGet パッケージの参照設定などは project.json に記述
- カスタムアセンブリは bin フォルダーへ
- node.js
- npm パッケージは node_modulesフォルダーへ
- D:\local\Temp\Functions\Binding
- バインディングされたオブジェクトは Temp フォルダに
- 外から参照できません
各Function Appフォルダには複数のスクリプトや関連するバイナリを置くことができますが、実行時にそれらを参照したりできないようです。(C#のアセンブリロードなどはちょっと特殊)
また複数言語の混在はエラーになるので注意しましょう。(run.csxとrun.ps1を一緒に置いとくなど)
実行するスクリプトの決定ルールなどは基本的にWebJobsと同様です。同一言語のスクリプトが複数存在する場合 run.{拡張子} が起動されます。
開発Tips
C#
- .NET Compiler Platform Scripting APIでファイルに変更があった場合コンパイルされます。(.csと.csxが対象)
- public static な Run メソッドが必須(エントリポイント)
- project.json ファイルを使用して NuGet パッケージの指定など可(細かい話は.NET Core CLIなどのドキュメントを参照してください)
- Run メソッドの引数はバインディングで指定した名前で実装します。
- 一部outputのバインディングには out パラメーター修飾子を利用します(BlobのOutput時はout string outputBlobなどにする)
- CancellationToken token を使用してグレースフル シャットダウンに応答できます。
- 外部アセンブリの読み込みは #r ディレクティブを使用します。もしproject.json で指定した場合は不要( using ステートメントで読み込み)
- カスタムアセンブリは Function App フォルダ直下の bin フォルダに保存(パス変えられません)
- 外部スクリプト(.csx)の読み込みは #load ディレクティブを使用(こちらは相対パス)
- 詳細はこちら https://azure.microsoft.com/ja-jp/documentation/articles/functions-reference-csharp/
JavaScript/node.js
- module.exports で function(context){} を1つエクスポート(必須)
- inputなバインディングは引数指定可(context でアクセスは可能)
- 現状、node.js のバージョンは 5.9.1 固定
- パッケージは Function App フォルダ内に npm install 等を使用してnode_modules フォルダーに保存、利用時は通常通り require(‘パッケージ’)
- TypeScript/CoffeeScriptのランタイム側での自動コンパイルなどは未サポートです。
- 詳細はこちら https://azure.microsoft.com/ja-jp/documentation/articles/functions-reference-node/
その他
- バインディングされたオブジェクトはテンポラリのフォルダ上で保存
D:\local\Temp\Functions\Binding\<ジョブID>\<バインディング名> - C# や node.js 以外の言語では上記パスが環境変数で提供されるので適宜読み出し・書き込みを行います
バインディングされたオブジェクトの取得例
C#
#r "Microsoft.WindowsAzure.Storage" using System; using Microsoft.WindowsAzure.Storage.Blob; public static void Run(CloudBlockBlob inputBlob, CloudBlockBlob outputBlob, TraceWriter log) { log.Info(inputBlob.StorageUri.PrimaryUri.ToString()); outputBlob.StartCopyFromBlob(inputBlob); }
PowerShell
$requestBody = Get-Content $Env:req -Raw | ConvertFrom-Json $name = $requestBody.name Out-File -Encoding Ascii $Env:res -inputObject "Hello $name"
PowerShellの上記例の場合、実行時に以下のようにファイルが生成されます。
D:\local\Temp\Functions\Binding\<ジョブID>\req D:\local\Temp\Functions\Binding\<ジョブID>\res
アプリケーション設定の取得
アプリケーション設定は環境変数に入っているので以下のように取得できます。(decodeという設定を取得する場合)
C#
System.Environment.GetEnvironmentVariable("decode")
※ConfigurationManager経由でも取れます。
node.js
process.env.decode
PowerShell
$Env:decode
バインディングTips
細かいのはドキュメントが揃いだしてきたのでこちらを参照。
ドキュメントにもありますが、バインディング時にBlobなどパス指定する場合にパラメーターを使用することができます。
Blobの場合は {name} や {blobname}.{blobextension} といった感じ。またトリガーで {name}.txt のように指定することでパターンマッチングのようにフィルタすることもできます。この場合、 Blob名の最後が .txt のBlob時のみ発火します。
Queueの場合は
- expirationTime
- insertionTime
- nextVisibleTime
- queueTrigger
- id
- popReceipt
- dequeueCount
などが利用できます。queueTriggerにはメッセージ本文が入ってるので例えばQueueトリガーで発火した後、OutputでBlobのパスに {queueTrigger}.txt のように指定すればメッセージ本文に含まれてる文字列.txt といったファイルが作成されます。
※パラメーターはトリガーやInputのバインディングで取得したものをOutputで使うこともできます。
また特殊なパラメーターとしてGUIDを生成する %rand-guid% とランダムな数値を生成する %rand-int% も利用できます。
※それぞれC#でいうところの Guid.NewGuid().ToString() と (new Random()).Next(10000, int.MaxValue).ToString(CultureInfo.InvariantCulture) になります。
指定例:
{ "type": "blob", "name": "outputBlob1", "path": "outcontainer/{name}.txt", "direction": "out“ }, { "type": "blob", "name": "outputBlob1", “path": "outcontainer/{blobname}.{blobextension}", "direction": "out“ }, { "type": "blob", "name": "outputBlob2", "path": "outcontainer/%rand-guid%", "direction": "out“ }
そのほか注意点はいくつかありますが、Blobトリガーは現状ポーリングして発火しているので1万以上のファイル(Blob)がある場合、パフォーマンス低下や発火漏れが懸念されます(公式より)
HTTPトリガー時の認可について
Web AppsのAuthN/AuthZ機能も使えますが通常API Keyを使った認可機能を使用すればよいかと思います。
また指定方法や範囲などはモードと認可レベル・Webhookタイプで変わりますので注意が必要です。
- モード: Standard
- 認可レベル: Function 、 Anonymous、 Admin
- Anonymousはキーなしでアクセスできます。
- Functionの場合は各Function App専用のキーもしくはホストのfunctionKeyが必要
- Adminの場合はホストのmasterKeyが必要
- URLクエリストリングにcode=を付ける、もしくはHTTPリクエストヘッダにx-functions-keyを追加してキーを送信する必要があります。
- モード: Webhook
- Webhookタイプ:
- Generic JSON
- URLクエリストリングにcode=を付ける
- Github
- HTTPリクエストヘッダに X-Hub-Signature という名前でキーを使って生成された署名を付ける必要がある
- Generic JSON
- Webhookタイプ:
適切な方法で適切なレベルのキーが提供されない場合、認可エラーになり失敗します。
どの場合もキー(WebhookのGithubを選択した場合だけ名称がGithub Secretになりますが)は画面上に表示されているものを使用します。またキーの実体はdata\secrets フォルダにあります。
<Function App名>.json … 各Function App用の専用キーです。認可レベルをFunctionに指定した場合に使用できます。
{"key":"<Function App専用のキー>"}
host.json … Functionsコンテナー全体のキーを管理します。
{ "masterKey": "<Adminレベル用のキー>", "functionKey": "<全Function App共通キー>" }
もしキーを変更したい場合はKuduなどを使用して直接これらのファイル内のキーを編集することで変更できます。
デバッグについて
C#などの場合、Visual Studioを使用して直接Functions上の.csxファイルを開いてデバッグすることもできます。※デモしたけど、シンボルが読み込まれないとかちょっと不安定だったけど…
※Cloud Explorerからファイル開いてアタッチするだけ
※うまくシンボルが読み込まれない場合はVisual Studioのオプションで以下のチェックをオフにしてみてください。
あるいはローカルにWebJobs.Script.Hostを動作させてローカル上でスクリプトをデバッグすることもできます。WebJobs.ScriptをCloneなりして実行することでローカル上で開発が可能です。(ちょっとコツがいる)
※最低限ローカル上でAzureWebJobsEnv 環境変数に Development と設定、AzureWebJobsStorage 、 AzureWebJobsDashboard環境変数をポータル上からコピペして設定、あとはFunctions上のsite\wwwrootフォルダ以下と同じ構成にしたフォルダのパスをAzureWebJobsScriptRoot 環境変数に設定すれば大丈夫と思います。
※function.json(バインディング)でBlobなどを使用する場合、接続文字列等をfunction.jsonで定義している名前と同じ環境変数に設定しておきます。(ないとHost起動時に読み込まれない)
※HTTPトリガーの場合はWebJobs.Script.WebHostを起動しましょう
→ もっと簡単にローカル開発できるようになりました。こちらの記事を参照ください。
スケールについて
Consumption Planの場合、インスタンスが自動的に増減します。構成されているトリガーに基づいてトラフィックや実行状況から判断されるようです。1つのインスタンス内の同時実行可能数はメモリ領域の設定などによって異なるようです。
※どのように稼働してるか確認する手段はなくなりました。
App Service Planの場合は基本的にApp Serviceの構成に依存します。オートスケールや稼働するインスタンス数などはApp Serviceでユーザーが構成します。
デプロイについて
FunctionsコンテナーそのもののデプロイはARM Templateを使って展開することもできます。既にQuickstart templateに公開されているのでそちらを参考に。
Function AppについてはCIの設定からSCMと連携して行うことも可能です。
またSite\wwwrootフォルダ以下にFunction App名なフォルダと必要なファイル(function.jsonとrun.csxなど)があればよいのでFTPやWeb Deployなどを使用してデプロイすることも可能です。あるいは環境によりますが、Azure File Storage上の共有フォルダを直接マウントして編集(あるいはフォルダごとコピーなど)することで展開することもできます。
モニタリング/ログ
消費ユニット/インスタンス数はMonitoringタブから参照できます。(この機能はなくなりました)
お金関連(請求関連)はhttps://account.windowsazure.comやBilling API(REST API)経由で取得できます。以下の2つのメーターを参照しましょう(日本語の場合)
- コンピューティング期間 (GB秒) – Functions
- コンピューティング要求 – Functions
Function App単位のログやライブな実行状況などは各Function AppのMonitorから行えます。
Live event stream
数秒ラグありますが、ライブで要求数や実行時間、失敗数などを見ることができます。
URLを見ればわかりますが、Web Appsのサポート用ツールだったりします。
https://support-bay.scm.azurewebsites.net/Support.functionsmetrics/#/<Functions名>/<Function App名>
以下のInvocation logは直接参照したりする場合です。纏めたものがMonitorで見れるようになったので触ることはないかと思います。
Invocation log(呼び出しログ)
https://<Functions名>.scm.azurewebsites.net/azurejobs/#/functions というURLになります。Azure WebJobsのログを見る時と同じアプリ(SiteExtension)ですね。
ちなみにログはAzure Table Storage上のAzureFunctionsLogTableコンテナーに保存されてます。(ちなみにホストに関するログ等は同じくAzure Blob Storage上のazure-webjobs-hosts コンテナーに保存される様子)※Dynamicプラン時のみかも
詳細を見ることでFunction Appのログで見た内容(Outputの内容)やバインドされた各値の内容など参照できます。
Openness
Azure Functionsに関するコード等はすべてGitHub上で公開されています。もしフィードバックなどあればGitHubのIssueに登録するとよいかもです。またライセンスはMITライセンスとなっているようです。
- WebJobs.Script
- ランタイムなど含みます。Azure Functionsの本体です。
- Azure Functions UX
- functions.azure.com/signin などの画面関連です。
- Azure Functions Templates
- Function App作成時に選択できるテンプレートです。
そのほかWebJobs SDKやWeb Jobs SDK Extensionも参考に。
また複数言語対応という点もありますが、基本的にランタイムが公開されているのでオンプレだろうがAzureじゃないクラウドだろうが動かすことはできます。ただ現状手厚いサポートはありませんが。(ポータル部分とか展開方法とかいろいろ)
すぐに試してみたい!
Azureの契約(サブスクリプション)が無くても1時間だけ作って試せるTry Functionsというサイトがあります。
こちらのサイトからMSアカウントやGoogle、Facebookアカウントでサインインしてお試しください。
注意事項や制限事項
- 2016年11月15日にGAしました
- GA価格は2017年1月1日から
- 利用可能なリージョン
- ドイツやインド、英国など一部を除き利用可能(日本は東西とも利用可能)
- カスタムドメイン名は非対応
- 内部のWeb Apps側で設定しても404になります。(要望は上がってるのと、上位にTraffic ManagerやAPI Managementを乗せるという手はある)
- スロット
- こちらも現状利用不可(要望は上がってた気がする)
質問やフィードバック
今のところPreviewということで、有償のテクニカルサポートはありません。ベストエフォート的な対応になりますが、基本的にはStack OverflowやMSDN Forum、あとTwitterなどでやり取りする感じです。
- Stack Overflow (英語)
- https://social.msdn.microsoft.com/Forums/azure/en-US/home?forum=azurefunctions (英語)
- @AzureFunctions (Twitter)
バグ報告とかはGitHubへ。
ドキュメント
- 公式
- Azure Functions (リンク集的な)
その他
気が向いたら更新します。サンプルも気が向いたら。