연습 - 원격 분석 데이터를 시뮬레이션할 Azure 함수 작성

완료됨

이 예제에서는 이벤트 소싱을 사용합니다. 원격 분석 데이터를 시뮬레이션하는 함수를 작성하고 이벤트 허브로 보내 보겠습니다. 나중에 다른 함수가 이 이벤트를 수신 대기하고 처리하여 Azure Cosmos DB로 만든 데이터베이스에 저장할 수 있습니다.

Visualization of event sourcing for buying coffee at a coffee shop.

환경 준비

다음 명령을 최대한 짧고 이해하기 쉽게 유지하도록 몇 가지 환경 변수를 정의해 보겠습니다. <value> 자리 표시자를 정의하고, 터미널 또는 명령줄 도구에서 다음 명령을 붙여넣고 실행합니다.

RESOURCE_GROUP=<value>
EVENT_HUB_NAMESPACE=<value>
EVENT_HUB_NAME=<value>
EVENT_HUB_AUTHORIZATION_RULE=<value>
COSMOS_DB_ACCOUNT=<value>
STORAGE_ACCOUNT=<value>
FUNCTION_APP=<value>
LOCATION=<value>

참고

LOCATION 변수를 설정하려면 az functionapp list-consumption-locations 명령을 확인하고 가장 가까운 위치를 사용하면 됩니다.

필수 구성 요소 만들기

Azure에서 리소스를 프로비전하는 데 다소 시간이 걸립니다. 나중에 오래 기다리지 않도록 구성 요소 만들기를 최대한 빨리 시작하겠습니다.

리소스 그룹 만들기

언제나 학습, 개념 증명 또는 프로토타입 리소스를 하나의 리소스 그룹에 모두 바인딩하는 것이 좋습니다. 이렇게 하면 사용되는 모든 서비스를 하나의 명령으로 편리하게 정리할 수 있습니다. 지정된 위치에 리소스 그룹을 만들려면 터미널에서 다음 명령을 실행합니다.

az group create \
    --name $RESOURCE_GROUP \
    --location $LOCATION

이벤트 허브 만들기 및 구성하기

이벤트 허브의 경우 수신 대기해야 하는 네임스페이스를 지정해야 합니다. 또한 ListenSend에 대한 권한 부여 규칙도 구성해야 합니다.

az eventhubs namespace create \
    --resource-group $RESOURCE_GROUP \
    --name $EVENT_HUB_NAMESPACE
az eventhubs eventhub create \
    --resource-group $RESOURCE_GROUP \
    --name $EVENT_HUB_NAME \
    --namespace-name $EVENT_HUB_NAMESPACE \
az eventhubs eventhub authorization-rule create \
    --resource-group $RESOURCE_GROUP \
    --name $EVENT_HUB_AUTHORIZATION_RULE \
    --eventhub-name $EVENT_HUB_NAME \
    --namespace-name $EVENT_HUB_NAMESPACE \
    --rights Listen Send

Azure 함수 작성, 구성 및 배포

이 예제를 가능한 한 현실적으로 만들려면 Azure 함수를 만들고 원격 메트릭 데이터를 시뮬레이션합니다. IoT 디바이스를 Azure 함수에 바인딩한 다음 실제 데이터를 가져올 수도 있습니다. 이 함수는 이벤트를 생성하는 함수이므로 p 또는 -p 플래그를 추가해 보겠습니다.

az storage account create \
    --resource-group $RESOURCE_GROUP \
    --name $STORAGE_ACCOUNT"p" \
    --sku Standard_LRS
az functionapp create \
    --resource-group $RESOURCE_GROUP \
    --name $FUNCTION_APP"-p"\
    --storage-account $STORAGE_ACCOUNT"p" \
    --consumption-plan-location $LOCATION \
    --runtime java \
    --functions-version 4

참고 항목

functions-version 4를 2와 3으로 사용하는 것은 2022년 12월에 더 이상 사용되지 않습니다.

az functionapp create 명령은 함수 애플리케이션을 만들 때 같은 이름으로 Application Insights 리소스도 만듭니다. 나중에 모니터링을 위해 해당 리소스를 사용합니다.

스토리지 계정 및 이벤트 허브에 대한 연결 문자열 검색하려면 다음 명령을 사용하여 환경 변수에 저장한 다음 명령으로 echo 표시합니다.

AZURE_WEB_JOBS_STORAGE=$( \
    az storage account show-connection-string \
        --resource-group $RESOURCE_GROUP \
        --name $STORAGE_ACCOUNT"p" \
        --query connectionString \
        --output tsv)
echo $AZURE_WEB_JOBS_STORAGE
EVENT_HUB_CONNECTION_STRING=$( \
    az eventhubs eventhub authorization-rule keys list \
        --resource-group $RESOURCE_GROUP \
        --name $EVENT_HUB_AUTHORIZATION_RULE \
        --eventhub-name $EVENT_HUB_NAME \
        --namespace-name $EVENT_HUB_NAMESPACE \
        --query primaryConnectionString \
        --output tsv)
echo $EVENT_HUB_CONNECTION_STRING

Azure Function 계정의 애플리케이션 설정에 연결 문자열을 저장하려면 터미널에서 다음 명령을 실행합니다.

az functionapp config appsettings set \
    --resource-group $RESOURCE_GROUP \
    --name $FUNCTION_APP"-p" \
    --settings \
        AzureWebJobsStorage=$AZURE_WEB_JOBS_STORAGE \
        EventHubConnectionString=$EVENT_HUB_CONNECTION_STRING

이제 Azure 리소스 이벤트 허브와 Azure 함수가 만들어지고 함께 제대로 작동하도록 구성됩니다.

이제는 Maven를 사용하여 로컬 함수 프로젝트를 만듭니다.

mvn archetype:generate --batch-mode \
    -DarchetypeGroupId=com.microsoft.azure \
    -DarchetypeArtifactId=azure-functions-archetype \
    -DappName=$FUNCTION_APP"-p" \
    -DresourceGroup=$RESOURCE_GROUP \
    -DappRegion=$LOCATION \
    -DappServicePlanName=$LOCATION"plan" \
    -DgroupId=com.learn \
    -DartifactId=telemetry-functions-producer

이 명령은 telemetry-functions-producer 폴더 내에 다음과 같은 여러 파일을 생성합니다.

  • 미리 정의된 Azure 종속성이 있는 pom.xml 빌드 파일
  • 로컬 배포 및 수동 테스트를 위한 애플리케이션 설정을 저장할 local.settings.json 파일
  • Azure Functions 확장 번들을 사용하도록 설정하는 host.json 파일
  • 기본 HTTP 트리거 함수를 포함하는 Function.java 파일
  • 이 학습 모듈에서 사용하지 않는 몇 가지 테스트 파일

이 Learn 모듈에서는 테스트 파일을 건드리지 않으므로 자유롭게 삭제할 수 있습니다.

cd telemetry-functions-producer
rm -r src/test

로컬 실행을 위해 애플리케이션 설정을 검색하여 local.settings.json 파일에 저장해야 합니다. fetch-app-settings 명령을 실행하여 이 작업을 자동으로 수행할 수 있습니다.

func azure functionapp fetch-app-settings $FUNCTION_APP"-p"

이제 Function.java 파일을 열고 그 내용을 다음 코드로 바꿉니다.

package com.learn;

import com.microsoft.azure.functions.annotation.EventHubOutput;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.TimerTrigger;
import com.microsoft.azure.functions.ExecutionContext;
public class Function {

    @FunctionName("generateSensorData")
    @EventHubOutput(
        name = "event",
        eventHubName = "", // blank because the value is included in the connection string
        connection = "EventHubConnectionString")
    public TelemetryItem generateSensorData(
        @TimerTrigger(
            name = "timerInfo",
            schedule = "*/10 * * * * *") // every 10 seconds
            String timerInfo,
        final ExecutionContext context) {
            context.getLogger().info("Java Timer trigger function executed at: " + java.time.LocalDateTime.now());
            double temperature = Math.random() * 100;
            double pressure = Math.random() * 50;
        return new TelemetryItem(temperature, pressure);
    }
}

generateSensorData 함수는 온도 및 압력 판독값을 이벤트 허브에 보내는 센서를 시뮬레이션합니다. 타이머 트리거는 10초마다 이 함수를 실행하고, 이벤트 허브 출력 바인딩은 반환 값을 이벤트 허브에 보냅니다.

이벤트 허브에서 메시지를 받으면 이벤트가 생성됩니다.

이 함수에서 사용하는 데이터는 구현해야 하는 TelemetryItem이라는 클래스를 사용하여 저장됩니다. TelemetryItem.java라는 새 파일을 Function.java와 같은 위치에 만들고 다음 코드를 추가합니다.

package com.learn;

public class TelemetryItem {

    private String id;
    private double temperature;
    private double pressure;
    private boolean isNormalPressure;
    private status temperatureStatus;
    static enum status {
        COOL,
        WARM,
        HOT
    }

    public TelemetryItem(double temperature, double pressure) {
        this.temperature = temperature;
        this.pressure = pressure;
    }

    public String getId() {
        return id;
    }

    public double getTemperature() {
        return temperature;
    }

    public double getPressure() {
        return pressure;
    }

    @Override
    public String toString() {
        return "TelemetryItem={id=" + id + ",temperature="
            + temperature + ",pressure=" + pressure + "}";
    }

    public boolean isNormalPressure() {
        return isNormalPressure;
    }

    public void setNormalPressure(boolean isNormal) {
        this.isNormalPressure = isNormal;
    }

    public status getTemperatureStatus() {
        return temperatureStatus;
    }

    public void setTemperatureStatus(status temperatureStatus) {
        this.temperatureStatus = temperatureStatus;
    }
}

로컬 실행

Azure Functions를 로컬로 실행하면 이미 전 세계로 스트리밍된 상태입니다. 또한 Azure Portal에서 검토할 수도 있습니다.

mvn clean package
mvn azure-functions:run

일부 빌드 및 시작 메시지 후에는 함수가 실행될 때마다 다음 예제와 비슷한 출력이 표시됩니다.

[2021-01-19T16:25:40.005Z] Executing 'Functions.generateSensorData' (Reason='Timer fired at 2021-01-19T17:25:40.0044630+01:00', Id=fcf567a3-03ec-4159-9714-aa4449861b30)
[2021-01-19T16:25:40.011Z] Java Timer trigger function executed at: 2021-01-19T17:25:40.009405
[2021-01-19T16:25:40.013Z] Function "generateSensorData" (Id: fcf567a3-03ec-4159-9714-aa4449861b30) invoked by Java Worker
[2021-01-19T16:25:40.048Z] Executed 'Functions.generateSensorData' (Succeeded, Id=fcf567a3-03ec-4159-9714-aa4449861b30, Duration=43ms)

참고

Azure 클라우드에서 함수를 배포하고 실행하기 전에 전 세계 로컬 머신에서 이벤트를 보낼 수 있습니다. 이는 개발, 디버깅 및 로컬 테스트에 매우 유용합니다.

Azure에 배포

mvn azure-functions:deploy 명령을 실행하여 Azure에서 배포를 트리거하고 계속 진행합니다.

mvn azure-functions:deploy