御成門プログラマーの技術日記

Microsoft AzureやAngularなどの技術情報を発信します。

Azure Functionsの拡張機能「Durable Functions」の基礎を知るためにとりあえずデプロイしてみた

最近「Azure Functions」がらみでよく話に出る「Durable Function」のクイックスタートをやってみました。
備忘録的に作った際のメモを残そうと思います。

Durable Functions の概要

概要については公式ページ参照 docs.microsoft.com

Durable Functions の主な用途は、サーバーレス アプリケーションにおける複雑でステートフルな調整の問題をシンプルにすることです。 次のセクションでは、Durable Functions を使用することでメリットがある、いくつかの典型的なアプリケーションのパターンを示します。
パターン #1: 関数チェーン
パターン #2: ファンアウト/ファンイン
パターン #3: 非同期 HTTP API
パターン #4: 監視
パターン #5: 人による操作

Azure Functionsを連続、並列で実行したりする機能なのかなぁってイメージです。
機能、事例とかを知るためにTechSummit2018でMicrosoftの牛尾さんがDurable Functionsのセッションやってたから見てみようかなと思っています。

さらっと作ってみた

Azure Functionsのプロジェクトを作る

Visual Studioから作ります。
新しいプロジェクトで「Visual C#」→「Cloud」→「Azure Functions」 f:id:tt-suzukiit:20181210184506p:plain

バージョンを「Azure Functions v2(.NET Core)」
テンプレートは「なし」
ストレージアカウントは「ストレージエミュレーターf:id:tt-suzukiit:20181210184522p:plain

プロジェクトに新しい関数を追加する

「プロジェクトを右クリック」→「追加」→「新しいAzure関数...」
f:id:tt-suzukiit:20181210184906p:plain

「Azure関数」を選択し、名前を付けて追加をクリック
f:id:tt-suzukiit:20181210184959p:plain

「Durable Functions Orchestration」を選択してOKを選択する f:id:tt-suzukiit:20181210185056p:plain

下記のようなDurable Functionsのコードが自動生成される。

using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;

namespace DurableFuncApp
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<List<string>> RunOrchestrator(
            [OrchestrationTrigger] DurableOrchestrationContext context)
        {
            var outputs = new List<string>();

            // Replace "hello" with the name of your Durable Activity Function.
            outputs.Add(await context.CallActivityAsync<string>("Function1_Hello", "Tokyo"));
            outputs.Add(await context.CallActivityAsync<string>("Function1_Hello", "Seattle"));
            outputs.Add(await context.CallActivityAsync<string>("Function1_Hello", "London"));

            // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
            return outputs;
        }

        [FunctionName("Function1_Hello")]
        public static string SayHello([ActivityTrigger] string name, ILogger log)
        {
            log.LogInformation($"Saying hello to {name}.");
            return $"Hello {name}!";
        }

        [FunctionName("Function1_HttpStart")]
        public static async Task<HttpResponseMessage> HttpStart(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")]HttpRequestMessage req,
            [OrchestrationClient]DurableOrchestrationClient starter,
            ILogger log)
        {
            // Function input comes from the request content.
            string instanceId = await starter.StartNewAsync("Function1", null);

            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

            return starter.CreateCheckStatusResponse(req, instanceId);
        }
    }
}

HttpStartで関数を起動し、RunOrchestrator(名前はFunction1)で
「Function1_Hello」関数を3回連続で実行するコードみたいですね。

デバッグ実行で試す

デバッグ実行に成功すると、ローカルホストのURLが出力されるので、
このURLをブラウザ上で実行する。 f:id:tt-suzukiit:20181210190509p:plain

ブラウザ上でURLをたたくと下記のような文字列が出力される。 f:id:tt-suzukiit:20181210190647p:plain

{"id":"4fbb74e39ae04151a6fce230198617f4","statusQueryGetUri":"http://localhost:7071/runtime/webhooks/durabletask/instances/4fbb74e39ae04151a6fce230198617f4?taskHub=DurableFunctionsHub&connection=Storage&code=JJ8MNcYXpnllJD4LkpJdXQ3/jSbW0R0qad/Hs3W/PayFCSlrf5V/2w==","sendEventPostUri":"http://localhost:7071/runtime/webhooks/durabletask/instances/4fbb74e39ae04151a6fce230198617f4/raiseEvent/{eventName}?taskHub=DurableFunctionsHub&connection=Storage&code=JJ8MNcYXpnllJD4LkpJdXQ3/jSbW0R0qad/Hs3W/PayFCSlrf5V/2w==","terminatePostUri":"http://localhost:7071/runtime/webhooks/durabletask/instances/4fbb74e39ae04151a6fce230198617f4/terminate?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=JJ8MNcYXpnllJD4LkpJdXQ3/jSbW0R0qad/Hs3W/PayFCSlrf5V/2w==","rewindPostUri":"http://localhost:7071/runtime/webhooks/durabletask/instances/4fbb74e39ae04151a6fce230198617f4/rewind?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=JJ8MNcYXpnllJD4LkpJdXQ3/jSbW0R0qad/Hs3W/PayFCSlrf5V/2w=="}

上記文字列の中から「statusQueryGetUri」をコピーし、ブラウザ上で実行すると実行結果が表示されました。

出力結果

"Hello Tokyo!","Hello Seattle!","Hello London!"が出力されており、
「Function1_Hello」関数が3連続で呼ばれていることがわかりました。

{"instanceId":"4fbb74e39ae04151a6fce230198617f4","runtimeStatus":"Completed","input":null,"customStatus":null,"output":["Hello Tokyo!","Hello Seattle!","Hello London!"],"createdTime":"2018-12-10T08:58:29Z","lastUpdatedTime":"2018-12-10T08:58:37Z"}

Azureに発行する

発行する方法はいつもと変わらないので省略します。
動作は、デバッグ実行時と変わりません。

参考ページ

docs.microsoft.com