つばろぐ

福岡のエンジニアによる技術的な備忘録です。

Azure Functionsの出力バインドにCosmos DBを指定してローカル開発を行う

Azure Functionsには関数の呼出し(トリガー)と、関数で処理したデータの出力先を定義する必要があります。
それらの入出力にAzureのサービスなどを紐付けることを「バインド」と表します。

docs.microsoft.com

Azure FunctionsでタイマーやAzure Storageなどがトリガーとしてサポートされています。
またバインドできる出力先には、Azure StorageやSQL Database、Cosmos DBやプッシュ通知などがあります。

今回は出力バインドにCosmos DB(DocumentDB)を指定した構成でのローカル開発環境に必要な設定を紹介します。
なおVisual Studio 2015を使った開発環境を前提としてます。

サンプルも作ってありますので、良かったら参考にしてみてください。

github.com

Azure Functionsのローカル開発環境の整備

ブチザッキに従いましょう。

Azure Functions のローカル開発 | ブチザッキ

Cosmos DBのエミュレータのインストー

こちらの記事冒頭の「Binaries > Download MSI」のリンクをクリックして、インストーラを入手しましょう。
手っ取り早いのはインストール式のエミュレータですが、Dockerイメージとしても提供されているようです。 docs.microsoft.com

Cosmos DB(当時はDocumentDB)のエミュレータについては2016年末に軽くブログで紹介しています。

tsubalog.hatenablog.com

Azure Functionsの出力バインドの設定

Visual Studioで関数を作成すると function.jsonというファイルが生成されます。
例えば単純なHTTPを入出力バインドとした構成はこちら。

{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "res",
      "type": "http",
      "direction": "out"
    }
  ]
}

次に出力バインドをCosmos DB(DocumentDB)用に変更します。

{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "res",
      "type": "documentDB",
      "databaseName": "mlb",
      "collectionName": "players",
      "createIfNotExists": true,
      "connection": "documentDB",
      "direction": "out"
    }
  ]
}

注意点

connectionの値名称自体は任意に設定可能ですが、ここにDocumentDBの接続先情報がリンクされます。
では接続先情報をどこに定義するかというと、appsettings.jsonになります。
appsettings.jsonとはアプリケーション設定を定義するために使用されるファイルとなります。
Azure Functionsに限らず、Azure App Servicesのアプリケーションの開発でよく使用されるファイルですね。

このファイルに接続先情報を定義してもよいし、ローカル開発環境向けにappsettings.jsonを複製・リネームしたlocal.settings.jsonに定義しても良いです。
デバッグ実行時はlocal.setting.jsonが存在すれば、そのファイルを優先して参照してくれます。

appsettings.jsonもしくはlocal.settings.jsonに、DocumentDBの接続文字列を定義します。
Cosmos DBのエミュレータを接続先としたサンプルはこちらです。

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "AzureWebJobsDashboard": "",
    "documentDB": "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
  }
}

function.json > "connection"に定義した名称と、appsettings.jsonもしくはlocal.settings.json > "Values"に定義した名称がリンクされるという仕組みになっています。

データをCosmos DBに出力するコード

次に関数のコードの変更になります。エントリポイントのメソッドの第2引数にout修飾子つきの引数を定義することで、その引数にセットされたデータが出力バインドに流し込まれるという仕組みです。C#のサンプルはこちらをご覧ください。

docs.microsoft.com

Cosmos DBエミュレータにデータを出力してみる

ここまでの設定が済んだらCosmos DBエミュレータを起動したうえでデバッグ実行を開始して、関数のエンドポイントをコールしてみましょう。
タスクバーにCosmos DBエミュレータのアイコンを右クリックし、「Open Data Explorer」をクリックするとデータを確認することができるページが表示されます。

f:id:tech-tsubaki:20170702151528j:plain

まとめ

ここまでAzureのサービスを使用したアプリケーションを作ってきましたが、一切Azure上にリソースを作成していません。
開発がローカルで終始するなんて凄くいいですよね。
今回のサンプルはAzure FunctionsでWebページのスクレイピングを行っているのでインターネットに繋がっている必要がありますが、処理によってはオフラインでデータ出力までの開発を行うことができますね。

Visual Studio Tools for Azure Functionsでデバッグできない現象を解決する方法

仕事や趣味でAzure Functionsのアプリケーションを作ることがちょくちょくあります。
サーバを作るほどでも無いちょっとしたアプリケーションをホストするにはとても使い勝手がよいです。

Visual Studio 2015を使えば、Azure Functionsのローカル開発を行うことができます。詳しくはこちらをご覧ください。

Azure Functions のローカル開発 | ブチザッキ

通常、デバッグを実行するとlocalhostのWebサーバが起動し、Functionsの関数へのエンドポイントが実行されます。
しかし、いつからかデバッグできない状態に陥っていました。(Visual Studio 2017をインストールしてからかも?)

具体的にはlocalhostのWebサーバは起動するが、関数のエンドポイントが繋がらず 503 Service Unavailable となってしまいます。

f:id:tech-tsubaki:20170701205119j:plain

Warning: The filename 'appsettings.json' is deprecated. Rename it to local.settings.json

                  %%%%%%
                 %%%%%%
            @   %%%%%%    @
          @@   %%%%%%      @@
       @@@    %%%%%%%%%%%    @@@
     @@      %%%%%%%%%%        @@
       @@         %%%%       @@
         @@      %%%       @@
           @@    %%      @@
                %%
                %

Listening on http://localhost:7071/
Hit CTRL-C to exit...
[2017/07/01 11:30:42] Reading host configuration file 'D:\Functions\host.json'
[2017/07/01 11:30:42] Host configuration file read:
[2017/07/01 11:30:42] {
[2017/07/01 11:30:42]
[2017/07/01 11:30:42] }
[2017/07/01 11:30:42] Loaded custom extension: BotFrameworkConfiguration from ''
[2017/07/01 11:30:42] Loaded custom extension: SendGridConfiguration from ''
[2017/07/01 11:30:46] Generating 1 job function(s)
[2017/07/01 11:30:46] Starting Host (HostId=matvaio-1730734029, Version=1.0.11002.0, ProcessId=9884, Debug=False, Attempt=0)
[2017/07/01 11:30:46] Found the following functions:
[2017/07/01 11:30:46] Host.Functions.Hoge
[2017/07/01 11:30:46]
[2017/07/01 11:30:46] Job host started
The host is taking longer than expected to start.
The host is taking longer than expected to start.
The host is taking longer than expected to start.

The host is taking longer than expected to start.という出力が延々続いて、何もできない状態となります。
Visual Studio 2015の修復や、Visual Studio Tools for Azure Functionsの修復を何度か試しましたが、改善されず放置していました。
まぁVisual Studio 2017に開発ツールが出てくるのを待てばいいや、というスタンスでした。

しかしやはり不便だったので解決方法を調べてみると、Azure Functions CLIリポジトリにIssueがあがっていました。

github.com

このIssueで述べられていた内容としては、デバッグ時に使用するポート(既定では7071)が既にシステムに登録されているよ、という内容でした。
コマンドプロンプトを管理者権限で起動し、次のコマンドを入力しましょう。

netsh http delete urlacl url=http://+:7071/

私もこのコマンドを使用することでデバッグできない問題が解消されました。
これでエンドポイントにアクセスすることができ、デバッグ実行を行うことができるようになりました。

f:id:tech-tsubaki:20170701205401j:plain

Azureの開発ツールもGitHubで管理・公開されるようになり、不具合に関する情報が見えやすくなってきていますね。
もし同じ現象で困っている方の参考になればいいなーと思います。

de:code2017に参加してきました

今年もde:codeに参加してきました。

de:code (decode) 2017 | 日本マイクロソフトの開発者/アーキテクト/IT Pro 向けイベント - Microsoft Events & Seminars

今年のde:codeはCognitive Servicesのような「AI」、HoloLensのような「MR (Mixed Reality)」をテーマとしたセッションが多かった印象です。
逆に言語系のセッション数が減っていましたね。Xamarinのセッションは多かったけども。

ということで備忘録として私が聴講したセッションをメモしときます。

day 0 (5/22)

今年は前夜祭として、Developers Summitとコラボしたイベントが前日に開催されました。
de:codeの事前受付もできるということで参加しました。

Developers Summit code your future ~エッジな技術領域とエンジニアのキャリアデザインについて語ろう~

day 1 (5/23)

  • [Keynote] The New Age of Intelligence
  • [TL02] “Shift Left” で問題の早期発見を実現する、最新 Visual Studio の品質チェック・テスト機能の使い方
  • [DO03] 50 分でわかるテスト駆動開発

ラスト2枠はブース出展の担当だったため不参加。

f:id:tech-tsubaki:20170527222430j:plain

参加者パーティ

抽選でBluetoothキーボードが当たりました。抽選番号は幸運にもマリアノ・リベラ「42」

de:codeのパーリィで当選したキーボードの開封の儀

day 2 (5/24)

  • [CT04] AI サービスの作り方、育て方
  • [MW05] その API、本当に大丈夫? ~ 公開前に知っておくべき API の保護と最適化 ~
  • [AC07] 米国マイクロソフト本社で体験したノウハウを伝授!マイクロサービス実行基盤Azure Service Fabricの勘所
  • [DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法
  • [AI09] いまさら聞けない、エンジニアのための機械学習のキホン
  • [TL13] Build 2017 Updates ~ Build/de:code 総括! テクノロジーとアプリ開発の最新動向

旅の〆