Compartilhar via


Tutorial: Armazenar dados na borda com bancos de dados do SQL Server

Aplica-se àmarca de seleção IoT Edge 1.4 IoT Edge 1.4

Importante

O IoT Edge 1.5 LTS e o IoT Edge 1.4 têm suporte para versões. Se você estiver em uma versão anterior, consulte Atualizar ioT Edge.

Implante um módulo do SQL Server para armazenar dados em um dispositivo que executa o Azure IoT Edge com contêineres do Linux.

Use o Azure IoT Edge e o SQL Server para armazenar e consultar dados na borda. O Azure IoT Edge tem recursos básicos de armazenamento para armazenar mensagens em cache se um dispositivo ficar offline e encaminhá-las quando a conexão for restabelecida. No entanto, talvez você queira recursos de armazenamento mais avançados, como poder consultar dados localmente. Seus dispositivos do IoT Edge podem usar bancos de dados locais para executar computação mais complexa sem precisar manter uma conexão com o Hub IoT.

Este artigo fornece instruções para implantar um banco de dados do SQL Server em um dispositivo IoT Edge. O Azure Functions, em execução no dispositivo IoT Edge, estrutura os dados de entrada e os envia para o banco de dados. As etapas neste artigo também podem ser aplicadas a outros bancos de dados que funcionam em contêineres, como MySQL ou PostgreSQL.

Neste tutorial, você aprenderá como:

  • Usar o Visual Studio Code para criar uma função do Azure
  • Implantar um banco de dados SQL em seu dispositivo IoT Edge
  • Usar o Visual Studio Code para criar módulos e implantá-los em seu dispositivo IoT Edge
  • Exibir dados gerados

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

Pré-requisitos

Antes de iniciar este tutorial, você deve ter passado pelo tutorial anterior para configurar seu ambiente de desenvolvimento para o desenvolvimento de contêiner do Linux: desenvolver módulos do Azure IoT Edge usando o Visual Studio Code. Ao concluir esse tutorial, você deve ter os seguintes pré-requisitos em vigor:

Este tutorial usa um módulo do Azure Functions para enviar dados ao SQL Server. Para desenvolver um módulo do IoT Edge com o Azure Functions, instale os seguintes pré-requisitos adicionais em seu computador de desenvolvimento:

Criar um projeto de função

Para enviar dados para um banco de dados, você precisa de um módulo que possa estruturar os dados corretamente e, em seguida, armazená-los em uma tabela.

Criar um novo projeto

As etapas a seguir mostram como criar uma função do IoT Edge usando o Visual Studio Code e a extensão do Azure IoT Edge.

  1. Abra o Visual Studio Code.

  2. Abra a paleta de comandos do Visual Studio Code selecionando Exibir>paleta de comandos.

  3. Na paleta de comandos, digite e execute o comando Azure IoT Edge: nova solução do IoT Edge. Na paleta de comandos, forneça as seguintes informações para criar sua solução:

    Campo Value
    Selecionar pasta Escolha o local em seu computador de desenvolvimento para o Visual Studio Code para criar os arquivos da solução.
    Fornecer um nome de solução Insira um nome descritivo para sua solução, como SqlSolution, ou aceite o padrão.
    Selecionar modelo de módulo Escolha O Azure Functions – C#.
    Fornecer um nome de módulo Nomeie o sqlFunction do módulo.
    Fornecer o repositório de imagens do Docker para o módulo Um repositório de imagem inclui o nome do registro de contêiner e o nome da imagem do contêiner. Sua imagem de contêiner é pré-preenchida da última etapa. Substitua localhost:5000 pelo valor do servidor de logon do registro de contêiner do Azure. Você pode recuperar o servidor de logon na página Visão geral do registro de contêiner no portal do Azure.

    A cadeia de caracteres final se parece com <o nome> do registro.azurecr.io/sqlfunction.

    A janela do Visual Studio Code carrega o workspace da solução do IoT Edge.

Adicionar suas credenciais do Registro

O arquivo de ambiente armazena as credenciais do registro de contêiner e as compartilha com o runtime do IoT Edge. O runtime precisa dessas credenciais para efetuar pull de suas imagens privadas para o dispositivo do IoT Edge.

A extensão do IoT Edge tenta extrair suas credenciais de registro de contêiner do Azure e as preenche no arquivo de ambiente. Verifique se suas credenciais já estão incluídas. Caso contrário, adicione-os agora:

  1. No Gerenciador do Visual Studio Code, abra o arquivo .env.
  2. Atualize os campos com os valores de nome de usuário e senha copiados do registro de contêiner do Azure.
  3. Salve este arquivo.

Observação

Este tutorial usa credenciais de logon de administrador para o Registro de Contêiner do Azure, que são convenientes para cenários de desenvolvimento e teste. Quando você estiver pronto para cenários de produção, recomendamos uma opção de autenticação com privilégios mínimos, como entidades de serviço. Para obter mais informações, consulte Gerenciar o acesso ao registro de contêiner.

Selecione sua arquitetura de destino

Você precisa selecionar qual arquitetura você está direcionando com cada solução, pois o contêiner é criado e executado de forma diferente para cada tipo de arquitetura. O padrão é Linux AMD64.

  1. Abra a paleta de comandos e pesquise o Azure IoT Edge: defina a Plataforma de Destino Padrão para a Solução de Borda ou selecione o ícone de atalho na barra lateral na parte inferior da janela.

  2. Na paleta de comandos, selecione a arquitetura de destino na lista de opções. Para este tutorial, estamos usando uma máquina virtual Ubuntu como o dispositivo IoT Edge, portanto, manteremos o amd64 padrão.

Atualizar o módulo com código personalizado

  1. No Gerenciador do Visual Studio Code, abra os módulos>sqlFunction>sqlFunction.csproj.

  2. Localize o grupo de referências de pacote e adicione um novo para incluir o SqlClient.

    <PackageReference Include="System.Data.SqlClient" Version="4.5.1"/>
    
  3. Salve o arquivo sqlFunction.csproj .

  4. Abra o arquivo sqlFunction.cs .

  5. Substitua todo o conteúdo do arquivo pelo seguinte código:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.Azure.Devices.Client;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.EdgeHub;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Sql = System.Data.SqlClient;
    
    namespace Functions.Samples
    {
        public static class sqlFunction
        {
            [FunctionName("sqlFunction")]
            public static async Task FilterMessageAndSendMessage(
                [EdgeHubTrigger("input1")] Message messageReceived,
                [EdgeHub(OutputName = "output1")] IAsyncCollector<Message> output,
                ILogger logger)
            {
                const int temperatureThreshold = 20;
                byte[] messageBytes = messageReceived.GetBytes();
                var messageString = System.Text.Encoding.UTF8.GetString(messageBytes);
    
                if (!string.IsNullOrEmpty(messageString))
                {
                    logger.LogInformation("Info: Received one non-empty message");
                    // Get the body of the message and deserialize it.
                    var messageBody = JsonConvert.DeserializeObject<MessageBody>(messageString);
    
                    //Store the data in SQL db
                    const string str = "<sql connection string>";
                    using (Sql.SqlConnection conn = new Sql.SqlConnection(str))
                    {
                        conn.Open();
                        var insertMachineTemperature = "INSERT INTO MeasurementsDB.dbo.TemperatureMeasurements VALUES (CONVERT(DATETIME2,'" + messageBody.timeCreated + "', 127), 'machine', " + messageBody.machine.temperature + ");";
                        var insertAmbientTemperature = "INSERT INTO MeasurementsDB.dbo.TemperatureMeasurements VALUES (CONVERT(DATETIME2,'" + messageBody.timeCreated + "', 127), 'ambient', " + messageBody.ambient.temperature + ");";
                        using (Sql.SqlCommand cmd = new Sql.SqlCommand(insertMachineTemperature + "\n" + insertAmbientTemperature, conn))
                        {
                            //Execute the command and log the # rows affected.
                            var rows = await cmd.ExecuteNonQueryAsync();
                            logger.LogInformation($"{rows} rows were updated");
                        }
                    }
    
                    if (messageBody != null && messageBody.machine.temperature > temperatureThreshold)
                    {
                        // Send the message to the output as the temperature value is greater than the threshold.
                        using (var filteredMessage = new Message(messageBytes))
                        {
                             // Copy the properties of the original message into the new Message object.
                             foreach (KeyValuePair<string, string> prop in messageReceived.Properties)
                             {filteredMessage.Properties.Add(prop.Key, prop.Value);}
                             // Add a new property to the message to indicate it is an alert.
                             filteredMessage.Properties.Add("MessageType", "Alert");
                             // Send the message.
                             await output.AddAsync(filteredMessage);
                             logger.LogInformation("Info: Received and transferred a message with temperature above the threshold");
                        }
                    }
                }
            }
        }
        //Define the expected schema for the body of incoming messages.
        class MessageBody
        {
            public Machine machine {get; set;}
            public Ambient ambient {get; set;}
            public string timeCreated {get; set;}
        }
        class Machine
        {
            public double temperature {get; set;}
            public double pressure {get; set;}
        }
        class Ambient
        {
            public double temperature {get; set;}
            public int humidity {get; set;}
        }
    }
    
  6. Na linha 35, substitua a cadeia de conexão> sql da cadeia de caracteres< pela cadeia de caracteres a seguir. A propriedade Fonte de Dados faz referência ao contêiner do SQL Server, que ainda não existe. Você o criará com o nome SQL na próxima seção. Escolha uma senha forte para a palavra-chave Senha .

    Data Source=tcp:sql,1433;Initial Catalog=MeasurementsDB;User Id=SA;Password=<YOUR-STRONG-PASSWORD>;TrustServerCertificate=False;Connection Timeout=30;
    
  7. Salve o arquivo sqlFunction.cs .

Adicionar o contêiner do SQL Server

Um manifesto de implantação declara quais módulos o runtime do IoT Edge instalará em seu dispositivo IoT Edge. Você forneceu o código para criar um módulo de função personalizado na seção anterior, mas o módulo do SQL Server já foi criado e está disponível no Registro de Artefatos da Microsoft. Você só precisa dizer ao runtime do IoT Edge para incluí-lo e configurá-lo em seu dispositivo.

  1. No Visual Studio Code, abra a paleta de comandos selecionando Exibir>paleta de comandos.

  2. Na paleta de comandos, digite e execute o comando Azure IoT Edge: Adicionar módulo do IoT Edge. Na paleta de comandos, forneça as seguintes informações para adicionar um novo módulo:

    Campo Value
    Selecionar arquivo de modelo de implantação A paleta de comandos realça o arquivo deployment.template.json na pasta da solução atual. Selecione esse arquivo.
    Selecionar modelo de módulo Selecione o módulo existente (insira a URL de imagem completa).
    Fornecer um nome de módulo Insira o sql. Esse nome corresponde ao nome do contêiner declarado na cadeia de conexão no arquivo sqlFunction.cs.
    Fornecer imagem do Docker para o módulo Insira o URI a seguir para efetuar pull da imagem de contêiner do SQL Server do Registro de Artefatos da Microsoft. Para imagens baseadas no Ubuntu, use mcr.microsoft.com/mssql/server:latest. Para imagens baseadas em RHEL (Red Hat Enterprise Linux), use mcr.microsoft.com/mssql/rhel/server:latest.

    A imagem de contêiner do SQL do Azure no Edge é uma versão leve e conteinerizada do SQL Server que pode ser executada em dispositivos IoT Edge. Ele é otimizado para cenários de borda e pode ser executado em dispositivos ARM e AMD64.

  3. Na pasta da solução, abra o arquivo deployment.template.json .

  4. Localize a seção de módulos . Você deve ver três módulos. O módulo SimulatedTemperatureSensor é incluído por padrão em novas soluções e fornece dados de teste a serem usados com seus outros módulos. O módulo sqlFunction é o módulo que você inicialmente criou e atualizou com o novo código. Por fim, o sql do módulo foi importado do Registro de Artefatos da Microsoft.

    Dica

    O módulo do SQL Server vem com um conjunto de senhas padrão nas variáveis de ambiente do manifesto de implantação. Sempre que você criar um contêiner do SQL Server em um ambiente de produção, deverá alterar a senha de administrador do sistema padrão.

  5. Feche o arquivo dedeployment.template.json .

Criar sua solução do IoT Edge

Nas seções anteriores, você criou uma solução com um módulo e, em seguida, adicionou outro ao modelo de manifesto de implantação. O módulo do SQL Server é hospedado publicamente pela Microsoft, mas você precisa colocar o código em contêiner no módulo Functions. Nesta seção, você cria a solução, cria imagens de contêiner para o módulo sqlFunction e envia a imagem por push para o registro de contêiner.

  1. No Visual Studio Code, abra o terminal integrado selecionando Exibir>Terminal.

  2. Entre no registro de contêiner no Visual Studio Code para que você possa enviar suas imagens por push para o registro. Use as mesmas credenciais do ACR (Registro de Contêiner do Azure) que você adicionou ao arquivo .env. Insira o seguinte comando no terminal integrado:

    docker login -u <ACR username> -p <ACR password> <ACR login server>
    

    Você pode ver um aviso de segurança recomendando o uso do parâmetro --password-stdin. Embora seu uso esteja fora do escopo deste artigo, recomendamos seguir essa prática recomendada. Para obter mais informações, consulte a referência de comando de logon do Docker .

  3. No Gerenciador do Visual Studio Code, clique com o botão direito do mouse no arquivo deployment.template.json e selecione Compilar e enviar por push a solução IoT Edge.

    O comando build e push inicia três operações. Primeiro, ele cria uma nova pasta na solução chamada configuração que contém o manifesto de implantação completo, que é compilado com base em informações no modelo de implantação e em outros arquivos de solução. Em segundo lugar, ele é executado docker build para criar a imagem de contêiner com base no dockerfile apropriado para sua arquitetura de destino. Em seguida, ele é executado docker push para enviar por push o repositório de imagens para o registro de contêiner.

    Esse processo pode levar vários minutos na primeira vez, mas é mais rápido na próxima vez que você executar os comandos.

    Você pode verificar se o módulo sqlFunction foi enviado por push com êxito para o registro de contêiner. No portal do Azure, navegue até o registro de contêiner. Selecione repositórios e pesquise sqlFunction. Os outros dois módulos, SimulatedTemperatureSensor e sql, não serão enviados por push para o registro de contêiner porque seus repositórios já estão nos registros da Microsoft.

Implantar a solução em um dispositivo

Você pode definir módulos em um dispositivo por meio do Hub IoT, mas também pode acessar seu Hub IoT e dispositivos por meio do Visual Studio Code. Nesta seção, você configurará o acesso ao Hub IoT e, em seguida, usará o Visual Studio Code para implantar sua solução em seu dispositivo IoT Edge.

  1. No Gerenciador do Visual Studio Code, na seção Hub IoT do Azure, expandaDispositivos para ver sua lista de dispositivos IoT.

  2. Clique com o botão direito do mouse no dispositivo que você deseja direcionar com sua implantação e selecione Criar Implantação para Dispositivo Único.

  3. Selecione o arquivo deployment.amd64.json na pasta de configuração e clique em Selecionar Manifesto de Implantação do Edge. Não use o arquivo deployment.template.json.

  4. Em seu dispositivo, expanda Módulos para ver uma lista de módulos implantados e em execução. Clique no botão atualizar. Você deverá ver os novos módulos sql e sqlFunction em execução junto com o módulo SimulatedTemperatureSensor e o $edgeAgent e $edgeHub.

    Você também pode verificar se todos os módulos estão em execução em seu dispositivo. Em seu dispositivo IoT Edge, execute o comando a seguir para ver o status dos módulos.

    iotedge list
    

    Pode levar alguns minutos para que os módulos sejam iniciados. O runtime do IoT Edge precisa receber seu novo manifesto de implantação, efetuar pull das imagens do módulo do runtime do contêiner e, em seguida, iniciar cada novo módulo.

Criar o banco de dados SQL

Ao aplicar o manifesto de implantação ao seu dispositivo, você obtém três módulos em execução. O módulo SimulatedTemperatureSensor gera dados de ambiente simulados. O módulo sqlFunction usa os dados e os formata para um banco de dados. Esta seção orienta você pela configuração do banco de dados SQL para armazenar os dados de temperatura.

Execute os comandos a seguir em seu dispositivo IoT Edge. Esses comandos se conectam ao módulo sql em execução em seu dispositivo e criam um banco de dados e uma tabela para manter os dados de temperatura que estão sendo enviados a ele. Substitua <YOUR-STRONG-PASSWORD> pela senha forte que você escolheu na cadeia de conexão.

  1. Em uma ferramenta de linha de comando em seu dispositivo IoT Edge, conecte-se ao banco de dados.

    sudo docker exec -it sql bash
    
  2. Abra a ferramenta de comando SQL.

    /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P '<YOUR-STRONG-PASSWORD>'
    
  3. Crie seu banco de dados:

    CREATE DATABASE MeasurementsDB
    ON
    (NAME = MeasurementsDB, FILENAME = '/var/opt/mssql/measurementsdb.mdf')
    GO
    
  4. Defina sua tabela.

    CREATE TABLE MeasurementsDB.dbo.TemperatureMeasurements (measurementTime DATETIME2, location NVARCHAR(50), temperature FLOAT)
    GO
    

Você pode personalizar o arquivo docker do SQL Server para configurar automaticamente o SQL Server a ser implantado em vários dispositivos do IoT Edge. Para obter mais informações, consulte o projeto de demonstração de contêiner do Microsoft SQL Server.

Exibir os dados locais

Depois que sua tabela é criada, o módulo sqlFunction começa a armazenar dados em um banco de dados local do SQL Server 2017 em seu dispositivo IoT Edge.

De dentro da ferramenta de comando SQL, execute o seguinte comando para exibir os dados da tabela formatada:

SELECT * FROM MeasurementsDB.dbo.TemperatureMeasurements
GO

Exibir o conteúdo do banco de dados local

Limpar os recursos

Se você planeja continuar para o próximo artigo recomendado, poderá manter os recursos e as configurações que criou e reutilizá-los. Você também pode continuar usando o mesmo dispositivo IoT Edge que um dispositivo de teste.

Caso contrário, você poderá excluir as configurações locais e os recursos do Azure criados neste artigo para evitar encargos.

Excluir recursos do Azure

A exclusão de recursos e grupos de recursos do Azure é irreversível. Não exclua acidentalmente grupo de recursos ou recursos incorretos. Se você criou o hub IoT dentro de um grupo de recursos existente que tem recursos que deseja manter, exclua apenas o recurso do hub IoT em si, não o grupo de recursos.

Para excluir os recursos:

  1. Entre no portal do Azure e selecione Grupos de recursos.

  2. Selecione o nome do grupo de recursos que contém os recursos de teste do IoT Edge.

  3. Examine a lista de recursos contidos em seu grupo de recursos. Se quiser excluir todos eles, selecione Excluir grupo de recursos. Se você quiser excluir apenas alguns deles, clique em cada recurso para excluí-los individualmente.

Neste tutorial, você criou um módulo do Azure Functions que contém código para filtrar dados brutos gerados pelo dispositivo IoT Edge. Quando estiver pronto para criar seus próprios módulos, você poderá saber mais sobre como desenvolver módulos do Azure IoT Edge usando o Visual Studio Code.

Próximas etapas

Se você quiser experimentar outro método de armazenamento na borda, leia sobre como usar o Armazenamento de Blobs do Azure no IoT Edge.