0
0

More than 1 year has passed since last update.

Azure Functions を Java の App Service でサービスエンドポイント経由の Azure Storage Queue とバインドしてみた

Last updated at Posted at 2023-06-10

Azure Functions を Java の App Service でサービスエンドポイント経由の Azure Storage Queue とバインドしてみました。

検証環境を準備

bash
# 環境変数をセットします
prefix=mnrfncjq
region=japaneast

# リソースグループを作成します
az group create \
  --name ${prefix}-rg \
  --location $region

# VNET を作成します
az network vnet create \
  --name ${prefix}-vnet \
  --resource-group ${prefix}-rg \
  --address-prefixes 10.0.0.0/24

# NSG を作成します
az network nsg create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-nsg

# サブネットを作成します
az network vnet subnet create \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vnet \
  --name fun-subnet \
  --address-prefix 10.0.0.0/26 \
  --network-security-group ${prefix}-nsg \
  --service-endpoints Microsoft.Storage

# Azure Storage を作成します
az storage account create \
  --name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --sku Standard_LRS

# キューを作成します
az storage queue create \
  --name messages \
  --account-name ${prefix}stor

# Azure Storage をネットワーク制限します
az storage account update \
  --name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --default-action deny

# 自分の IP アドレスからのアクセスを許可します
az storage account network-rule add \
  --account-name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --ip-address $(curl -s inet-ip.info)

# サブネットからのアクセスを許可します
az storage account network-rule add \
  --account-name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vnet \
  --subnet fun-subnet

# Application Insights を作成します
az monitor app-insights component create \
  --app ${prefix}-ai \
  --location $region \
  --resource-group ${prefix}-rg

# App Service Plan を作成します
az appservice plan create \
  --name ${prefix}-funplan \
  --resource-group ${prefix}-rg \
  --sku B1

# Azure Functions を作成します
az functionapp create \
  --name ${prefix}-fun \
  --resource-group ${prefix}-rg \
  --plan ${prefix}-funplan \
  --runtime java \
  --functions-version 4 \
  --storage-account ${prefix}stor \
  --app-insights ${prefix}-ai \
  --https-only \
  --os-type Windows \
  --assign-identity

# FTP を無効にします
az webapp config set \
  --name ${prefix}-fun \
  --resource-group ${prefix}-rg \
  --ftps-state Disabled

# 自分の IP アドレスからのアクセスを許可します
az webapp config access-restriction add \
  --name ${prefix}-fun \
  --resource-group ${prefix}-rg \
  --priority 100 \
  --rule-name MyIP \
  --action Allow \
  --ip-address $(curl -s inet-ip.info)

# VNET 統合して Functions から Azure Storage にアクセスできるようにします
az webapp vnet-integration add \
  --name ${prefix}-fun \
  --resource-group ${prefix}-rg \
  --vnet ${prefix}-vnet \
  --subnet fun-subnet

ローカルで Azure Functions を作成

bash
# Maven で Java 11 の Functions 雛形を作成します 
mvn archetype:generate -DarchetypeGroupId=com.microsoft.azure -DarchetypeArtifactId=azure-functions-archetype -DjavaVersion=11

# 入力サンプル
# groupId: com.example
# artifactId: java-func-example
# version	1.0-SNAPSHOT
# package	com.example

# 作成されたディレクトリに移動します
cd java-func-example

# Maven で Functions アプリをビルドします
mvn clean package

# Functions アプリをローカルで動かします
mvn azure-functions:run

Functions アプリに QueueOutput バインドを追加

src/main/java/com/example/Functions.java
package com.example;

// import com.microsoft.azure.functions.ExecutionContext;
// import com.microsoft.azure.functions.HttpMethod;
// import com.microsoft.azure.functions.HttpRequestMessage;
// import com.microsoft.azure.functions.HttpResponseMessage;
// import com.microsoft.azure.functions.HttpStatus;
// import com.microsoft.azure.functions.annotation.AuthorizationLevel;
// import com.microsoft.azure.functions.annotation.FunctionName;
// import com.microsoft.azure.functions.annotation.HttpTrigger;
import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;

import java.util.Optional;

/**
 * Azure Functions with HTTP Trigger.
 */
public class Function {
    /**
     * This function listens at endpoint "/api/HttpExample". Two ways to invoke it using "curl" command in bash:
     * 1. curl -d "HTTP Body" {your host}/api/HttpExample
     * 2. curl "{your host}/api/HttpExample?name=HTTP%20Query"
     */
    @FunctionName("HttpExample")
    public HttpResponseMessage run(
            @HttpTrigger(
                name = "req",
                methods = {HttpMethod.GET, HttpMethod.POST},
                authLevel = AuthorizationLevel.ANONYMOUS)
                HttpRequestMessage<Optional<String>> request,
            @QueueOutput(
                name = "msg",
                queueName = "messages",
                connection = "AzureWebJobsStorage")
                OutputBinding<String> msg,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        // Parse query parameter
        final String query = request.getQueryParameters().get("name");
        final String name = request.getBody().orElse(query);

        if (name == null) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
        } else {
            msg.setValue(name);
            return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
        }
    }
}

Functions アプリのデプロイ設定

pom.xmlの該当箇所
                <configuration>
                    <!-- function app name -->
                    <appName>mnrfncjq-fun</appName>
                    <!-- function app resource group -->
                    <resourceGroup>mnrfncjq-rg</resourceGroup>
                    <!-- function app service plan name -->
                    <appServicePlanName>mnrfncjq-funplan</appServicePlanName>
                    <!-- function app region-->
                    <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details#supported-regions for all valid values -->
                    <region>japaneast</region>
                    <!-- function pricingTier, default to be consumption if not specified -->
                    <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details#supported-pricing-tiers for all valid values -->
                    <pricingTier>B1</pricingTier>
                    <!-- Whether to disable application insights, default is false -->
                    <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details for all valid configurations for application insights-->
                    <!-- <disableAppInsights></disableAppInsights> -->
                    <runtime>
                        <!-- runtime os, could be windows, linux or docker-->
                        <os>windows</os>
                        <javaVersion>11</javaVersion>
                    </runtime>
                    <appSettings>
                        <property>
                            <name>FUNCTIONS_EXTENSION_VERSION</name>
                            <value>~4</value>
                        </property>
                    </appSettings>
                </configuration>

Azure Functions にデプロイして動作確認

bash
# テスト用のコードを無効化します
mv src/test/java/com/example/FunctionTest.java src/test/java/com/example/FunctionTest.java.bak
mv src/test/java/com/example/HttpResponseMessageMock.java src/test/java/com/example/HttpResponseMessageMock.java.bak

# Functions アプリをビルドします
mvn package

# Functions アプリをデプロイします
mvn azure-functions:deploy

# Functions 経由でキューにメッセージを登録します
curl https://mnrfncjq-fun.azurewebsites.net/api/httpexample?name=HelloMessage

# キューにメッセージ登録されていれば成功
# Application Insights の trace ログにもメッセージが表示されていれば成功

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0