Esercitazione: Archiviare dati nei dispositivi perimetrali con database di SQL Server
Si applica a: IoT Edge 1.5 IoT Edge 1.4
Importante
IoT Edge 1.5 LTS e IoT Edge 1.4 LTS sono versioni supportate. IoT Edge 1.4 LTS raggiungerà il fine vita il 12 novembre 2024. Se si usa una versione precedente, vedere Aggiornare IoT Edge.
Distribuire un modulo di SQL Server per archiviare dati in un dispositivo che esegue Azure IoT Edge con contenitori Linux.
Usare Azure IoT Edge e SQL Server per archiviare i dati ed eseguirne query nei dispositivi perimetrali. Azure IoT Edge offre funzionalità di archiviazione di base che memorizzano nella cache i messaggi se un dispositivo passa alla modalità offline e quindi li inoltrano quando viene ristabilita la connessione. È tuttavia possibile che siano necessarie funzionalità di archiviazione più avanzate, ad esempio la possibilità di eseguire query sui dati in locale. I dispositivi IoT Edge possono usare database locale per eseguire elaborazioni più complesse senza la necessità di mantenere una connessione all'hub IoT.
Questo articolo contiene istruzioni per la distribuzione di un database di SQL Server a un dispositivo IoT Edge. Funzioni di Azure, in esecuzione sul dispositivo IoT Edge, struttura i dati in ingresso e quindi li invia al database. I passaggi descritti in questo articolo sono applicabili anche ad altri database che operano in contenitori, ad esempio MySQL o PostgreSQL.
In questa esercitazione apprenderai a:
- Usare Visual Studio Code per creare una funzione di Azure
- Distribuire un database SQL nel dispositivo IoT Edge
- Usare Visual Studio Code per compilare i moduli e distribuirli nel dispositivo IoT Edge
- Visualizzare i dati generati
Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.
Prerequisiti
Prima di iniziare questa esercitazione, è necessario eseguire l'esercitazione precedente per configurare l'ambiente di sviluppo per lo sviluppo di contenitori Linux: Sviluppare moduli Azure IoT Edge usando Visual Studio Code. Completando tale esercitazione, saranno soddisfatti i prerequisiti seguenti:
- Un hub IoT di livello Gratuito o Standard in Azure.
- Un dispositivo AMD64 che esegue Azure IoT Edge con contenitori Linux. È possibile usare le guide introduttive per configurare un dispositivo Linux o un dispositivo Windows.
- I dispositivi ARM, ad esempio Raspberry Pis, non possono eseguire SQL Server. Se si vuole usare SQL in un dispositivo ARM, è possibile usare SQL Edge di Azure.
- Un registro contenitori, ad esempio Registro Azure Container.
- Visual Studio Code configurato con le estensioni Azure IoT Edge e hub IoT di Azure. L'estensione Azure IoT Edge Tools per Visual Studio Code è in modalità manutenzione.
- Scaricare e installare un sistema di gestione contenitori compatibile con Docker nel computer di sviluppo. Configurarlo per l'esecuzione di contenitori Linux.
In questa esercitazione si usa un modulo di Funzioni di Azure per inviare dati a SQL Server. Per sviluppare un modulo IoT Edge con Funzioni di Azure, installare i prerequisiti aggiuntivi seguenti nel computer di sviluppo:
Creare un progetto per le funzioni
Per inviare dati in un database, è necessario un modulo con cui strutturare i dati in modo corretto e quindi archiviarli in una tabella.
Crea un nuovo progetto
La procedura seguente illustra come creare una funzione di IoT Edge tramite Visual Studio Code e l'estensione Azure IoT Edge.
Aprire Visual Studio Code.
In Visual Studio Code aprire il riquadro comandi selezionando Visualizza>Riquadro comandi.
Nel riquadro comandi digitare ed eseguire il comando Azure IoT Edge: New IoT Edge solution (Azure IoT Edge: Nuova soluzione IoT Edge). Nel riquadro comandi immettere le informazioni seguenti per creare la soluzione:
Campo valore Seleziona cartella Nel computer di sviluppo scegliere la posizione in cui Visual Studio Code dovrà creare i file della soluzione. Provide a solution name (Specificare un nome per la soluzione) Immettere un nome descrittivo per la soluzione, ad esempio SqlSolution, oppure accettare l'impostazione predefinita. Select module template (Selezionare un modello di modulo) Scegliere Azure Functions - C# (Funzioni di Azure - C#). Provide a module name (Specificare un nome per il modulo) Assegnare al modulo il nome sqlFunction. Provide Docker image repository for the module (Specificare il repository di immagini Docker per il modulo) Un repository di immagini include il nome del registro contenitori e il nome dell'immagine del contenitore. L'immagine del contenitore è prepopolata dall'ultimo passaggio. Sostituire localhost:5000 con il valore di Server di accesso del registro contenitori di Azure. È possibile recuperare il server di accesso dalla pagina Panoramica del registro contenitori nel portale di Azure.
La stringa finale è simile a <nome registro>.azurecr.io/sqlfunction.La finestra di Visual Studio Code carica l'area di lavoro della soluzione IoT Edge.
Aggiungere le credenziali del registro
Il file dell'ambiente archivia le credenziali per il registro contenitori e le condivide con il runtime IoT Edge. Queste credenziali sono necessarie al runtime per eseguire il pull delle immagini private nel dispositivo IoT Edge.
L'estensione IoT Edge cerca di eseguire il pull delle credenziali del Registro Container da Azure, per inserirle nel file di ambiente. Verificare se le credenziali sono già incluse. In caso contrario, aggiungerle:
- Nello strumento di esplorazione di Visual Studio Code aprire il file con estensione env.
- Aggiornare i campi con i valori di nome utente e password copiati dal Registro Azure Container.
- Fare clic su Salva per salvare il file.
Nota
Questa esercitazione usa le credenziali di accesso amministratore per Registro Azure Container, utili per scenari di sviluppo e test. Quando si è pronti per gli scenari di produzione, è consigliabile usare un'opzione di autenticazione con privilegi minimi, ad esempio le entità servizio. Per altre informazioni, vedere Gestire l'accesso al registro contenitori.
Selezionare l'architettura di destinazione
È necessario selezionare l'architettura di destinazione per ogni soluzione, perché il contenitore viene creato ed eseguito in modo diverso in base al tipo di architettura. L'impostazione predefinita è Linux AMD64.
Aprire il riquadro comandi e cercare Azure IoT Edge: Impostare la piattaforma di destinazione predefinita per la soluzione Edgeoppure selezionare l'icona di scelta rapida nella barra laterale nella parte inferiore della finestra.
Nel riquadro comandi selezionare l'architettura di destinazione nell'elenco di opzioni. Per questa esercitazione si usa una macchina virtuale Ubuntu come dispositivo IoT Edge, quindi si manterrà il valore predefinito amd64.
Aggiornare il modulo con il codice personalizzato
Nello strumento di esplorazione di Visual Studio Code aprire i moduli>sqlFunction>sqlFunction.csproj.
Trovare il gruppo di riferimenti ai pacchetti e aggiungerne uno nuovo per includere SqlClient.
<PackageReference Include="System.Data.SqlClient" Version="4.5.1"/>
Salvare il file sqlFunction.csproj.
Aprire il file sqlFunction.cs.
Sostituire l'intero contenuto del file con il codice seguente:
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 threashold. 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;} } }
Nella riga 35 sostituire la stringa <sql connection string> con la stringa seguente. La proprietà Data Source fa riferimento al contenitore SQL Server che non esiste ancora. Verrà creato con il nome SQL nella sezione successiva. Scegliere una password complessa per la parola chiave Password.
Data Source=tcp:sql,1433;Initial Catalog=MeasurementsDB;User Id=SA;Password=<YOUR-STRONG-PASSWORD>;TrustServerCertificate=False;Connection Timeout=30;
Salvare il file sqlFunction.cs.
Aggiungere il contenitore di SQL Server
Un manifesto della distribuzione dichiara i moduli che il runtime IoT Edge installerà nel dispositivo IoT Edge. Nella sezione precedente è stato specificato il codice per creare un modulo di funzione personalizzato, ma il modulo di SQL Server è già compilato e disponibile nel Registro artefatti Microsoft. È sufficiente indicare al runtime IoT Edge di includerlo, quindi configurarlo nel dispositivo.
In Visual Studio Code aprire il riquadro comandi selezionando Visualizza>Riquadro comandi.
Nel riquadro comandi digitare ed eseguire il comando Azure IoT Edge: Aggiungere il modulo IoT Edge. Nel riquadro comandi immettere le informazioni seguenti per aggiungere un nuovo modulo:
Campo valore Select deployment template file (Selezionare il file del modello di distribuzione) Il riquadro comandi evidenzia il file deployment.template.json nella cartella della soluzione corrente. Selezionare questo file. Select module template (Selezionare un modello di modulo) Selezionare Existing Module (Enter full image URL) (Modulo esistente - Immettere l'URL completo dell'immagine). Specificare un nome per il modulo Immettere sql. Questo nome corrisponde al nome del contenitore dichiarato nella stringa di connessione nel file sqlFunction.cs. Specificare l'immagine Docker per il modulo Immettere l'URI seguente per eseguire il pull dell'immagine del contenitore di SQL Server dal Registro artefatti Microsoft. Per le immagini basate su Ubuntu, usare mcr.microsoft.com/mssql/server:latest
. Per le immagini basate su Red Hat Enterprise Linux (RHEL), usaremcr.microsoft.com/mssql/rhel/server:latest
.L'immagine del contenitore SQL Edge di Azure è una versione leggera e in contenitori di SQL Server che può essere eseguita nei dispositivi IoT Edge. È ottimizzato per gli scenari perimetrali e può essere eseguito su dispositivi ARM e AMD64.
Nella cartella della soluzione aprire il file deployment.template.json.
Individuare la sezione modules. Dovrebbero essere visualizzati tre moduli. Il modulo SimulatedTemperatureSensor è incluso per impostazione predefinita nelle nuove soluzioni e fornisce i dati di test da usare con gli altri moduli. Il modulo sqlFunction è quello che è stato creato inizialmente e aggiornato con il nuovo codice. Infine, il modulo sql è stato importato dal Registro artefatti Microsoft.
Suggerimento
Il modulo di SQL Server include una password predefinita impostata nelle variabili di ambiente del manifesto della distribuzione. Ogni volta che si crea un contenitore SQL Server in un ambiente di produzione, è necessario modificare la password dell'amministratore di sistema predefinita.
Chiudere il file deployment.template.json.
Compilare la soluzione IoT Edge
Nelle sezioni precedenti è stata creata una soluzione con un modulo e quindi ne è stata aggiunta un'altra al modello di manifesto della distribuzione. Il modulo di SQL Server viene ospitato pubblicamente da Microsoft, ma è necessario aggiungere il codice a un contenitore nel modulo Functions. In questa sezione viene compilata la soluzione, vengono create le immagini del contenitore per il modulo sqlFunction e ne viene eseguito il push nel registro contenitori.
In Visual Studio Code aprire il terminale integrato selezionando Visualizza>Terminale.
Accedere al registro contenitori in Visual Studio Code per poter eseguire il push delle immagini nel registro. Usare le stesse credenziali di Registro Azure Container aggiunte al file con estensione env. Immettere il comando seguente nel terminale integrato:
docker login -u <ACR username> -p <ACR password> <ACR login server>
È possibile che venga visualizzato un avviso di sicurezza in cui si consiglia l'uso del parametro --password-stdin. Sebbene il suo utilizzo non rientri nell'ambito di questo articolo, si raccomanda di seguire questa procedura consigliata. Per altre informazioni, vedere la guida comandi di accesso di Docker.
Nello strumento di esplorazione di Visual Studio Code fare clic con il pulsante destro del mouse sul file deployment.template.json e scegliere Compila ed esegui il push della soluzione IoT Edge.
Il comando di creazione e push avvia tre operazioni. Prima di tutto, crea una nuova cartella nella soluzione denominata config che contiene il manifesto completo della distribuzione, basato sulle informazioni del modello di distribuzione e di altri file della soluzione. In secondo luogo, esegue
docker build
per creare l'immagine del contenitore in base al documento dockerfile appropriato per l'architettura di destinazione. Infine, eseguedocker push
per eseguire il push del repository di immagini nel registro contenitori.Questo processo può richiedere alcuni minuti quando viene eseguito per la prima volta, ma alla successiva esecuzione dei comandi avviene più rapidamente.
È possibile verificare se il push del modulo sqlFunction nel registro contenitori è stato eseguito correttamente. Nel portale di Azure passare al registro contenitori. Selezionare repository e cercare sqlFunction. Il push degli altri due moduli, SimulatedTemperatureSensor e sql, nel registro contenitori non verrà eseguito perché i relativi repository sono già presenti nei registri Microsoft.
Distribuire la soluzione in un dispositivo
È possibile impostare i moduli in un dispositivo tramite l'hub IoT, ma è anche possibile accedere all'hub IoT e ai dispositivi tramite Visual Studio Code. In questa sezione si configura l'accesso all'hub IoT e quindi si usa Visual Studio Code per distribuire la soluzione nel dispositivo IoT Edge.
Nello strumento di esplorazione di Visual Studio Code espandere Dispositivi nella sezione Azure IoT Hub (Hub IoT di Azure) per visualizzare l'elenco dei dispositivi IoT.
Fare clic con il pulsante destro del mouse sul dispositivo che si vuole specificare come destinazione della distribuzione e scegliere Create Deployment for Single Device (Crea la distribuzione per un unico dispositivo).
Selezionare il file deployment.amd64.json nella cartella config e quindi fare clic su Select Edge Deployment Manifest (Seleziona il manifesto della distribuzione di Edge). Non usare il file deployment.template.json.
Nel dispositivo espandere Moduli per visualizzare un elenco dei moduli distribuiti e in esecuzione. Fare clic sul pulsante Aggiorna. Verranno visualizzati i nuovi moduli sql e sqlFunction in esecuzione insieme al modulo SimulatedTemperatureSensor e a $edgeAgent e $edgeHub.
È anche possibile verificare che tutti i moduli siano operativi nel dispositivo. Nel dispositivo IoT Edge eseguire questo comando per visualizzare lo stato dei moduli.
iotedge list
L'avvio dei moduli potrebbe richiedere alcuni minuti. Il runtime IoT Edge deve ricevere il nuovo manifesto della distribuzione, eseguire il pull delle immagini dei moduli dal runtime del contenitore e quindi avviare ogni nuovo modulo.
Creare il database SQL
Quando si applica il manifesto della distribuzione al dispositivo, si ottengono tre moduli in esecuzione. Il modulo SimulatedTemperatureSensor genera i dati dell'ambiente simulato. Il modulo sqlFunction acquisisce i dati e li formatta per un database. Questa sezione descrive come configurare il database SQL per l'archiviazione dei dati di temperatura.
Eseguire i comandi seguenti nel dispositivo IoT Edge. Questi comandi stabiliscono una connessione al modulo sql in esecuzione nel dispositivo e creano un database e una tabella per i dati di temperatura inviati al modulo. Sostituire <YOUR-STRONG-PASSWORD> con la password complessa scelta nella stringa di connessione.
In uno strumento da riga di comando nel dispositivo IoT Edge connettersi al database.
sudo docker exec -it sql bash
Aprire lo strumento di comando SQL.
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P '<YOUR-STRONG-PASSWORD>'
Creare il database:
CREATE DATABASE MeasurementsDB ON (NAME = MeasurementsDB, FILENAME = '/var/opt/mssql/measurementsdb.mdf') GO
Definire la tabella.
CREATE TABLE MeasurementsDB.dbo.TemperatureMeasurements (measurementTime DATETIME2, location NVARCHAR(50), temperature FLOAT) GO
È possibile personalizzare il file Docker di SQL Server in modo da impostare automaticamente la distribuzione di SQL Server in più dispositivi IoT Edge. Per altre informazioni, vedere il progetto demo di contenitore Microsoft SQL Server.
Visualizzare i dati locali
Dopo che la tabella è stata creata, il modulo sqlFunction avvia l'archiviazione dei dati in un database di SQL Server 2017 locale nel dispositivo IoT Edge.
Dallo strumento di comando SQL eseguire il comando seguente per visualizzare i dati della tabella formattati:
SELECT * FROM MeasurementsDB.dbo.TemperatureMeasurements
GO
Pulire le risorse
Se si intende continuare con il prossimo articolo consigliato, è possibile conservare le risorse e le configurazioni create e riutilizzarle. È anche possibile continuare a usare lo stesso dispositivo IoT Edge come dispositivo di test.
In caso contrario, è possibile eliminare le risorse di Azure e le configurazioni locali create in questo articolo per evitare addebiti.
Eliminare le risorse di Azure
L'eliminazione delle risorse e dei gruppi di risorse di Azure è irreversibile. Assicurarsi di non eliminare accidentalmente il gruppo di risorse sbagliato o le risorse errate. Se l'hub IoT è stato creato all'interno di un gruppo di risorse esistente che contiene risorse che si vogliono conservare, eliminare solo la risorsa hub IoT stessa, invece dell'intero gruppo.
Per eliminare le risorse:
Accedere al portale di Azure e selezionare Gruppi di risorse.
Selezionare il nome del gruppo di risorse contenente le risorse di test di IoT Edge.
Esaminare l'elenco delle risorse contenute nel gruppo di risorse. Per eliminarle tutte, è possibile selezionare Elimina gruppo di risorse. Se se ne vogliono eliminare solo alcune, è possibile selezionare ogni risorsa per eliminarle singolarmente.
In questa esercitazione è stato creato un modulo di Funzioni di Azure contenente il codice per filtrare i dati non elaborati generati dal dispositivo IoT Edge. Quando si è pronti per compilare moduli personalizzati, sono disponibili altre informazioni su come Sviluppare modulo Azure IoT Edge con Visual Studio Code.
Passaggi successivi
Se si vuole provare un altro metodo di archiviazione nei dispositivi perimetrali, leggere l'articolo su come usare Archiviazione BLOB di Azure in IoT Edge.