目次

概要

Azure Functions で Goはサポートされていない。( Azure Functions でサポートされている言語
・・が、カスタム ハンドラーを使用する事によって、サポート外の言語でも Azure Functions として利用する事ができる。
ここでは、カスタムハンドラーを使用して Go で実装した Azure Functions を動作させる方法について記載する。

カスタムハンドラーの仕組み

カスタムハンドラーは軽量のWebサーバとして動作するもので、Functions Host と Web通信する事により動作する。
https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-custom-handlers#overview


トリガー

ーー リクエスト ーー>
<ーー レスポンス ーー

Functions Host

ーー Webリクエスト ーー>
<ーー Webレスポンス ーー

カスタムハンドラー

つまり、Webサーバがかける言語であれば何でも動く。

ファイル構成

以下の通り構成する。

+ host.json
+ 関数名
    ┗ function.json
+ Webサーバ(スクリプト,実行可能ファイルなど)

準備

ローカルでの Azure Storage の開発とテスト用にAzurite エミュレーターをインストールしておく。
https://docs.microsoft.com/ja-jp/azure/storage/common/storage-use-azurite

インストール&起動

npm install -g azurite
azurite --silent --location ./azurite --debug ./azurite/debug.log

host.json の作成

参考
https://github.com/Azure-Samples/functions-custom-handlers/blob/master/go/host.json
Azure Functions 2.x 以降の host.json のリファレンス

・defaultExecutablePath で今回 Go で作成するWebサーバの実行可能ファイルのPATHを指定する。
・ローカル開発用の拡張機能バンドル(extensionBundle)を利用すれば、拡張機能バンドルを別途インストールしなくても良い。

{
	"version": "2.0",
	"extensionBundle": {
		"id": "Microsoft.Azure.Functions.ExtensionBundle",
		"version": "[1.*, 2.0.0)"
	},
	"httpWorker": {
		"description": {
			"defaultExecutablePath": "MyGoCustomHandlers.exe"
		}
	}
}

Azure functions が実行される Functions Host 上に既にランタイムがある場合

スクリプトのPATH を defaultWorkerPath で指定する。
注) nodejs は Azure functions のサポート対象言語なので、そもそもカスタムハンドラを使用する必要はない。

{
    "version": "2.0",
    "httpWorker": {
        "description": {
            "defaultExecutablePath": "node",
            "defaultWorkerPath": "server.js"
        }
    }
}

function.json の作成

参考: http://json.schemastore.org/function
   https://github.com/Azure-Samples/functions-custom-handlers/tree/master/go/BlobTrigger

以下、Blob トリガーにより起動される Functions の例

{
  "bindings" : [ {
    "type" : "blobTrigger",
    "direction" : "in",
    "name" : "triggerBlob",
    "path" : "test-input-container/{name}",
    "dataType" : "binary",
    "connection" : "AzureWebJobsStorage"
  },
  {
    "type" : "blob",
    "direction" : "out",
    "name" : "$return",
    "path" : "test-output-container/{name}",
    "dataType" : "binary",
    "connection" : "AzureWebJobsStorage"
  } ]
}

local.settings.json の作成

{
    "IsEncrypted": false,
    "Values": {
      "AzureWebJobsStorage": "YOUR_STORAGE_CONNECTION_STRING"
    }   
}

ローカルのストレージエミュレータに接続する場合は以下の通り設定する。

       :
      "AzureWebJobsStorage": "UseDevelopmentStorage=true"
       :

処理の作成

以下、test-input-container にアップロードされたファイルを base64エンコードしたものを test-output-container に出力する例。

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
)

type ReturnValue struct {
	Data string
}
type InvokeResponse struct {
	Outputs     map[string]interface{}
	Logs        []string
	ReturnValue interface{}
}

type InvokeRequest struct {
	Data     map[string]interface{}
	Metadata map[string]interface{}
}

func blobTriggerHandler(w http.ResponseWriter, r *http.Request) {
	var invokeReq InvokeRequest
	d := json.NewDecoder(r.Body)
	decodeErr := d.Decode(&invokeReq)
	if decodeErr != nil {
		http.Error(w, decodeErr.Error(), http.StatusBadRequest)
		return
	}
	fmt.Println("The JSON data is:invokeReq metadata......")
	fmt.Println(invokeReq.Metadata)

        // データはBASE64エンコードされいる
	returnValue := invokeReq.Data["triggerBlob"]
	invokeResponse := InvokeResponse{Logs: []string{"test log1", "test log2"}, ReturnValue: returnValue}

	js, err := json.Marshal(invokeResponse)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(js)
}

func main() {
	httpInvokerPort, exists := os.LookupEnv("FUNCTIONS_HTTPWORKER_PORT")
	if exists {
		fmt.Println("FUNCTIONS_HTTPWORKER_PORT: " + httpInvokerPort)
	}
	mux := http.NewServeMux()
	mux.HandleFunc("/BlobTrigger", blobTriggerHandler)
	log.Println("Go server Listening...on httpInvokerPort:", httpInvokerPort)
	log.Fatal(http.ListenAndServe(":"+httpInvokerPort, mux))
}

レスポンスとして以下を返却する。

ペイロードのキーデータ型解説
OutputsJSONfunction.json ファイルの bindings 配列によって定義される応答値。
LogsarrayFunctions の呼び出しログとして表示するメッセージ。
ReturnValuestringレスポンス本文。(function.json ファイルの $return として出力が構成されている場合)

https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-custom-handlers#response-payload

動作確認

カスタムハンドラ起動

go build
func start
  :
  :
Now listening on: http://0.0.0.0:7071
Application started. Press Ctrl+C to shut down.
  :

テスト用のBlobストレージコンテナの作成

# ローカルのエミュレータに接続するように環境変数を設定
export AZURE_STORAGE_CONNECTION_STRING="UseDevelopmentStorage=true"

# 入出力用のコンテナをそれぞれ作成
az storage container create -n test-input-container
az storage container create -n test-out-container

コンテナにファイルをアップロード

az storage blob upload -f ./sample.txt -c test-input-container -n sample.txt

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS