練習 - 建立 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

注意

在 2022 年 12 月,使用 functions-version 4 作為 2 和 3 已被取代。

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 Functions 帳戶的應用程式設定中,請在終端機中執行下列命令:

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 資料夾內產生數個檔案:

  • pom.xml 組建檔案,其中已預先定義 Azure 相依性。
  • local.settings.json 檔案,其中包含用於本機部署和手動測試的應用程式設定。
  • host.json 檔案,可啟用 Azure Functions 延伸模組套件組合。
  • Function.java 檔案,其中包含預設 HTTP 觸發程序函式。
  • 此 Learn 課程模組未使用的幾個測試檔案。

我們在此 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 的類別進行儲存,而您必須加以實作。 在與 Function.java 相同的位置中建立名為 TelemetryItem.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 函式時,這些函式已串流至全球各地! 此外,您也可以在 Azure 入口網站中進行檢閱。

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