Dela via


Distribuera Orleans till Azure App Service

I den här självstudien lär du dig hur du distribuerar en Orleans kundvagnsapp till Azure App Service. Den här guiden går igenom ett exempelprogram som stöder följande funktioner:

  • Kundvagn: Ett enkelt kundvagnsprogram som använder Orleans för sitt plattformsoberoende ramverksstöd och skalbara distribuerade programfunktioner.

    • Inventeringshantering: Redigera och/eller skapa produktinventering.
    • Butiksinventering: Utforska köpbara produkter och lägg dem i kundvagnen.
    • Kundvagn: Visa en sammanfattning av alla objekt i kundvagnen och hantera dessa objekt genom att ta bort eller ändra antalet för varje objekt.

Med en förståelse för appen och dess funktioner lär du dig hur du distribuerar appen till Azure App Service med hjälp av GitHub Actions, .NET och Azure CLIs och Azure Bicep. Dessutom får du lära dig hur du konfigurerar det virtuella nätverket för appen i Azure.

I den här tutorialen lär du dig följande:

  • Distribuera ett Orleans program till Azure App Service
  • Automatisera distributionen med GitHub Actions och Azure Bicep
  • Konfigurera det virtuella nätverket för appen i Azure

Förutsättningar

Köra appen lokalt

Om du vill köra appen lokalt förgrenar du Azure Samples: Orleans Cluster på Azure App Service-lagringsplatsen och klonar den till den lokala datorn. När du har klonat öppnar du lösningen i valfri IDE. Om du använder Visual Studio högerklickar du på Orleans. ShoppingCart.Silo-projekt , välj Ange som startprojekt och kör sedan appen. Annars kör du appen med följande .NET CLI-kommando:

dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj

Mer information finns i dotnet run. När appen körs navigerar du runt och testar dess funktioner. Alla appfunktioner när de körs lokalt förlitar sig på minnesintern beständighet och lokal klustring. Det använder också Bogus NuGet-paketet för att generera falska produkter. Stoppa appen antingen genom att välja alternativet Stoppa felsökning i Visual Studio eller genom att trycka på Ctrl+C i .NET CLI.

Inne i kundvagnsappen

Orleans är ett tillförlitligt och skalbart ramverk för att skapa distribuerade program. För denna handledning distribuerar du en enkel kundvagnsapp byggd med Orleans till Azure App Service. Appen gör det möjligt att hantera lager, lägga till och ta bort objekt i en kundvagn och handla tillgängliga produkter. Klienten skapas med Blazor med en servervärdsmodell. Appen är skapad på följande sätt:

Orleans: Exempel på apparkitektur för kundvagn.

Föregående diagram visar att klienten är Blazor-appen på serversidan. Den består av flera tjänster som använder ett motsvarande Orleans korn. Varje tjänst parkopplas med ett Orleans korn enligt följande:

  • InventoryService: Använder IInventoryGrain där lagret är partitionerat efter produktkategori.
  • ProductService: Förbrukar den IProductGrain där en enskild produkt är bunden till en instans av ett enda korn genom Id.
  • ShoppingCartService: Förbrukar den IShoppingCartGrain där en enskild användare bara har en enda kundvagnsinstans oavsett vilka kunder som konsumerar.

Lösningen innehåller tre projekt:

  • Orleans.ShoppingCart.Abstractions: Ett klassbibliotek som definierar modeller och gränssnitt för appen.
  • Orleans.ShoppingCart.Grains: Ett klassbibliotek som definierar de komponenter som implementerar appens affärslogik.
  • Orleans.ShoppingCart.Silos: En server-side Blazor-app som värdar Orleans-silon.

Klientanvändarupplevelsen

Kundvagnsklientappen har flera sidor som var och en representerar en annan användarupplevelse. Appens användargränssnitt skapas med hjälp av NuGet-paketet MudBlazor .

Startsida

Några enkla fraser hjälper dig att förstå appens syfte och lägga till kontext i varje navigeringsmenyalternativ.

Orleans: Exempelapp för kundvagn, startsida.

Butiksinventeringssida

En sida som visar alla produkter som är tillgängliga att köpa. Objekt kan läggas till i kundvagnen från den här sidan.

Orleans: Exempelapp för kundvagn, butiksinventeringssida.

Tom kundvagnssida

Om inget har lagts till i kundvagnen återger sidan ett meddelande som anger att inga objekt finns i kundvagnen.

Orleans: Exempelapp för kundvagn, tom kundvagnssida.

Objekt som lagts till i kundvagnen på butiksinventeringssidan

När objekt läggs till i kundvagnen på butiksinventeringssidan visar appen ett meddelande som anger att objektet har lagts till.

Orleans: Exempelapp för kundvagn, artiklar som lagts till i kundvagnen på butiksinventeringssidan.

Produkthanteringssidan

Hantera inventering från den här sidan. Produkter kan läggas till, redigeras och tas bort från lagret.

Orleans: Exempelapp för kundvagn, produkthanteringssida.

Skapa ny dialogruta för produkthantering

När du klickar på knappen Skapa ny produkt visas en dialogruta där du kan skapa en ny produkt.

Orleans: Exempelapp för kundvagn, produkthanteringssida – skapa ny produktdialogruta.

Objekt på kundvagnssidan

När objekten finns i kundvagnen visar du dem, ändrar deras kvantitet och tar till och med bort dem. En sammanfattning av artiklarna i kundvagnen och den totala kostnaden före skatt visas.

Orleans: Exempelapp för kundvagn, artiklar på kundvagnssidan.

Viktigt!

När den här appen körs lokalt i en utvecklingsmiljö använder den localhost-kluster, minnesintern lagring och en lokal silo. Det sår också lagret med falsk data som genereras automatiskt med hjälp av Bogus NuGet-paketet. Detta är avsiktligt för att demonstrera funktioner.

Översikt över distribution

Orleans program är utformade för att skala upp och skala ut effektivt. För att åstadkomma detta kommunicerar programinstanser direkt via TCP-socketar. Orleans kräver nätverksanslutning mellan silor, därför. Azure App Service stöder detta krav via integrering av virtuella nätverk och ytterligare konfiguration som instruerar App Service att allokera privata nätverksportar för appinstanser.

När du distribuerar Orleans till Azure App Service vidtar du följande åtgärder för att säkerställa att värdarna kan kommunicera:

Konfigurera antal privata portar med Hjälp av Azure CLI

az webapp config set -g '<resource-group-name>' --subscription '<subscription-id>' -n '<app-service-app-name>' --generic-configurations '{\"vnetPrivatePortsCount\": "2"}'

Konfigurera värdnätverk

När du har konfigurerat Azure App Service med integrering av virtuellt nätverk (VNet) och ställt in den för att tillhandahålla programinstanser med minst två privata portar vardera, tillhandahålls ytterligare två miljövariabler till dina appprocesser: WEBSITE_PRIVATE_IP och WEBSITE_PRIVATE_PORTS. Dessa variabler innehåller två viktiga informationsdelar:

  • Vilken IP-adress andra värdar i det virtuella nätverket kan använda för att kontakta en viss appinstans. och
  • Vilka portar på ip-adressen dirigeras till den appinstansen

Variabeln WEBSITE_PRIVATE_IP anger en IP-routningsbar ip-adress från det virtuella nätverket, men inte nödvändigtvis en IP-adress som appinstansen direkt kan binda till. Därför ska du instruera värden att binda till alla interna adresser genom att skicka listenOnAnyHostAddress: true till metodens anrop ConfigureEndpoints. I följande exempel konfigureras en ISiloBuilder instans för att använda de inmatade miljövariablerna och lyssna på rätt gränssnitt:

var endpointAddress = IPAddress.Parse(builder.Configuration["WEBSITE_PRIVATE_IP"]!);
var strPorts = builder.Configuration["WEBSITE_PRIVATE_PORTS"]!.Split(',');
if (strPorts.Length < 2)
{
    throw new Exception("Insufficient private ports configured.");
}

var (siloPort, gatewayPort) = (int.Parse(strPorts[0]), int.Parse(strPorts[1]));

siloBuilder
    .ConfigureEndpoints(endpointAddress, siloPort, gatewayPort, listenOnAnyHostAddress: true)

Koden ovan finns också i Azure Samples: Orleans Cluster på Azure App Service-lagringsplatsen , vilket gör det möjligt att visa den i kontexten för resten av värdkonfigurationen.

Distribuera till Azure App Service

Ett typiskt Orleans program består av ett kluster av serverprocesser (silor) där kornen finns och en uppsättning klientprocesser (vanligtvis webbservrar) som tar emot externa begäranden, omvandlar dem till kornmetodanrop och returnerar resultat. För att köra ett Orleans-program är första steget att starta ett kluster med silor. I testsyfte kan ett kluster bestå av en enda silo.

Anmärkning

För en tillförlitlig produktionsdistribution skulle du vilja ha mer än en silo i ett kluster för feltolerans och skalning.

Innan du distribuerar appen skapar du en Azure-resursgrupp (eller så kan du använda en befintlig). Om du vill skapa en ny Azure-resursgrupp använder du någon av följande artiklar:

Anteckna namnet på resursgruppen som du väljer. du behöver den senare för att distribuera appen.

Skapa ett huvudnamn för tjänsten

För att automatisera appens distribution måste du skapa ett huvudnamn för tjänsten. Det här är ett Microsoft-konto som har behörighet att hantera Azure-resurser åt dig.

az ad sp create-for-rbac --sdk-auth --role Contributor \
  --name "<display-name>"  --scopes /subscriptions/<your-subscription-id>

JSON-autentiseringsuppgifterna som skapas ser ut ungefär så här, men med faktiska värden för din klient, prenumeration och klientorganisation:

{
  "clientId": "<your client id>",
  "clientSecret": "<your client secret>",
  "subscriptionId": "<your subscription id>",
  "tenantId": "<your tenant id>",
  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com/",
  "resourceManagerEndpointUrl": "https://brazilus.management.azure.com",
  "activeDirectoryGraphResourceId": "https://graph.windows.net/",
  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
  "galleryEndpointUrl": "https://gallery.azure.com",
  "managementEndpointUrl": "https://management.core.windows.net"
}

Kopiera kommandots utdata till urklipp och fortsätt till nästa steg.

Skapa en GitHub-hemlighet

GitHub tillhandahåller en mekanism för att skapa krypterade hemligheter. Hemligheterna du skapar är tillgängliga för användning i GitHub Actions-arbetsflöden. Du ser hur du använder GitHub Actions för att automatisera appens distribution tillsammans med Azure Bicep. Bicep är ett domänspecifikt språk (DSL) som använder deklarativ syntax för att distribuera Azure-resurser. Mer information finns i Vad är Bicep?. Med hjälp av utdata från steget Skapa en tjänsthuvudnamn måste du skapa en GitHub-hemlighet med namnet AZURE_CREDENTIALS med JSON-formaterade autentiseringsuppgifter.

På din GitHub-lagringsplats väljer du Inställningar>Hemligheter>Skapa en ny hemlighet. Ange namnet AZURE_CREDENTIALS och klistra in JSON-autentiseringsuppgifterna från föregående steg i fältet Värde .

GitHub-lagringsplats: Inställningar Hemligheter >

Mer information finns i GitHub: Krypterade hemligheter.

Förbereda för Azure-distribution

Paketera appen för distribution. Orleans.ShoppingCart.Silos I projektet definieras ett Target element som körs efter Publish steget. Detta mål zippar publiceringskatalogen till en silo.zip-fil:

<Target Name="ZipPublishOutput" AfterTargets="Publish">
    <Delete Files="$(ProjectDir)\..\silo.zip" />
    <ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>

Det finns många sätt att distribuera en .NET-app till Azure App Service. I den här självstudien använder du GitHub Actions, Azure Bicep och .NET och Azure CLIs. Överväg filen ./github/workflows/deploy.yml i roten på GitHub-lagringsplatsen:

name: Deploy to Azure App Service

on:
  push:
    branches:
    - main

env:
  UNIQUE_APP_NAME: cartify
  AZURE_RESOURCE_GROUP_NAME: orleans-resourcegroup
  AZURE_RESOURCE_GROUP_LOCATION: centralus

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Setup .NET 8.0
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: 8.0.x

    - name: .NET publish shopping cart app
      run: dotnet publish ./Silo/Orleans.ShoppingCart.Silo.csproj --configuration Release

    - name: Login to Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Flex bicep
      run: |
        az deployment group create \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
          --template-file '.github/workflows/flex/main.bicep' \
          --parameters location=${{ env.AZURE_RESOURCE_GROUP_LOCATION }} \
            appName=${{ env.UNIQUE_APP_NAME }} \
          --debug

    - name: Webapp deploy
      run: |
        az webapp deploy --name ${{ env.UNIQUE_APP_NAME }} \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME  }} \
          --clean true --restart true \
          --type zip --src-path silo.zip --debug

    - name: Staging deploy
      run: |
        az webapp deploy --name ${{ env.UNIQUE_APP_NAME }} \
          --slot ${{ env.UNIQUE_APP_NAME }}stg \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME  }} \
          --clean true --restart true \
          --type zip --src-path silo.zip --debug

Föregående GitHub-arbetsflöde gör följande:

Arbetsflödet utlöses vid en push till grenen main. Mer information finns i GitHub Actions och .NET.

Tips/Råd

Om du stöter på problem när du kör arbetsflödet kan du behöva kontrollera att tjänstens huvudnamn har alla nödvändiga providernamnområden registrerade. Följande providernamnområden krävs:

  • Microsoft.Web
  • Microsoft.Network
  • Microsoft.OperationalInsights
  • Microsoft.Insights
  • Microsoft.Storage

Mer information finns i Lösa fel för registrering av resursprovider.

Azure tillämpar namngivningsbegränsningar och konventioner för resurser. Uppdatera värdena i filen deploy.yml för följande miljövariabler:

  • UNIQUE_APP_NAME
  • AZURE_RESOURCE_GROUP_NAME
  • AZURE_RESOURCE_GROUP_LOCATION

Ange dessa värden till ditt unika appnamn och namnet och platsen för azure-resursgruppen.

Mer information finns i Namngivningsregler och begränsningar för Azure-resurser.

Utforska Bicep-mallarna

az deployment group create När kommandot körs utvärderas filen main.bicep. Den här filen innehåller De Azure-resurser som ska distribueras. Tänk på det här steget som att tillhandahålla alla resurser för distribution.

Viktigt!

Om du använder Visual Studio Code förbättras bicep-skrivupplevelsen när du använder Bicep-tillägget.

Det finns många Bicep-filer som var och en innehåller antingen resurser eller moduler (samlingar med resurser). Filen main.bicep är startpunkten och består främst av module definitioner:

param appName string
param location string = resourceGroup().location

module storageModule 'storage.bicep' = {
  name: 'orleansStorageModule'
  params: {
    name: '${appName}storage'
    location: location
  }
}

module logsModule 'logs-and-insights.bicep' = {
  name: 'orleansLogModule'
  params: {
    operationalInsightsName: '${appName}-logs'
    appInsightsName: '${appName}-insights'
    location: location
  }
}

resource vnet 'Microsoft.Network/virtualNetworks@2021-05-01' = {
  name: '${appName}-vnet'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '172.17.0.0/16',
        '192.168.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'default'
        properties: {
          addressPrefix: '172.17.0.0/24'
          delegations: [
            {
              name: 'delegation'
              properties: {
                serviceName: 'Microsoft.Web/serverFarms'
              }
            }
          ]
        }
      }
      {
        name: 'staging'
        properties: {
          addressPrefix: '192.168.0.0/24'
          delegations: [
            {
              name: 'delegation'
              properties: {
                serviceName: 'Microsoft.Web/serverFarms'
              }
            }
          ]
        }
      }
    ]
  }
}

module siloModule 'app-service.bicep' = {
  name: 'orleansSiloModule'
  params: {
    appName: appName
    location: location
    vnetSubnetId: vnet.properties.subnets[0].id
    stagingSubnetId: vnet.properties.subnets[1].id
    appInsightsConnectionString: logsModule.outputs.appInsightsConnectionString
    appInsightsInstrumentationKey: logsModule.outputs.appInsightsInstrumentationKey
    storageConnectionString: storageModule.outputs.connectionString
  }
}

Föregående Bicep-fil definierar följande:

  • Två parametrar för resursgruppens namn och appnamnet.
  • Definitionen storageModule , som definierar lagringskontot.
  • Definitionen logsModule , som definierar Azure Log Analytics- och Application Insights-resurserna.
  • Resursen vnet , som definierar det virtuella nätverket.
  • Definitionen siloModule , som definierar Azure App Service.

En mycket viktig resource är det virtuella nätverket. Med resursen vnet kan Azure App Service kommunicera med Orleans klustret.

När en module påträffas i Bicep-filen utvärderas den via en annan Bicep-fil som innehåller resursdefinitionerna. Den första modulen som påträffades är storageModule, definierad i filen storage.bicep :

param name string
param location string

resource storage 'Microsoft.Storage/storageAccounts@2021-08-01' = {
  name: name
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}

var key = listKeys(storage.name, storage.apiVersion).keys[0].value
var protocol = 'DefaultEndpointsProtocol=https'
var accountBits = 'AccountName=${storage.name};AccountKey=${key}'
var endpointSuffix = 'EndpointSuffix=${environment().suffixes.storage}'

output connectionString string = '${protocol};${accountBits};${endpointSuffix}'

Bicep-filer accepterar parametrar som deklareras med hjälp av nyckelordet param . På samma sätt kan de deklarera utdata med hjälp av nyckelordet output . Lagringen resource förlitar sig på Microsoft.Storage/storageAccounts@2021-08-01 typen och versionen. Den provisioneras på platsen för resursgruppen som en StorageV2 och Standard_LRS SKU. Bicep-filen för lagring definierar anslutningssträngen som en output. Detta connectionString används senare av silo Bicep-filen för att ansluta till lagringskontot.

Därefter definierar logs-and-insights.bicep-filen Azure Log Analytics- och Application Insights-resurserna:

param operationalInsightsName string
param appInsightsName string
param location string

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: appInsightsName
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logs.id
  }
}

resource logs 'Microsoft.OperationalInsights/workspaces@2021-06-01' = {
  name: operationalInsightsName
  location: location
  properties: {
    retentionInDays: 30
    features: {
      searchVersion: 1
    }
    sku: {
      name: 'PerGB2018'
    }
  }
}

output appInsightsInstrumentationKey string = appInsights.properties.InstrumentationKey
output appInsightsConnectionString string = appInsights.properties.ConnectionString

Den här Bicep-filen definierar Azure Log Analytics- och Application Insights-resurserna. Resursen appInsights är en web typ och resursen logs är en PerGB2018 typ. Både appInsights och logs resurser etableras på resursgruppens plats. Resursen appInsights länkar till resursen logs via egenskapen WorkspaceResourceId . Den här Bicep-filen definierar två utdata som används senare av App Service module.

Slutligen definierar filen app-service.bicep Azure App Service-resursen:

param appName string
param location string
param vnetSubnetId string
param stagingSubnetId string
param appInsightsInstrumentationKey string
param appInsightsConnectionString string
param storageConnectionString string

resource appServicePlan 'Microsoft.Web/serverfarms@2021-03-01' = {
  name: '${appName}-plan'
  location: location
  kind: 'app'
  sku: {
    name: 'S1'
    capacity: 1
  }
}

resource appService 'Microsoft.Web/sites@2021-03-01' = {
  name: appName
  location: location
  kind: 'app'
  properties: {
    serverFarmId: appServicePlan.id
    virtualNetworkSubnetId: vnetSubnetId
    httpsOnly: true
    siteConfig: {
      vnetPrivatePortsCount: 2
      webSocketsEnabled: true
      netFrameworkVersion: 'v8.0'
      appSettings: [
        {
          name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
          value: appInsightsInstrumentationKey
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: appInsightsConnectionString
        }
        {
          name: 'ORLEANS_AZURE_STORAGE_CONNECTION_STRING'
          value: storageConnectionString
        }
        {
          name: 'ORLEANS_CLUSTER_ID'
          value: 'Default'
        }
      ]
      alwaysOn: true
    }
  }
}

resource stagingSlot 'Microsoft.Web/sites/slots@2022-03-01' = {
  name: '${appName}stg'
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    virtualNetworkSubnetId: stagingSubnetId
    siteConfig: {
      http20Enabled: true
      vnetPrivatePortsCount: 2
      webSocketsEnabled: true
      netFrameworkVersion: 'v8.0'
      appSettings: [
        {
          name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
          value: appInsightsInstrumentationKey
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: appInsightsConnectionString
        }
        {
          name: 'ORLEANS_AZURE_STORAGE_CONNECTION_STRING'
          value: storageConnectionString
        }
        {
          name: 'ORLEANS_CLUSTER_ID'
          value: 'Staging'
        }
      ]
      alwaysOn: true
    }
  }
}

resource slotConfig 'Microsoft.Web/sites/config@2021-03-01' = {
  name: 'slotConfigNames'
  parent: appService
  properties: {
    appSettingNames: [
      'ORLEANS_CLUSTER_ID'
    ]
  }
}

resource appServiceConfig 'Microsoft.Web/sites/config@2021-03-01' = {
  parent: appService
  name: 'metadata'
  properties: {
    CURRENT_STACK: 'dotnet'
  }
}

Den här Bicep-filen konfigurerar Azure App Service som ett .NET 8-program. Både appServicePlan och appService resurser etableras på resursgruppens plats. Resursen appService är konfigurerad för att använda SKU:n S1 med en kapacitet på 1. Dessutom är resursen konfigurerad för att använda vnetSubnetId undernätet och HTTPS. Också konfigurerar den appInsightsInstrumentationKey instrumentationsnyckeln, samt anslutningssträngarna appInsightsConnectionString och storageConnectionString. Kundvagnsappen använder dessa värden.

Det ovan nämnda Visual Studio Code-tillägget för Bicep innehåller en visualiserare. Alla dessa Bicep-filer visualiseras på följande sätt:

Orleans: Kundvagnsexempelapp bicep tilldelningsvisualisering rendering.

Mellanlagringsmiljöer

Distributionsinfrastrukturen kan distribueras till mellanlagringsmiljöer. Dessa är kortlivade, testcentrerade, oföränderliga testmiljöer som är mycket användbara för att testa utplaceringar innan de flyttas till produktion.

Anmärkning

Om App Service körs i Windows måste varje App Service ha en egen separat App Service-plan. Du kan också undvika den här konfigurationen genom att använda App Service på Linux i stället, och det här problemet är löst.

Sammanfattning

När källkoden uppdateras och ändringar skickas pushtill main lagringsplatsens gren körs deploy.yml arbetsflödet. Den tilldelar de resurser som definierats i Bicep-filer och distribuerar applikationen. Programmet kan utökas till att omfatta nya funktioner, till exempel autentisering, eller för att stödja flera instanser. Det primära målet med det här arbetsflödet är att demonstrera möjligheten att etablera och distribuera resurser i ett enda steg.

Förutom visualiseraren från Bicep-tillägget ser resursgruppssidan i Azure-portalen ut ungefär som i följande exempel efter etablering och distribution av programmet:

Azure Portal: Orleans exempelappresurser för kundvagn.

Se även