Delen via


Orleans implementeren in Azure App Service

In deze zelfstudie leert u hoe u een orleans winkelwagen-app implementeert in Azure App Service. In de zelfstudie wordt een voorbeeldtoepassing beschreven die ondersteuning biedt voor de volgende functies:

  • Winkelwagen: Een eenvoudige winkelwagentoepassing die Orleans gebruikt voor de platformoverschrijdende frameworkondersteuning en de schaalbare gedistribueerde toepassingen.

    • Voorraadbeheer: bewerk en/of maak een productvoorraad.
    • Winkelinventaris: Verken aankoopbare producten en voeg ze toe aan uw winkelwagen.
    • Winkelwagen: Bekijk een overzicht van alle items in uw winkelwagen en beheer deze items; het verwijderen of wijzigen van de hoeveelheid van elk item.

Als u kennis hebt van de app en de bijbehorende functies, leert u vervolgens hoe u de app implementeert in Azure App Service met behulp van GitHub Actions, de .NET- en Azure-CURI's en Azure Bicep. Daarnaast leert u hoe u het virtuele netwerk voor de app in Azure configureert.

In deze zelfstudie leert u het volgende:

  • Een Orleans-toepassing implementeren in Azure App Service
  • Implementatie automatiseren met behulp van GitHub Actions en Azure Bicep
  • Het virtuele netwerk voor de app in Azure configureren

Vereisten

De app lokaal uitvoeren

Als u de app lokaal wilt uitvoeren, forkt u de Azure Samples: Orleans Cluster op Azure App Service opslagplaats en kloont u deze naar uw lokale computer. Nadat de oplossing is gekloond, opent u de oplossing in een IDE van uw keuze. Als u Visual Studio gebruikt, klikt u met de rechtermuisknop op het project Orleans.ShoppingCart.Silo en selecteert u Instellen als opstartproject en voert u de app uit. Anders kunt u de app uitvoeren met behulp van de volgende .NET CLI-opdracht:

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

Zie dotnet run voor meer informatie. Terwijl de app wordt uitgevoerd, kunt u navigeren en kunt u de mogelijkheden testen. Alle functionaliteit van de app bij lokaal uitvoeren is afhankelijk van persistentie in het geheugen, lokale clustering en het Bogus NuGet-pakket om nepproducten te genereren. Stop de app door de optie Foutopsporing stoppen te selecteren in Visual Studio of door op Ctrl+C te drukken in de .NET CLI.

In de winkelwagen-app

Orleans is een betrouwbaar en schaalbaar framework voor het bouwen van gedistribueerde toepassingen. Voor deze zelfstudie implementeert u een eenvoudige winkelwagen-app die is gebouwd met orleans om te Azure App Service. De app biedt de mogelijkheid om voorraad te beheren, items toe te voegen aan en te verwijderen uit een winkelwagen en beschikbare producten te kopen. De client is gebouwd met behulp van Blazor met een serverhostingmodel. De app is als volgt ontworpen:

Orleans: Voorbeeld-app-architectuur van winkelwagen.

In het voorgaande diagram ziet u dat de client de Blazor-app aan de serverzijde is. Het bestaat uit verschillende services die een overeenkomstige orleanskorrel verbruiken. Elke service wordt als volgt gekoppeld aan een Orleans-korrel:

  • InventoryService: Gebruikt de locatie waar de IInventoryGrain voorraad is gepartitioneerd op productcategorie.
  • ProductService: gebruikt de IProductGrain locatie waar één product is gekoppeld aan één korrelexemplaar door Id.
  • ShoppingCartService: Gebruikt de IShoppingCartGrain locatie waarbij één gebruiker slechts één exemplaar van een winkelwagen heeft, ongeacht het verbruik van clients.

De oplossing bevat drie projecten:

  • Orleans.ShoppingCart.Abstractions: Een klassebibliotheek die de modellen en de interfaces voor de app definieert.
  • Orleans.ShoppingCart.Grains: een klassenbibliotheek die de korrels definieert waarmee de bedrijfslogica van de app wordt geïmplementeerd.
  • Orleans.ShoppingCart.Silos: Een Blazor-app aan de serverzijde die als host fungeert voor de orleanssilo.

De gebruikerservaring van de client

De winkelwagenclient-app heeft verschillende pagina's, die elk een andere gebruikerservaring vertegenwoordigen. De gebruikersinterface van de app is gebouwd met behulp van het MudBlazor NuGet-pakket .

Startpagina

Enkele eenvoudige zinnen voor de gebruiker om het doel van de app te begrijpen en context toe te voegen aan elk navigatiemenu-item.

Orleans: Voorbeeld-app winkelwagen, startpagina.

Pagina Winkelinventaris

Een pagina waarop alle producten worden weergegeven die kunnen worden gekocht. Items kunnen vanaf deze pagina aan de winkelwagen worden toegevoegd.

Orleans: Winkelwagen voorbeeld-app, winkelinventarispagina.

Lege winkelwagenpagina

Wanneer u niets aan uw winkelwagen hebt toegevoegd, wordt op de pagina een bericht weergegeven dat aangeeft dat u geen items in uw winkelwagen hebt.

Orleans: Voorbeeld-app winkelwagen, lege winkelwagenpagina.

Items die aan de winkelwagen zijn toegevoegd terwijl ze op de winkelinventarispagina staan

Wanneer artikelen aan uw winkelwagen worden toegevoegd terwijl u op de winkelinventarispagina bent, geeft de app een bericht weer dat aangeeft dat het artikel aan de winkelwagen is toegevoegd.

Orleans: Voorbeeld-app winkelwagen, items toegevoegd aan winkelwagen terwijl op winkelinventarispagina.

Pagina Productbeheer

Een gebruiker kan inventaris beheren vanaf deze pagina. Producten kunnen worden toegevoegd, bewerkt en verwijderd uit de inventaris.

Orleans: Voorbeeld-app winkelwagen, pagina voor productbeheer.

Dialoogvenster Nieuw maken op de pagina Productbeheer

Wanneer een gebruiker op de knop Nieuw product maken klikt, wordt in de app een dialoogvenster weergegeven waarmee de gebruiker een nieuw product kan maken.

Orleans: Voorbeeld-app winkelwagen, productbeheerpagina - dialoogvenster voor het maken van een nieuw product.

Items op de winkelwagenpagina

Wanneer artikelen zich in uw winkelwagen bevinden, kunt u ze bekijken en hun aantal wijzigen en ze zelfs uit de winkelwagen verwijderen. De gebruiker krijgt een overzicht te zien van de artikelen in de winkelwagen en de totale kosten vóór btw.

Orleans: Winkelwagen voorbeeld-app, items in winkelwagen pagina.

Belangrijk

Wanneer deze app lokaal wordt uitgevoerd, in een ontwikkelomgeving, gebruikt de app localhost-clustering, opslag in het geheugen en een lokale silo. Ook wordt de inventaris gezaaid met valse gegevens die automatisch worden gegenereerd met behulp van het Bogus NuGet-pakket . Dit is allemaal bedoeld om de functionaliteit te demonstreren.

Implementeren naar Azure App Service

Een typische Orleans-toepassing bestaat uit een cluster van serverprocessen (silo's) waar korrels zich bevinden, en een set clientprocessen, meestal webservers, die externe aanvragen ontvangen, deze omzetten in aanroepen van graanmethodes en resultaten retourneren. Het eerste wat u moet doen om een Orleans-toepassing uit te voeren, is daarom een cluster van silo's starten. Voor testdoeleinden kan een cluster uit één silo bestaan.

Notitie

Voor een betrouwbare productie-implementatie hebt u meer dan één silo in een cluster nodig voor fouttolerantie en schaal.

Voordat u de app implementeert, moet u een Azure-resourcegroep maken (of u kunt ervoor kiezen om een bestaande resourcegroep te gebruiken). Gebruik een van de volgende artikelen om een nieuwe Azure-resourcegroep te maken:

Noteer de naam van de resourcegroep die u kiest. U hebt deze later nodig om de app te implementeren.

Een service-principal maken

Als u de implementatie van de app wilt automatiseren, moet u een service-principal maken. Dit is een Microsoft-account dat is gemachtigd om Azure-resources namens u te beheren.

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

De gemaakte JSON-referenties zien er ongeveer als volgt uit, maar met werkelijke waarden voor uw client, abonnement en tenant:

{
  "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"
}

Kopieer de uitvoer van de opdracht naar het Klembord en ga verder met de volgende stap.

Een GitHub-geheim maken

GitHub biedt een mechanisme voor het maken van versleutelde geheimen. De geheimen die u maakt, zijn beschikbaar voor gebruik in GitHub Actions werkstromen. U gaat zien hoe GitHub Actions kunnen worden gebruikt om de implementatie van de app te automatiseren, in combinatie met Azure Bicep. Bicep is een domeinspecifieke taal (DSL) die gebruikmaakt van een declaratieve syntaxis om Azure-resources te implementeren. Zie Wat is Bicep voor meer informatie. Met behulp van de uitvoer van de stap Een service-principal maken , moet u een GitHub-geheim met de naam AZURE_CREDENTIALS maken met de referenties in JSON-indeling.

Selecteer in de GitHub-opslagplaats Instellingen>Geheimen>Een nieuw geheim maken. Voer de naam AZURE_CREDENTIALS in en plak de JSON-referenties uit de vorige stap in het veld Waarde .

GitHub-opslagplaats: Instellingen > geheimen

Zie GitHub: Encrypted Secrets (Versleutelde geheimen) voor meer informatie.

Voorbereiden op Azure-implementatie

De app moet worden verpakt voor implementatie. In het Orleans.ShoppingCart.Silos project definiëren we een Target element dat na de Publish stap wordt uitgevoerd. Hiermee wordt de publicatiemap gezipt in een silo.zip-bestand :

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

Er zijn veel manieren om een .NET-app te implementeren in Azure App Service. In deze zelfstudie gebruikt u GitHub Actions, Azure Bicep en de .NET- en Azure CLIs. Overweeg het bestand ./github/workflows/deploy.yml in de hoofdmap van de GitHub-opslagplaats:

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 7.0
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: 7.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

De voorgaande GitHub-werkstroom:

De werkstroom wordt geactiveerd door een push naar de hoofdbranch . Zie GitHub Actions en .NET voor meer informatie.

Tip

Als u problemen ondervindt bij het uitvoeren van de werkstroom, moet u mogelijk controleren of de service-principal alle vereiste providernaamruimten heeft geregistreerd. De volgende providernaamruimten zijn vereist:

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

Zie Fouten voor de registratie van resourceproviders oplossen voor meer informatie.

Azure legt naamgevingsbeperkingen en -conventies op voor resources. U moet de bestandswaarden deploy.yml bijwerken voor het volgende:

  • UNIQUE_APP_NAME
  • AZURE_RESOURCE_GROUP_NAME
  • AZURE_RESOURCE_GROUP_LOCATION

Stel deze waarden in op uw unieke app-naam en de naam en locatie van uw Azure-resourcegroep.

Zie Naamgevingsregels en -beperkingen voor Azure-resources voor meer informatie.

De Bicep-sjablonen verkennen

Wanneer de az deployment group create opdracht wordt uitgevoerd, wordt het bestand main.bicep geëvalueerd. Dit bestand bevat de Azure-resources die u wilt implementeren. Een manier om deze stap te bedenken, is dat hiermee alle resources voor implementatie worden geïmplementeerd.

Belangrijk

Als u Visual Studio Code gebruikt, is de bicep-ontwerpervaring verbeterd wanneer u de Bicep-extensie gebruikt.

Er zijn veel bicep-bestanden, elk met resources of modules (verzamelingen resources). Het bestand main.bicep is het toegangspunt en bestaat voornamelijk module uit definities:

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
  }
}

Het voorgaande bicep-bestand definieert het volgende:

  • Twee parameters voor de naam van de resourcegroep en de naam van de app.
  • De storageModule definitie, waarmee het opslagaccount wordt gedefinieerd.
  • De logsModule definitie, waarmee de Azure Log Analytics- en Application Insights-resources worden gedefinieerd.
  • De vnet resource, waarmee het virtuele netwerk wordt gedefinieerd.
  • De siloModule definitie, waarmee de Azure App Service wordt gedefinieerd.

Een belangrijk punt resource is die van de Virtual Network. De vnet resource stelt de Azure App Service in staat om te communiceren met het orleanscluster.

Wanneer een module wordt aangetroffen in het bicep-bestand, wordt deze geëvalueerd via een ander bicep-bestand dat de resourcedefinities bevat. De eerste aangetroffen module was de storageModule, die is gedefinieerd in het bestand 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-bestanden accepteren parameters, die worden gedeclareerd met behulp van het param trefwoord. Op dezelfde manier kunnen ze ook uitvoer declareren met behulp van het output trefwoord. De opslag resource is afhankelijk van het type en de Microsoft.Storage/storageAccounts@2021-08-01 versie. Het wordt ingericht in de locatie van de resourcegroep, als een StorageV2 en-SKU Standard_LRS . De opslag-bicep definieert de connection string als een output. Dit connectionString wordt later gebruikt door de silo bicep om verbinding te maken met het opslagaccount.

Vervolgens definieert het bestand logs-and-insights.bicep de Azure Log Analytics- en Application Insights-resources:

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

Dit bicep-bestand definieert de Azure Log Analytics- en Application Insights-resources. De appInsights resource is een web type en de logs resource is een PerGB2018 type. Zowel de appInsights resource als de logs resource worden ingericht op de locatie van de resourcegroep. De appInsights resource is via de logs eigenschap gekoppeld aan de WorkspaceResourceId resource. Er zijn twee uitvoerwaarden gedefinieerd in deze bicep, die later worden gebruikt door de App Service module.

Ten slotte definieert het bestand app-service.bicep de Azure App Service resource:

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: 'v6.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: 'v7.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'
  }
}

Met dit bicep-bestand configureert u de Azure App Service als een .NET 7-toepassing. Zowel de appServicePlan resource als de appService resource worden ingericht op de locatie van de resourcegroep. De appService resource is geconfigureerd voor gebruik van de S1 SKU, met een capaciteit van 1. Daarnaast is de resource geconfigureerd voor het gebruik van het vnetSubnetId subnet en voor het gebruik van HTTPS. Ook worden de appInsightsInstrumentationKey instrumentatiesleutel, de appInsightsConnectionString connection string en de storageConnectionString connection string geconfigureerd. Deze worden gebruikt door de winkelwagen-app.

De eerder genoemde Visual Studio Code-extensie voor Bicep bevat een visualizer. Al deze bicep-bestanden worden als volgt gevisualiseerd:

Orleans: Voorbeeld-app voor winkelwagen met bicep-inrichting van visualizerrendering.

Faseringsomgevingen

De implementatie-infrastructuur kan worden geïmplementeerd in faseringsomgevingen, die kortstondige, testgerichte en onveranderbare wegwerpomgevingen zijn. Deze omgevingen zijn erg handig voor het testen van implementaties voordat ze naar productie worden gepromoot.

Notitie

Als uw App Service wordt uitgevoerd in Windows, moet elke App Service een afzonderlijk App Service-abonnement hebben. U kunt ook een dergelijke configuratie voorkomen door in plaats daarvan App Service op Linux te gebruiken. Dit probleem wordt dan opgelost.

Samenvatting

Wanneer u de broncode bijwerkt en push wijzigingen aan de main vertakking van de opslagplaats wijzigt, wordt de werkstroom deploy.yml uitgevoerd. Het biedt de resources die zijn gedefinieerd in de bicep-bestanden en implementeert de toepassing. De toepassing kan worden uitgebreid met nieuwe functies, zoals verificatie, of ter ondersteuning van meerdere exemplaren van de toepassing. Het primaire doel van deze werkstroom is het demonstreren van de mogelijkheid om resources in één stap in te richten en te implementeren.

Naast de visualizer van de bicep-extensie ziet de pagina Azure Portal resourcegroep er ongeveer uit als in het volgende voorbeeld na het inrichten en implementeren van de toepassing:

Azure Portal: Resources voor voorbeelden van apps in de winkelmand van Orleans.

Zie ook