Share via


Tutorial: Criar uma função em Java com um gatilho do Hub de Eventos e uma ligação de saída do Azure Cosmos DB

Este tutorial mostra como usar o Azure Functions para criar uma função Java que analisa um fluxo contínuo de dados de temperatura e pressão. Os eventos do hub de eventos que representam leituras do sensor acionam a função. A função processa os dados do evento e, em seguida, adiciona entradas de status a uma instância do Azure Cosmos DB.

Neste tutorial, você:

  • Crie e configure recursos do Azure usando a CLI do Azure.
  • Crie e teste funções Java que interagem com esses recursos.
  • Implante suas funções no Azure e monitore-as com o Application Insights.

Se não tiver uma subscrição do Azure, crie uma conta gratuita do Azure antes de começar.

Pré-requisitos

Para concluir este tutorial, você deve ter o seguinte instalado:

  • Use o ambiente Bash no Azure Cloud Shell. Para obter mais informações, consulte Guia de início rápido para Bash no Azure Cloud Shell.

  • Se preferir executar comandos de referência da CLI localmente, instale a CLI do Azure. Se estiver a utilizar o Windows ou macOS, considere executar a CLI do Azure num contentor Docker. Para obter mais informações, consulte Como executar a CLI do Azure em um contêiner do Docker.

    • Se estiver a utilizar uma instalação local, inicie sessão no CLI do Azure ao utilizar o comando az login. Para concluir o processo de autenticação, siga os passos apresentados no seu terminal. Para outras opções de entrada, consulte Entrar com a CLI do Azure.

    • Quando solicitado, instale a extensão da CLI do Azure na primeira utilização. Para obter mais informações sobre as extensões, veja Utilizar extensões com o CLI do Azure.

    • Execute o comando az version para localizar a versão e as bibliotecas dependentes instaladas. Para atualizar para a versão mais recente, execute o comando az upgrade.

Importante

A JAVA_HOME variável de ambiente deve ser definida como o local de instalação do JDK para concluir este tutorial.

Se você preferir usar o código para este tutorial diretamente, consulte o repositório de exemplo java-functions-eventhub-cosmosdb .

Criar recursos do Azure

Neste tutorial, você precisará destes recursos:

  • Um grupo de recursos para conter os outros recursos
  • Um namespace de Hubs de Eventos, hub de eventos e regra de autorização
  • Uma conta, banco de dados e coleção do Azure Cosmos DB
  • Um aplicativo de função e uma conta de armazenamento para hospedá-lo

As seções a seguir mostram como criar esses recursos usando a CLI do Azure.

Definir variáveis de ambiente

Em seguida, crie algumas variáveis de ambiente para os nomes e a localização dos recursos que você criará. Use os comandos a seguir, substituindo os <value> espaços reservados por valores de sua escolha. Os valores devem estar em conformidade com as regras de nomenclatura e restrições para recursos do Azure. Para a LOCATION variável, use um dos valores produzidos pelo az functionapp list-consumption-locations comando.

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>

O restante deste tutorial usa essas variáveis. Lembre-se de que essas variáveis persistem apenas durante a sua sessão atual da CLI do Azure ou do Cloud Shell. Você precisará executar esses comandos novamente se usar uma janela de terminal local diferente ou se a sessão do Cloud Shell expirar.

Criar um grupo de recursos

O Azure usa grupos de recursos para coletar todos os recursos relacionados em sua conta. Dessa forma, você pode visualizá-los como uma unidade e excluí-los com um único comando quando terminar de usá-los.

Use o seguinte comando para criar um grupo de recursos:

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

Criar um hub de eventos

Em seguida, crie um namespace de Hubs de Eventos do Azure, um hub de eventos e uma regra de autorização usando os seguintes comandos:

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 \
    --message-retention 1
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

O namespace Hubs de Eventos contém o hub de eventos real e sua regra de autorização. A regra de autorização permite que suas funções enviem mensagens para o hub e ouçam os eventos correspondentes. Uma função envia mensagens que representam dados de telemetria. Outra função escuta eventos, analisa os dados do evento e armazena os resultados no Azure Cosmos DB.

Criar uma base de dados do Azure Cosmos DB

Em seguida, crie uma conta, um banco de dados e uma coleção do Azure Cosmos DB usando os seguintes comandos:

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'

O partition-key-path valor particiona seus dados com base no temperatureStatus valor de cada item. A chave de partição permite que o Azure Cosmos DB aumente o desempenho dividindo seus dados em subconjuntos distintos que ele pode acessar independentemente.

Criar uma conta de armazenamento e um aplicativo de função

Em seguida, crie uma conta de Armazenamento do Azure, que é exigida pelo Azure Functions e, em seguida, crie o aplicativo de função. Use os seguintes comandos:

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 3

Quando o comando cria seu aplicativo de função, ele também cria um recurso do Application Insights com o az functionapp create mesmo nome. O aplicativo de função é configurado automaticamente com uma configuração chamada APPINSIGHTS_INSTRUMENTATIONKEY que o conecta ao Application Insights. Você pode exibir a telemetria do aplicativo depois de implantar suas funções no Azure, conforme descrito posteriormente neste tutorial.

Configurar seu aplicativo de função

Seu aplicativo de função precisará acessar os outros recursos para funcionar corretamente. As seções a seguir mostram como configurar seu aplicativo de função para que ele possa ser executado em sua máquina local.

Recuperar cadeias de conexão de recursos

Use os seguintes comandos para recuperar o armazenamento, o hub de eventos e as cadeias de conexão do Azure Cosmos DB e salvá-las em variáveis de ambiente:

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

Essas variáveis são definidas como valores recuperados dos comandos da CLI do Azure. Cada comando usa uma consulta JMESPath para extrair a cadeia de conexão da carga JSON retornada. As cadeias de conexão também são exibidas usando echo para que você possa confirmar que elas foram recuperadas com êxito.

Atualizar as configurações do aplicativo de função

Em seguida, use o seguinte comando para transferir os valores da cadeia de conexão para as configurações do aplicativo em sua conta do 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

Os seus recursos do Azure foram agora criados e configurados para funcionarem corretamente em conjunto.

Crie e teste as suas funções

Em seguida, você criará um projeto em sua máquina local, adicionará código Java e o testará. Você usará comandos que funcionam com o Plug-in do Azure Functions para Maven e as Ferramentas Principais do Azure Functions. Suas funções serão executadas localmente, mas usarão os recursos baseados em nuvem que você criou. Depois de fazer com que as funções funcionem localmente, você pode usar o Maven para implantá-las na nuvem e ver seus dados e análises se acumularem.

Se você usou o Cloud Shell para criar seus recursos, não estará conectado ao Azure localmente. Nesse caso, use o comando para iniciar o az login processo de login baseado em navegador. Em seguida, se necessário, defina a assinatura padrão com az account set --subscription seguido pelo ID da assinatura. Finalmente, execute os seguintes comandos para recriar algumas variáveis de ambiente em sua máquina local. Substitua os <value> espaços reservados pelos mesmos valores usados anteriormente.

RESOURCE_GROUP=<value>
FUNCTION_APP=<value>

Criar um projeto de funções locais

Use o seguinte comando Maven para criar um projeto de funções e adicionar as dependências necessárias.

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

Este comando gera vários arquivos dentro de uma telemetry-functions pasta:

  • Um pom.xml arquivo para uso com o Maven
  • Um local.settings.json arquivo para manter as configurações do aplicativo para teste local
  • Um host.json arquivo que habilita o Pacote de Extensão do Azure Functions, necessário para a vinculação de saída do Azure Cosmos DB em sua função de análise de dados
  • Um Function.java arquivo que inclui uma implementação de função padrão
  • Alguns arquivos de teste que este tutorial não precisa

Para evitar erros de compilação, você precisará excluir os arquivos de teste. Execute os seguintes comandos para navegar até a nova pasta do projeto e excluir a pasta de teste:

cd telemetry-functions
rm -r src/test

Recuperar as configurações do aplicativo de função para uso local

Para testes locais, seu projeto de função precisará das cadeias de conexão que você adicionou ao seu aplicativo de função no Azure anteriormente neste tutorial. Use o seguinte comando Ferramentas Principais do Azure Functions, que recupera todas as configurações do aplicativo de função armazenadas na nuvem e as adiciona ao seu local.settings.json arquivo:

func azure functionapp fetch-app-settings $FUNCTION_APP

Adicionar código Java

Em seguida, abra o arquivo e substitua o Function.java conteúdo pelo código a seguir.

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",
            containerName = "TelemetryInfo",
            connection = "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);
    }
}

Como você pode ver, esse arquivo contém duas funções generateSensorData e processSensorData. A generateSensorData função simula um sensor que envia leituras de temperatura e pressão para o hub de eventos. Um gatilho de temporizador executa a função a cada 10 segundos e uma ligação de saída do hub de eventos envia o valor de retorno para o hub de eventos.

Quando o hub de eventos recebe a mensagem, ele gera um evento. A processSensorData função é executada quando recebe o evento. Em seguida, ele processa os dados do evento e usa uma associação de saída do Azure Cosmos DB para enviar os resultados para o Azure Cosmos DB.

Os dados usados por essas funções são armazenados usando uma classe chamada TelemetryItem, que você precisará implementar. Crie um novo arquivo chamado TelemetryItem.java no mesmo local que Function.java e adicione o seguinte código:

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;
    }
}

Executar localmente

Agora você pode criar e executar as funções localmente e ver os dados aparecerem no seu Azure Cosmos DB.

Use os seguintes comandos do Maven para criar e executar as funções:

mvn clean package
mvn azure-functions:run

Após algumas mensagens de compilação e inicialização, você verá uma saída semelhante ao exemplo a seguir para cada vez que as funções forem executadas:

[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)

Em seguida, você pode ir para o portal do Azure e navegar até sua conta do Azure Cosmos DB. Selecione Data Explorer, expanda TelemetryInfo e selecione Itens para exibir seus dados quando eles chegarem.

Azure Cosmos DB Data Explorer

Implantar no Azure e exibir telemetria de aplicativo

Finalmente, você pode implantar seu aplicativo no Azure e verificar se ele continua a funcionar da mesma forma que funcionava localmente.

Implante seu projeto no Azure usando o seguinte comando:

mvn azure-functions:deploy

Suas funções agora são executadas no Azure e continuam a acumular dados no Azure Cosmos DB. Você pode exibir seu aplicativo de função implantado no portal do Azure e exibir a telemetria do aplicativo por meio do recurso do Application Insights conectado, conforme mostrado nas seguintes capturas de tela:

Transmissão de métricas ao vivo:

Application Insights Live Metrics Stream

Desempenho:

Application Insights Performance blade

Clean up resources (Limpar recursos)

Quando já não precisar dos recursos do Azure criados neste tutorial, pode utilizar o comando abaixo para os eliminar:

az group delete --name $RESOURCE_GROUP

Próximos passos

Neste tutorial, você aprendeu como criar uma Função do Azure que manipula eventos do Hub de Eventos e atualiza uma instância do Azure Cosmos DB. Para obter mais informações, consulte o Guia do desenvolvedor Java do Azure Functions. Para obter informações sobre as anotações usadas, consulte a referência com.microsoft.azure.functions.annotation .

Este tutorial usou variáveis de ambiente e configurações de aplicativo para armazenar segredos, como cadeias de conexão. Para obter informações sobre como armazenar esses segredos no Cofre da Chave do Azure, consulte Usar referências do Cofre da Chave para o Serviço de Aplicativo e o Azure Functions.

Em seguida, saiba como usar o CI/CD do Azure Pipelines para implantação automatizada: