教學課程:使用事件中樞觸發程式和 Azure Cosmos DB 輸出系結在 JAVA 中建立函式
本教學課程會說明如何使用 Azure Functions 來建立 Java 函式,以分析溫度和壓力資料的連續資料流。 代表感應器讀數的事件中樞事件會觸發函式。 函數會處理事件資料,然後將狀態項目新增至 Azure Cosmos DB 執行個體。
在本教學課程中,您將會:
- 使用 Azure CLI 來建立和設定 Azure 資源。
- 建立和測試會與這些資源互動的 Java 函式。
- 將函式部署到 Azure,並使用 Application Insights 加以監視。
如果您沒有 Azure 訂閱,請在開始之前,先建立 Azure 免費帳戶。
必要條件
若要完成本教學課程,您必須安裝下列項目:
- Java Developer Kit 第 8 版
- Apache Maven 3.0 版或更新版本
- Azure Functions Core Tools 2.6.666 版或更新版本
在 Azure Cloud Shell 中使用 Bash 環境。 如需詳細資訊,請參閱 Azure Cloud Shell 中的 Bash 快速入門。
若要在本地執行 CLI 參考命令,請安裝 Azure CLI。 若您在 Windows 或 macOS 上執行,請考慮在 Docker 容器中執行 Azure CLI。 如需詳細資訊,請參閱〈如何在 Docker 容器中執行 Azure CLI〉。
如果您使用的是本機安裝,請使用 az login 命令,透過 Azure CLI 來登入。 請遵循您終端機上顯示的步驟,完成驗證程序。 如需其他登入選項,請參閱使用 Azure CLI 登入。
出現提示時,請在第一次使用時安裝 Azure CLI 延伸模組。 如需擴充功能詳細資訊,請參閱使用 Azure CLI 擴充功能。
執行 az version 以尋找已安裝的版本和相依程式庫。 若要升級至最新版本,請執行 az upgrade。
重要
JAVA_HOME
環境變數必須設定為 JDK 的安裝位置,才能完成本教學課程。
如果您想要直接使用本教學課程的程式碼,請參閱 java-functions-eventhub-cosmosdb 範例存放庫。
建立 Azure 資源
在本教學課程中,您將需要下列資源:
- 資源群組,以便包含其他資源
- 事件中樞的命名空間、事件中樞和授權規則
- Azure Cosmos DB 帳戶、資料庫和集合
- 函式應用程式和用來裝載函式應用程式的儲存體帳戶
下列各節會說明如何使用 Azure CLI 來建立這些資源。
設定環境變數
接下來,針對您將建立的資源,為其名稱和位置建立一些環境變數。 使用下列命令,並將 <value>
預留位置取代為您選擇的值。 所選擇的這些值應符合 Azure 資源的命名規則和限制。 針對 LOCATION
變數,請使用 az functionapp list-consumption-locations
命令所產生的其中一個值。
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>
本教學課程的其餘部分會使用這些變數。 請注意,這些變數只會在目前 Azure CLI 或 Cloud Shell 工作階段的持續期間內存在。 如果您使用不同的本機終端機視窗,抑或是 Cloud Shell 工作階段逾時,您就必須再次執行這些命令。
建立資源群組
Azure 會使用資源群組來收集您帳戶中的所有相關資源。 如此一來,您就可以進行整體檢視,並在用完這些資源時,透過單一命令即可將其全部刪除。
請使用下列命令來建立資源群組:
建立事件中樞
接下來,請使用下列命令建立 Azure 事件中樞的命名空間、事件中樞和授權規則:
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 \
--retention-time 1 \
--cleanup-policy Delete
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 Cosmos DB 中。
建立 Azure Cosmos DB
接下來,請使用下列命令建立 Azure Cosmos DB 帳戶、資料庫和集合:
az cosmosdb create \
--resource-group $RESOURCE_GROUP \
--name $COSMOS_DB_ACCOUNT
az cosmosdb sql database create \
--resource-group $RESOURCE_GROUP \
--account-name $COSMOS_DB_ACCOUNT \
--name TelemetryDb
az cosmosdb sql container create \
--resource-group $RESOURCE_GROUP \
--account-name $COSMOS_DB_ACCOUNT \
--database-name TelemetryDb \
--name TelemetryInfo \
--partition-key-path '/temperatureStatus'
partition-key-path
值會根據每個項目的 temperatureStatus
值來分割您的資料。 分割區索引鍵可讓 Azure Cosmos DB 將資料分成可供其獨立存取的不同子集,藉以提升效能。
建立儲存體帳戶和函式應用程式
接下來,請建立 Azure Functions 所需的 Azure 儲存體帳戶,然後建立函式應用程式。 使用下列命令:
az storage account create \
--resource-group $RESOURCE_GROUP \
--name $STORAGE_ACCOUNT \
--sku Standard_LRS
az functionapp create \
--resource-group $RESOURCE_GROUP \
--name $FUNCTION_APP \
--storage-account $STORAGE_ACCOUNT \
--consumption-plan-location $LOCATION \
--runtime java \
--functions-version 4
az functionapp create
命令在建立您的函式應用程式時,也會一併建立具有相同名稱的 Application Insights 資源。 函式應用程式則會使用名為 APPINSIGHTS_INSTRUMENTATIONKEY
的設定 (可供其連線至 Application Insights) 自動進行設定。 將函式部署至 Azure 之後,您就可以檢視應用程式遙測資料,如本教學課程稍後所述。
設定函式應用程式
函式應用程式必須存取其他資源才能正常運作。 下列各節會說明如何設定函式應用程式,使其可在您的本機電腦上執行。
擷取資源的連接字串
請使用下列命令來擷取儲存體、事件中樞和 Azure Cosmos DB 的連接字串,並將這些項目儲存在環境變數中:
注意
Microsoft 建議您使用最安全的可用驗證流程。 此程式中所述的驗證流程,例如資料庫、快取、傳訊或 AI 服務,在應用程式中需要高度的信任,而且不會在其他流程中帶來風險。 只有在更安全的選項,例如無密碼或無密鑰連線的受控識別時,才能使用此流程。 針對本機計算機作業,偏好使用無密碼或無密鑰連線的使用者身分識別。
AZURE_WEB_JOBS_STORAGE=$( \
az storage account show-connection-string \
--name $STORAGE_ACCOUNT \
--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
COSMOS_DB_CONNECTION_STRING=$( \
az cosmosdb keys list \
--resource-group $RESOURCE_GROUP \
--name $COSMOS_DB_ACCOUNT \
--type connection-strings \
--query 'connectionStrings[0].connectionString' \
--output tsv)
echo $COSMOS_DB_CONNECTION_STRING
這些變數會設定為透過 Azure CLI 命令所擷取到的值。 每個命令都會使用 JMESPath 查詢,從傳回的 JSON 承載中擷取連接字串。 連接字串也會使用 echo
加以顯示,以便讓您確認是否已成功擷取連接字串。
更新函式應用程式的設定
接下來,請使用下列命令將連接字串值傳送至 Azure Functions 帳戶中的應用程式設定:
az functionapp config appsettings set \
--resource-group $RESOURCE_GROUP \
--name $FUNCTION_APP \
--settings \
AzureWebJobsStorage=$AZURE_WEB_JOBS_STORAGE \
EventHubConnectionString=$EVENT_HUB_CONNECTION_STRING \
CosmosDBConnectionSetting=$COSMOS_DB_CONNECTION_STRING
您的 Azure 資源現已建立完成,並已設定為可正常搭配運作。
建立和測試函式
接下來,您會在本機電腦上建立專案、新增 Java 程式碼,並加以測試。 您會使用可與適用於 Maven 的 Azure Functions 外掛程式和 Azure Functions Core Tools 搭配運作的命令。 您的函式會在本機執行,但會使用您已建立的雲端式資源。 讓函式在本機運作之後,您就可以使用 Maven 將函式部署至雲端,並觀看資料和分析的累積。
如果您使用了 Cloud Shell 來建立資源,則不會在本機連線至 Azure。 在此情況下,請使用 az login
命令來啟動以瀏覽器為基礎的登入流程。 然後,如有必要,請使用 az account set --subscription
並於後面加上訂用帳戶識別碼來設定預設的訂用帳戶。 最後,請執行下列命令在本機電腦上重新建立某些環境變數。 將 <value>
預留位置取代為您先前使用的相同值。
建立本機 Functions 專案
請使用下列 Maven 命令來建立函式專案,並新增所需的相依性。
mvn archetype:generate --batch-mode \
-DarchetypeGroupId=com.microsoft.azure \
-DarchetypeArtifactId=azure-functions-archetype \
-DappName=$FUNCTION_APP \
-DresourceGroup=$RESOURCE_GROUP \
-DappRegion=$LOCATION \
-DgroupId=com.example \
-DartifactId=telemetry-functions
此命令會在 telemetry-functions
資料夾內產生數個檔案:
pom.xml
檔案,用來與 Maven 搭配使用local.settings.json
檔案,用來保存應用程式設定以進行本機測試host.json
檔案,可啟用 Azure Functions 延伸模組套件組合,此為資料分析函數中的 Azure Cosmos DB 輸出繫結所需項目Function.java
檔案,會包含預設的函式實作- 本教學課程不需要的幾個測試檔案
為避免編譯錯誤,您必須刪除測試檔案。 請執行下列命令以瀏覽至新的專案資料夾,並刪除測試資料夾:
擷取函式應用程式設定以供本機使用
為了進行本機測試,函式專案會需要您稍早在本教學課程中新增至 Azure 中函式應用程式的連接字串。 請使用下列 Azure Functions Core Tools 命令,來擷取儲存在雲端中的所有函式應用程式設定,並將這些設定新增至 local.settings.json
檔案:
注意
Microsoft 建議您使用最安全的可用驗證流程。 此程式中所述的驗證流程,例如資料庫、快取、傳訊或 AI 服務,在應用程式中需要高度的信任,而且不會在其他流程中帶來風險。 只有在更安全的選項,例如無密碼或無密鑰連線的受控識別時,才能使用此流程。 針對本機計算機作業,偏好使用無密碼或無密鑰連線的使用者身分識別。
新增 Java 程式碼
接下來,請開啟 Function.java
檔案,並以下列程式碼取代內容。
package com.example;
import com.example.TelemetryItem.status;
import com.microsoft.azure.functions.annotation.Cardinality;
import com.microsoft.azure.functions.annotation.CosmosDBOutput;
import com.microsoft.azure.functions.annotation.EventHubOutput;
import com.microsoft.azure.functions.annotation.EventHubTrigger;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.TimerTrigger;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.OutputBinding;
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);
}
@FunctionName("processSensorData")
public void processSensorData(
@EventHubTrigger(
name = "msg",
eventHubName = "", // blank because the value is included in the connection string
cardinality = Cardinality.ONE,
connection = "EventHubConnectionString")
TelemetryItem item,
@CosmosDBOutput(
name = "databaseOutput",
databaseName = "TelemetryDb",
collectionName = "TelemetryInfo",
connectionStringSetting = "CosmosDBConnectionSetting")
OutputBinding<TelemetryItem> document,
final ExecutionContext context) {
context.getLogger().info("Event hub message received: " + item.toString());
if (item.getPressure() > 30) {
item.setNormalPressure(false);
} else {
item.setNormalPressure(true);
}
if (item.getTemperature() < 40) {
item.setTemperatureStatus(status.COOL);
} else if (item.getTemperature() > 90) {
item.setTemperatureStatus(status.HOT);
} else {
item.setTemperatureStatus(status.WARM);
}
document.setValue(item);
}
}
如您所見,此檔案包含兩個函式,分別是 generateSensorData
和 processSensorData
。 generateSensorData
函式模擬將溫度和壓力讀數傳送到事件中樞的感應器。 計時器觸發程序每 10 秒執行一次該函式,而事件中樞輸出繫結會將傳回值傳送到事件中樞。
當事件中樞收到訊息時,其會產生事件。 processSensorData
函式會在接收事件時執行。 然後,此函式會處理事件資料,並使用 Azure Cosmos DB 輸出繫結將結果傳送至 Azure Cosmos DB。
這些函式所使用的資料會使用名為 TelemetryItem
的類別來加以儲存,而您必須加以實作。 在與 Function.java
相同的位置中建立名為 TelemetryItem.java
的新檔案,並新增下列程式碼:
package com.example;
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 Cosmos DB 中。
請使用下列 Maven 命令來建置和執行函式:
在一些建置和啟動訊息之後,每次函式執行時,您都會看到類似於下列範例的輸出:
[10/22/19 4:01:30 AM] Executing 'Functions.generateSensorData' (Reason='Timer fired at 2019-10-21T21:01:30.0016769-07:00', Id=c1927c7f-4f70-4a78-83eb-bc077d838410)
[10/22/19 4:01:30 AM] Java Timer trigger function executed at: 2019-10-21T21:01:30.015
[10/22/19 4:01:30 AM] Function "generateSensorData" (Id: c1927c7f-4f70-4a78-83eb-bc077d838410) invoked by Java Worker
[10/22/19 4:01:30 AM] Executed 'Functions.generateSensorData' (Succeeded, Id=c1927c7f-4f70-4a78-83eb-bc077d838410)
[10/22/19 4:01:30 AM] Executing 'Functions.processSensorData' (Reason='', Id=f4c3b4d7-9576-45d0-9c6e-85646bb52122)
[10/22/19 4:01:30 AM] Event hub message received: TelemetryItem={id=null,temperature=32.728691307527015,pressure=10.122563042388165}
[10/22/19 4:01:30 AM] Function "processSensorData" (Id: f4c3b4d7-9576-45d0-9c6e-85646bb52122) invoked by Java Worker
[10/22/19 4:01:38 AM] Executed 'Functions.processSensorData' (Succeeded, Id=1cf0382b-0c98-4cc8-9240-ee2a2f71800d)
然後,您可以移至 Azure 入口網站,並瀏覽至 Azure Cosmos DB 帳戶。 選取 [資料總管],展開 [TelemetryInfo],然後選取 [項目] 以便在資料抵達時進行檢視。
部署至 Azure 並檢視應用程式遙測資料
最後,您可以將應用程式部署至 Azure,並確認其可以和在本機時一樣繼續以相同方式運作。
使用下列命令將專案部署至 Azure:
您的函式現在會在 Azure 中執行,並繼續在 Azure Cosmos DB 中累積資料。 您可以在 Azure 入口網站中檢視已部署的函式應用程式,並透過已連線的 Application Insights 資源來檢視應用程式遙測資料,如下列螢幕擷取畫面所示:
即時計量資料流:
效能:
清除資源
當您完成使用本教學課程中建立的 Azure 資源時,您可以使用下列命令將其刪除:
下一步
在本教學課程中,您已瞭解如何建立 Azure 函數,以處理事件中樞的事件並更新 Azure Cosmos DB 執行個體。 如需詳細資訊,請參閱 Azure Functions Java 開發人員指南。 如需所用註釋的相關資訊,請參閱 com.microsoft.azure.functions.annotation 參考資料。
本教學課程使用了環境變數和應用程式設定來儲存秘密 (例如連接字串)。 如需在 Azure Key Vault 中儲存這些秘密的相關資訊,請參閱使用 App Service 和 Azure Functions 的 Key Vault 參考。
注意
Microsoft 建議您使用最安全的可用驗證流程。 此程式中所述的驗證流程,例如資料庫、快取、傳訊或 AI 服務,在應用程式中需要高度的信任,而且不會在其他流程中帶來風險。 只有在更安全的選項,例如無密碼或無密鑰連線的受控識別時,才能使用此流程。 針對本機計算機作業,偏好使用無密碼或無密鑰連線的使用者身分識別。
接下來,請了解如何使用 Azure Pipelines CI/CD 來進行自動化部署: