Condividi tramite


Esercitazione: Creare una cache write-behind usando Funzioni di Azure e Azure Redis

Questa esercitazione descrive come usare un'istanza di Redis gestita di Azure (anteprima) o cache di Azure per Redis come cache write-behind. Il modello write-behind in questa esercitazione illustra come scritture nella cache attivano scritture corrispondenti a un database SQL (un'istanza del servizio di database SQL di Azure).

Usare il trigger Redis per Funzioni di Azure per implementare questa funzionalità. In questo scenario viene illustrato come usare Redis per archiviare le informazioni sull'inventario e sui prezzi durante il backup di tali informazioni in un database SQL.

Ogni nuovo elemento o nuovo prezzo scritto nella cache viene quindi traslato in una tabella SQL nel database.

In questa esercitazione apprenderai a:

  • Configurare un database, un trigger e le stringhe di connessione.
  • Verificare che i trigger funzionino.
  • Distribuire il codice in un'app per le funzioni.

Prerequisiti

  • Una sottoscrizione di Azure. Se non hai una sottoscrizione di Azure, crea un account gratuito.
  • Completamento dell'esercitazione precedente, Introduzione ai trigger di Funzioni di Azure in Azure Redis, con queste risorse di cui è stato effettuato il provisioning:
    • Istanza di Redis gestita di Azure (anteprima) o cache di Azure per Redis
    • Istanza di Funzioni di Azure
    • Conoscenza pratica dell'uso di Azure SQL
    • Ambiente Visual Studio Code (VS Code) configurato con pacchetti NuGet installati

Creare e configurare un nuovo database SQL

Per questo esempio, il database SQL è il database backing. È possibile creare un database SQL tramite il portale di Azure o tramite un metodo di automazione di scelta.

Per altre informazioni sulla creazione di un database SQL, vedere Avvio rapido: Creare un database singolo - Database SQL di Azure.

In questo esempio viene usato il portale:

  1. Immettere un nome di database e selezionare Crea nuovo per creare un nuovo server per contenere il database.

    Screenshot della creazione di una risorsa SQL di Azure.

  2. Selezionare Usa autenticazione SQL e immettere un accesso amministratore e una password. Assicurarsi di ricordare queste credenziali o annotarle. Quando si distribuisce un server nell'ambiente di produzione, usare invece l'autenticazione con Microsoft Entra.

    Screenshot delle informazioni di autenticazione per una risorsa SQL di Azure.

  3. Passare alla scheda Rete e scegliere Endpoint pubblico come metodo di connessione. Selezionare per entrambe le regole del firewall visualizzate. Questo endpoint consente l'accesso dall'app per le funzioni di Azure.

    Screenshot dell'impostazione di rete per una risorsa SQL di Azure.

  4. Al termine della convalida, selezionare Rivedi e crea e quindi Crea. La distribuzione del database SQL verrà avviata.

  5. Al termine della distribuzione, passare alla risorsa nel portale di Azure e selezionare la scheda Editor di query. Creare una nuova tabella denominata inventory che contiene i dati che verranno scritti. Usare il comando SQL seguente per creare una nuova tabella con due campi:

    • ItemName elenca il nome di ogni elemento.
    • Price archivia il prezzo dell'articolo.
    CREATE TABLE inventory (
        ItemName varchar(255),
        Price decimal(18,2)
        );
    

    Screenshot che mostra la creazione di una tabella nell'editor di query di una risorsa SQL di Azure.

  6. Al termine dell'esecuzione del comando, espandere la cartella Tabelle e verificare che la nuova tabella sia stata creata.

Configurare il trigger Redis

Prima di tutto, creare una copia dello stesso progetto di VS Code usato nell'esercitazione precedente. Copiare la cartella dall'esercitazione precedente con un nuovo nome, ad esempio RedisWriteBehindTrigger, e aprirla in VS Code.

Quindi, eliminare i file RedisBindings.cs e RedisTriggers.cs .

In questo esempio si usa il trigger pub/sub per attivare le notifiche keyevent. Gli obiettivi dell'esempio consistono in:

  • Attivarsi ogni volta che si verifica un evento SET. Un evento SET si verifica quando vengono scritte nuove chiavi nell'istanza della cache o quando il valore di una chiave viene modificato.
  • Dopo l'attivazione di un evento SET, accedere all'istanza della cache per trovare il valore della nuova chiave.
  • Determinare se la chiave sia già esistente nella tabella di inventario nel database SQL.
    • Se esistente, aggiornare il valore della chiave.
    • In caso contrario, scrivere una nuova riga con la chiave e il relativo valore.

Per configurare il trigger:

  1. Importare il pacchetto NuGet System.Data.SqlClient per abilitare la comunicazione con il database SQL. Passare al terminale di VS Code e usare il comando seguente:

      dotnet add package System.Data.SqlClient
    
  2. Creare un nuovo file denominato RedisFunction.cs. Assicurarsi di aver eliminato i file RedisBindings.cs e RedisTriggers.cs.

  3. Copiare e incollare il codice seguente in RedisFunction.cs per sostituire il codice esistente:

using Microsoft.Extensions.Logging;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Redis;
using System.Data.SqlClient;

public class WriteBehindDemo
{
    private readonly ILogger<WriteBehindDemo> logger;

    public WriteBehindDemo(ILogger<WriteBehindDemo> logger)
    {
        this.logger = logger;
    }
    
    public string SQLAddress = System.Environment.GetEnvironmentVariable("SQLConnectionString");

    //This example uses the PubSub trigger to listen to key events on the 'set' operation. A Redis Input binding is used to get the value of the key being set.
    [Function("WriteBehind")]
    public void WriteBehind(
        [RedisPubSubTrigger(Common.connectionString, "__keyevent@0__:set")] Common.ChannelMessage channelMessage,
        [RedisInput(Common.connectionString, "GET {Message}")] string setValue)
    {
        var key = channelMessage.Message; //The name of the key that was set
        var value = 0.0;

        //Check if the value is a number. If not, log an error and return.
        if (double.TryParse(setValue, out double result))
        {
            value = result; //The value that was set. (i.e. the price.)
            logger.LogInformation($"Key '{channelMessage.Message}' was set to value '{value}'");
        }
        else
        {
            logger.LogInformation($"Invalid input for key '{key}'. A number is expected.");
            return;
        }        

        // Define the name of the table you created and the column names.
        String tableName = "dbo.inventory";
        String column1Value = "ItemName";
        String column2Value = "Price";        
        
        logger.LogInformation($" '{SQLAddress}'");
        using (SqlConnection connection = new SqlConnection(SQLAddress))
            {
                connection.Open();
                using (SqlCommand command = new SqlCommand())
                {
                    command.Connection = connection;

                    //Form the SQL query to update the database. In practice, you would want to use a parameterized query to prevent SQL injection attacks.
                    //An example query would be something like "UPDATE dbo.inventory SET Price = 1.75 WHERE ItemName = 'Apple'".
                    command.CommandText = "UPDATE " + tableName + " SET " + column2Value + " = " + value + " WHERE " + column1Value + " = '" + key + "'";
                    int rowsAffected = command.ExecuteNonQuery(); //The query execution returns the number of rows affected by the query. If the key doesn't exist, it will return 0.

                    if (rowsAffected == 0) //If key doesn't exist, add it to the database
                 {
                         //Form the SQL query to update the database. In practice, you would want to use a parameterized query to prevent SQL injection attacks.
                         //An example query would be something like "INSERT INTO dbo.inventory (ItemName, Price) VALUES ('Bread', '2.55')".
                        command.CommandText = "INSERT INTO " + tableName + " (" + column1Value + ", " + column2Value + ") VALUES ('" + key + "', '" + value + "')";
                        command.ExecuteNonQuery();

                        logger.LogInformation($"Item " + key + " has been added to the database with price " + value + "");
                    }

                    else {
                        logger.LogInformation($"Item " + key + " has been updated to price " + value + "");
                    }
                }
                connection.Close();
            }

            //Log the time that the function was executed.
            logger.LogInformation($"C# Redis trigger function executed at: {DateTime.Now}");
    }
}

Importante

Questo esempio è stato semplificato per i fini dell’esercitazione. Per l'uso in produzione, è consigliabile usare query SQL con parametri per evitare attacchi di inserimento SQL.

Configurazione delle stringhe di connessione

È necessario aggiornare il file local.settings.json in modo da includere la stringa di connessione per il database SQL. Aggiungere una voce nella sezione Values per SQLConnectionString. Il file avrà un aspetto simile all'esempio seguente:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "redisConnectionString": "<redis-connection-string>",
    "SQLConnectionString": "<sql-connection-string>"
  }
}

Per trovare il stringa di connessione Redis, passare al menu delle risorse nella risorsa Redis gestita di Azure o cache di Azure per Redis risorsa. Individuare la stringa nell'area Chiavi di accesso del menu Risorsa.

Per trovare la stringa di connessione del database SQL, passare al menu risorse nella risorsa del database SQL. In Impostazioni, selezionare Stringhe di connessione e quindi selezionare la scheda ADO.NET. La stringa si trova nell'area ADO.NET (autenticazione SQL).

È necessario immettere manualmente la password per la stringa di connessione del database SQL, poiché non verrà incollata automaticamente.

Importante

Questo esempio è stato semplificato per i fini dell’esercitazione. Per l'uso in produzione, è consigliabile usare Azure Key Vault per archiviare stringa di connessione informazioni o usare l'ID Entra di Azure per l'autenticazione SQL.

Compilare ed eseguire il progetto

  1. In VS Code, passare alla scheda Esecuzione e debug ed eseguire il progetto.

  2. Tornare all'istanza di Redis nel portale di Azure e selezionare il pulsante Console per immettere la console Redis. Provare a usare alcuni comandi SET:

    • SET apple 5.25
    • SET bread 2.25
    • SET apple 4.50

Importante

Lo strumento console non è ancora disponibile per Redis gestito di Azure. Prendere invece in considerazione l'uso dell'interfaccia della riga di comando redis o di uno strumento come Redis Insight per eseguire comandi direttamente nell'istanza di Redis.

  1. Tornando a VS Code, i trigger vengono registrati. Per verificare che i trigger funzionino:

    1. Passare al database SQL nel portale di Azure.

    2. Nel menu della risorsa, selezionare Editor di query.

    3. Per Nuova query, creare una query con il comando SQL seguente per visualizzare i primi 100 elementi nella tabella di inventario:

      SELECT TOP (100) * FROM [dbo].[inventory]
      

      Verificare che gli elementi scritti nell'istanza di Redis siano visualizzati qui.

    Screenshot che mostra che le informazioni sono state copiate in SQL dall'istanza della cache.

Distribuire il codice nell'app per le funzioni

Questa esercitazione amplia i concetti di quella precedente. Per altre informazioni, vedere Distribuire codice in una funzione di Azure.

  1. In VS Code, passare alla scheda Azure.

  2. Trovare la sottoscrizione ed espanderla. Individuare quindi la sezione App per le funzioni ed espanderla.

  3. Selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) sull'app per le funzioni e quindi scegliere Distribuisci nell'app per le funzioni.

Aggiungere le informazioni della stringa di connessione

Questa esercitazione amplia i concetti di quella precedente. Per altre informazioni su redisConnectionString, vedere Aggiungere informazioni sulla stringa di connessione.

  1. Passare all'app per le funzioni nel portale di Azure. Nel menu risorsa, selezionare Variabili di ambiente.

  2. Nel riquadro Impostazioni app, immettere SQLConnectionString come nuovo campo. Per Valore, immettere la stringa di connessione.

  3. Selezionare Applica.

  4. Passare al pannello Panoramica e selezionare Riavvia per riavviare l'app con le nuove informazioni sulla stringa di connessione.

Verificare la distribuzione

Al termine della distribuzione, tornare all'istanza di Redis e usare SET i comandi per scrivere altri valori. Verificare che questi vengano visualizzati anche nel database SQL.

Se si vuole confermare che l'app per le funzioni funziona correttamente, passare all'app nel portale e selezionare Flusso di log dal menu delle risorse. Verranno visualizzati i trigger in esecuzione e gli aggiornamenti corrispondenti eseguiti nel database SQL.

Se si vuole cancellare la tabella di database SQL senza eliminarla, è possibile usare la query SQL seguente:

TRUNCATE TABLE [dbo].[inventory]

Pulire le risorse

Per continuare a usare le risorse create in questo articolo, mantenere il gruppo di risorse.

In caso contrario, se le risorse sono state completate, per evitare addebiti è possibile eliminare il gruppo di risorse di Azure creato.

Importante

L'eliminazione di un gruppo di risorse è irreversibile. Quando si elimina un gruppo di risorse, tutte le risorse in esso contenute vengono eliminate in modo permanente. Assicurarsi di non eliminare accidentalmente il gruppo di risorse sbagliato o le risorse errate. Se le risorse sono state create all'interno di un gruppo di risorse esistente che contiene anche elementi da mantenere, è possibile eliminare ogni singolo elemento a sinistra anziché eliminare il gruppo di risorse.

Per eliminare un gruppo di risorse

  1. Accedere al portale di Azure e selezionare Gruppi di risorse.

  2. Scegliere il gruppo di risorse da eliminare.

    Se sono presenti molti gruppi di risorse, usare la casella Filtro per qualsiasi campo... e digitare il nome del gruppo di risorse creato per questo articolo. Nell’elenco dei risultati selezionare il gruppo di risorse.

    Screenshot che mostra nel riquadro di lavoro un elenco dei gruppi di risorse da eliminare.

  3. Selezionare Elimina gruppo di risorse.

  4. Verrà chiesto di confermare l'eliminazione del gruppo di risorse. Digitare il nome del gruppo di risorse per confermare e quindi selezionare Elimina.

    Screenshot che mostra un modulo richiedente il nome della risorsa per confermare l'eliminazione.

Dopo qualche istante, il gruppo di risorse e tutte le risorse che contiene vengono eliminati.

Riepilogo

Questa esercitazione e Introduzione ai trigger di Funzioni di Azure in Azure Redis illustrano come usare trigger e associazioni Redis nelle app per le funzioni di Azure. Illustrano anche come usare Redis come cache write-behind con database SQL di Azure. L'uso di Redis gestito di Azure o cache di Azure per Redis con Funzioni di Azure è una combinazione potente che può risolvere molti problemi di integrazione e prestazioni.