Övning – Ansluta en app till cachen

Slutförd

Nu när vår Redis-cache har skapats i Azure ska vi skapa ett program för att använda den. Kontrollera att du har information om din anslutningssträng från Azure Portal.

Kommentar

Integrerad Cloud Shell är tillgängligt till höger. Du kan använda kommandotolken för att skapa och köra exempelkoden som vi skapar här, eller utföra de här stegen lokalt om du har konfigurerat en .NET Core-utvecklingsmiljö.

Skapa ett konsolprogram

Vi använder ett konsolprogram så att vi kan fokusera på Redis-implementeringen.

  1. I Cloud Shell skapar du ett nytt .NET Core-konsolprogram och ger det SportsStatsTrackernamnet .

    dotnet new console --name SportsStatsTracker
    
  2. Ändra aktuell katalog till mappen för det nya projektet.

    cd SportsStatsTracker
    

Lägga till anslutningssträngen

Vi lägger till den anslutningssträng som vi fick från Azure Portal i koden. Lagra aldrig autentiseringsuppgifterna så här i källkoden. För att det här exemplet ska vara enkelt ska vi använda en konfigurationsfil. En bättre metod för ett program på serversidan i Azure är att använda Azure Key Vault med certifikat.

  1. Skapa en ny appsettings.json-fil som ska läggas till i projektet.

    touch appsettings.json
    
  2. Öppna kodredigeraren genom att skriva code . i projektmappen. Om du arbetar lokalt rekommenderar vi att du använder Visual Studio Code. De här stegen anpassas huvudsakligen med dess användning.

  3. Välj filen appsettings.json i redigeringsprogrammet och lägg till följande text. Klistra in anslutningssträngen i värdet för inställningen.

    {
      "CacheConnection": "[value-goes-here]"
    }
    
  4. Spara ändringarna.

    Viktigt!

    När du klistrar in eller ändrar kod i en fil i redigeraren ska du spara efteråt med hjälp av menyn ... eller acceleratornyckeln (Ctrl+S i Windows och Linux, Cmd+S på macOS).

  5. Välj filen SportsStatsTracker.csproj i redigeringsprogrammet för att öppna den.

  6. Lägg till följande <ItemGroup> konfigurationsblock i rotelementet <Project> under elementet <PropertyGroup> . Den här konfigurationen innehåller den nya filen i projektet och kopierar den till utdatamappen. Anvisningarna i det här blocket säkerställer att appkonfigurationsfilen placeras i utdatakatalogen när appen kompileras/skapas.

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
          ...
      </PropertyGroup>
    
      <ItemGroup>
         <None Update="appsettings.json">
           <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
         </None>
      </ItemGroup>
    
    </Project>
    
  7. Spara filen.

    Viktigt!

    Om du inte sparar filen förlorar du ändringen när du lägger till paketet senare.

Lägga till stöd för läsning från en JSON-konfigurationsfil

Ett .NET Core-program kräver att andra NuGet-paket läser en JSON-konfigurationsfil.

I kommandotolken i fönstret lägger du till en referens till NuGet-paketet Microsoft.Extensions.Configuration.Json :

dotnet add package Microsoft.Extensions.Configuration.Json

Lägga till kod för att läsa konfigurationsfilen

Nu när vi har lagt till de bibliotek som krävs för att aktivera läskonfigurationen måste vi aktivera den funktionen i konsolprogrammet.

  1. Välj Program.cs i redigeraren. Ersätt innehållet i filen med följande kod:

    using Microsoft.Extensions.Configuration;
    
    namespace SportsStatsTracker
    {
        class Program
        {
            static void Main(string[] args)
            {
                var config = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json")
                    .Build();
            }
        }
    }
    

    Med using instruktionen kan vi komma åt biblioteken för att läsa konfigurationen, och koden i Main metoden initierar konfigurationssystemet att läsa från appsettings.json-filen.

Hämta anslutningssträngen från konfigurationen

I Program.cs, i slutet av Main-metoden, använder du den nya variabeln config till att hämta anslutningssträngen och lagra den i en ny variabel med namnet connectionString.

Variabeln config innehåller en indexerare där du kan skicka en sträng som hämtas från din appSettings.json-fil.

string connectionString = config["CacheConnection"];

Lägga till stöd för Redis-cachens .NET-klient

Nu ska vi konfigurera konsolprogrammet till att använda StackExchange.Redis-klienten för .NET.

  1. Lägg till NuGet-paketet StackExchange.Redis i projektet med kommandotolken längst ned i Cloud Shell-redigeraren.

    dotnet add package StackExchange.Redis
    
  2. Välj Program.cs i redigeringsprogrammet och lägg till en using för namnområdet StackExchange.Redis

    using StackExchange.Redis;
    

När installationen är klar är Redis-cacheklienten redo för användning med ditt projekt.

Ansluta till cachen

Nu ska vi lägga till koden för att ansluta till cachen.

  1. Välj Program.cs i redigeraren.

  2. Skapa en ConnectionMultiplexer med ConnectionMultiplexer.Connect genom att skicka den till din anslutningssträng. Ge det returnerade värdet namnet cache.

  3. Eftersom anslutningen är kasserbar omsluter du den i ett using-block. Koden bör se ut ungefär som följande.

    string connectionString = config["CacheConnection"];
    
    using (var cache = ConnectionMultiplexer.Connect(connectionString))
    {
    
    }
    

Kommentar

Anslutningen till Azure Cache for Redis hanteras av klassen ConnectionMultiplexer. Den här klassen delas och återanvändas i hela klientprogrammet. Vi vill inte skapa en ny anslutning för varje åtgärd. I stället vill vi lagra den utanför som ett fält i vår klass och återanvända den för varje åtgärd. Här ska vi bara använda den i main-metoden, men i ett produktionsprogram ska den lagras i ett klassfält eller en singleton.

Lägga till ett värde i cachen

Nu när vi har anslutningen ska vi lägga till ett värde i cachen.

  1. I blocket using efter att anslutningen har skapats använder du GetDatabase metoden för att hämta en IDatabase instans:

     IDatabase db = cache.GetDatabase();
    
  2. Anropa StringSet i IDatabase-objektet för att ändra nyckeln ”test:key” till värdet ”some value”.

Returvärdet från StringSet är en bool som visar huruvida nyckeln har lagts till.

  1. Visa returvärdet från StringSet konsolen:

     bool setValue = db.StringSet("test:key", "some value");
     Console.WriteLine($"SET: {setValue}");
    

Hämta ett värde från cachen

  1. Sedan hämtar vi värdet med hjälp av StringGet. Den här metoden tar nyckeln för att hämta och returnerar värdet.

  2. Mata ut det returnerade värdet:

     string? getValue = db.StringGet("test:key");
     Console.WriteLine($"GET: {getValue}");
    
  3. Koden bör se ut så här:

     using System;
     using Microsoft.Extensions.Configuration;
     using System.IO;
     using StackExchange.Redis;
    
     namespace SportsStatsTracker
     {
         class Program
         {
             static void Main(string[] args)
             {
                 var config = new ConfigurationBuilder()
                     .SetBasePath(Directory.GetCurrentDirectory())
                     .AddJsonFile("appsettings.json")
                     .Build();
    
                 string connectionString = config["CacheConnection"];
    
                 using (var cache = ConnectionMultiplexer.Connect(connectionString))
                 {
                     IDatabase db = cache.GetDatabase();
    
                     bool setValue = db.StringSet("test:key", "some value");
                     Console.WriteLine($"SET: {setValue}");
    
                     string? getValue = db.StringGet("test:key");
                     Console.WriteLine($"GET: {getValue}");
                 }
             }
         }
     }
    
  4. Kör programmet för att se resultatet. Skriv dotnet run i terminalfönstret nedanför redigeringsprogrammet. Kontrollera att du är i projektmappen, annars hittar den inte din kod för att skapa och köra.

     dotnet run
    

Dricks

Om programmet inte gör det du förväntar dig, men kompileras, kan det bero på att du inte har sparat ändringarna i redigeraren. Kom alltid ihåg att spara ändringar när du växlar mellan terminalen och redigerarfönstren.

Använda de asynkrona versionerna av metoderna

Vi har kunnat hämta och ange värden från cacheminnet, men vi använder de äldre synkrona versionerna av dessa metoder. I program på serversidan är dessa metoder inte en effektiv användning av våra trådar. I stället vill vi använda de asynkrona versionerna. Du kan enkelt upptäcka dem; de slutar alla i Async.

För att göra dessa metoder enkla att arbeta med använder vi async i C# och await-nyckelord. Om du använder en egen .NET Core-utvecklingsmiljö i stället för det integrerade Cloud Shell måste du använda minst C# 7.1 för att kunna tillämpa dessa nyckelord på Main-metoden .

Använda async-nyckelordet

Tillämpa nyckelordet async på Main-metoden. Vi måste göra två saker.

  1. Lägga till async-nyckelordet i Main-metodens signatur.

  2. Ändra returtypen från void till Task.

    using Microsoft.Extensions.Configuration;
    using StackExchange.Redis;
    
    namespace SportsStatsTracker
    {
       class Program
       {
          static async Task Main(string[] args)
          {
             ...
    

Hämta och ange värden asynkront

Vi kan låta de synkrona metoderna vara kvar. Nu ska vi lägga till ett anrop till metoderna StringSetAsync och StringGetAsync för att lägga till ytterligare ett värde i cacheminnet. Ange räknare till värdet 100.

  1. StringSetAsync Använd metoderna och StringGetAsync för att ange och hämta en nyckel med namnet counter. Ange värdet till 100.

  2. Tillämpa await-nyckelordet för att få resultat från varje metod.

  3. Mata ut resultatet till konsolfönstret, precis som du gjorde med de synkrona versionerna:

    // Simple get and put of integral data types into the cache
    setValue = await db.StringSetAsync("counter", "100");
    Console.WriteLine($"SET: {setValue}");
    
    getValue = await db.StringGetAsync("counter");
    Console.WriteLine($"GET: {getValue}");
    
  4. Kör programmet igen. Det bör fortfarande fungera och har nu två värden.

Öka värdet

  1. Använd StringIncrementAsync-metoden till att öka ditt värde i räknaren. Skicka talet 50 som ska läggas till i räknaren:

    • Observera att metoden tar nyckeln och antingen en long eller double.

    • Beroende på vilka parametrar som skickades returnerar den antingen en long eller double.

  2. Visa resultaten från metoden i konsolen.

    long newValue = await db.StringIncrementAsync("counter", 50);
    Console.WriteLine($"INCR new value = {newValue}");
    

Andra åtgärder

Slutligen ska vi prova att köra några fler metoder med ExecuteAsync stöd.

  1. Kör PING för att testa serveranslutningen. Den bör svara med PONG.

  2. Kör FLUSHDB för att rensa databasvärdena. Den bör svara med OK:

    var result = await db.ExecuteAsync("ping");
    Console.WriteLine($"PING = {result.Type} : {result}");
    
    result = await db.ExecuteAsync("flushdb");
    Console.WriteLine($"FLUSHDB = {result.Type} : {result}");
    

Den slutliga koden bör se ut ungefär så här:

using Microsoft.Extensions.Configuration;
using StackExchange.Redis;

namespace SportsStatsTracker
{
   class Program
   {
      static async Task Main(string[] args)
      {
         var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();

         string connectionString = config["CacheConnection"];

         using (var cache = ConnectionMultiplexer.Connect(connectionString))
         {
            IDatabase db = cache.GetDatabase();

            bool setValue = db.StringSet("test:key", "some value");
            Console.WriteLine($"SET: {setValue}");

            string getValue = db.StringGet("test:key");
            Console.WriteLine($"GET: {getValue}");

            setValue = await db.StringSetAsync("counter", "100");
            Console.WriteLine($"SET: {setValue}");

            getValue = await db.StringGetAsync("counter");
            Console.WriteLine($"GET: {getValue}");

            long newValue = await db.StringIncrementAsync("counter", 50);
            Console.WriteLine($"INCR new value = {newValue}");  

            var result = await db.ExecuteAsync("ping");
            Console.WriteLine($"PING = {result.Type} : {result}");

            result = await db.ExecuteAsync("flushdb");
            Console.WriteLine($"FLUSHDB = {result.Type} : {result}");
         }
      }
   }
}

När du kör programmet igen bör du se följande utdata:

SET: True
GET: some value
SET: True
GET: 100
INCR new value = 150
PING = SimpleString : PONG
FLUSHDB = SimpleString : OK

Uppgift

Som en utmaning kan du försöka att serialisera en objekttyp till cachen. Här är de grundläggande stegen.

  1. Skapa en ny class med några offentliga egenskaper. Du kan göra en egen (”Person” eller ”Bil” är populära), eller använda exemplet ”GameStats” i den föregående utbildningsenhet.

  2. Lägg till stöd för NuGet-paketet Newtonsoft.Json med hjälp av dotnet add package.

  3. Lägg till en using för Newtonsoft.Json-namnområdet.

  4. Skapa ett av objekten.

  5. Serialisera det med JsonConvert.SerializeObject och använd StringSetAsync för att skicka det till cachen.

  6. Hämta tillbaka det från cachen med StringGetAsync och deserialisera det sedan med JsonConvert.DeserializeObject<T>.

Nu när vår Redis-cache har skapats i Azure ska vi skapa ett program för att använda den. Kontrollera att du har information om din anslutning från Azure-portalen.

Kommentar

Integrerad Cloud Shell är tillgängligt till höger. Du kan använda den kommandotolken för att skapa och köra exempelkoden vi skapar här, eller utföra de här stegen lokalt om du har en .Node.js-utvecklingsmiljökonfiguration.

Skapa ett konsolprogram

Vi använder ett konsolprogram så att vi kan fokusera på Redis-implementeringen.

  1. I Cloud Shell skapar du en ny katalog med namnet redisapp och initierar en ny Node.js-app där.

     mkdir redisapp
     cd redisapp
     npm init -y
     touch app.js
    
  2. Vår app använder följande npm-paket:

    • redis: Det vanligaste JavaScript-paketet för anslutning till Redis.
    • bluebird: Används för att konvertera metoderna i motringningsstilen redis i paketet till ett väntande löfte.
    • dotenv: Läser in miljövariabler från en .env fil, där vi lagrar vår Redis-anslutningsinformation.

    Nu ska vi installera dem. Kör det här kommandot för att lägga till dem i vår app:

    npm install redis bluebird dotenv
    

Lägga till konfiguration

Nu ska vi lägga till anslutningsinformationen vi fick från Azure-portalen i en .env-konfigurationsfil.

  1. Skapa en ny .env-fil i projektet:

    touch .env
    
  2. Öppna kodredigeraren genom att skriva code . i projektmappen. Om du arbetar lokalt rekommenderar vi att du använder Visual Studio Code. De här stegen anpassas huvudsakligen med dess användning.

  3. Välj .env-filen i redigeraren och klistra in följande text:

    REDISHOSTNAME=
    REDISKEY=
    REDISPORT=
    
  4. Klistra in i värdnamnet, primärnyckeln och porten efter är lika med-tecknet på varje respektive rad. Den fullständiga filen ser ut ungefär som följande exempel:

    REDISHOSTNAME=myredishost.redis.cache.windows.net
    REDISKEY=K21mLSMN++z8d1FvIeMGy3VOAgoOmqaNYCqeE44eMDc=
    REDISPORT=6380
    
  5. Spara filen med Ctrl + S på Windows och Linux eller Cmd + S på macOS.

Konfigurera implementeringen

Nu är det dags att skriva koden för vårt program.

  1. Välj app.js i redigeringsprogrammet.

  2. Först lägger vi till våra require-instruktioner. Klistra in följande kod högst upp i filen.

    var Promise = require("bluebird");
    var redis = require("redis");
    
  3. Sedan läser vi in konfigurationen .env och använder bluebirds promisifyAll funktion för att konvertera redis paketets funktioner och metoder till ett väntande löfte. Klistra in följande kod:

    require("dotenv").config();
    Promise.promisifyAll(redis);
    
  4. Nu ska vi initiera en Redis-klient. Klistra in den formaterade exempelkoden från föregående lektion (använd process.env för att komma åt värdnamnet, porten och nyckeln) för att skapa klienten:

    const client = redis.createClient(
       process.env.REDISPORT,
       process.env.REDISHOSTNAME,
       {
          password: process.env.REDISKEY,
          tls: { servername: process.env.REDISHOSTNAME }
       }
    );
    

Använda klienten för att arbeta med cachen

Vi är redo att skriva kod för att interagera med vår Redis-cache.

  1. Först lägger vi till en async funktionsomslutning längst ned i filen för att innehålla vår huvudkod. Vi behöver den här omslutningen för att await kunna de asynkrona funktionsanrop som vi ska använda. All resten av koden som vi lägger till i den här lektionen finns i den här omslutningen.

    (async () => {
    
       // The rest of the code you'll paste in goes here.
    
    })();
    
  2. Lägg till ett värde i cachen med setAsync-metoden och läs tillbaka det med getAsync:

    console.log("Adding value to the cache");
    await client.setAsync("myKey", "myValue");
    
    console.log("Reading value back:");
    console.log(await client.getAsync("myKey"));
    
  3. Skicka ett ping till cachen med pingAsync:

    console.log("Pinging the cache");
    console.log(await client.pingAsync());
    
  4. Ta bort alla nycklar i cachen med flushdbAsync:

    await client.flushdbAsync();
    
  5. Slutligen stänger du anslutningen med quitAsync:

    await client.quitAsync();
    
  6. Spara filen. Det färdiga programmet bör se ut så här:

    var Promise = require("bluebird");
    var redis = require("redis");
    
    require("dotenv").config();
    
    Promise.promisifyAll(redis);
    
    const client = redis.createClient(
    process.env.REDISPORT,
    process.env.REDISHOSTNAME,
    {
       password: process.env.REDISKEY,
       tls: { servername: process.env.REDISHOSTNAME }
    }
    );
    
    (async () => {
      console.log("Adding value to the cache");
      await client.setAsync("myKey", "myValue");
      console.log("Reading value back:");
      console.log(await client.getAsync("myKey"));
      console.log("Pinging the cache");
      console.log(await client.pingAsync());
      await client.flushdbAsync();
      await client.quitAsync();
    })();
    
  7. Kör programmet. I Cloud Shell kör du följande kommando.

    node app.js
    

    Du bör se nedanstående resultat.

    Adding value to the cache
    Reading value back:
    myValue
    Pinging the cache
    PONG