Distribuire Orleans in Servizio app di Azure
In questa esercitazione si apprenderà come distribuire un'app carrello acquisti Orleans in Servizio app di Azure. L'esercitazione illustra un'applicazione di esempio che supporta le funzionalità seguenti:
Carrello acquisti: una semplice applicazione carrello acquisti che usa Orleans per il supporto multipiattaforma e le sue funzionalità di applicazioni distribuite scalabili.
- Gestione inventario: modificare e/o creare l'inventario dei prodotti.
- Inventario acquisti: esplora i prodotti acquistabili e li aggiungi al carrello.
- Carrello: visualizza un riepilogo di tutti gli articoli nel carrello e gestisci questi articoli; rimozione o modifica della quantità di ogni articolo.
Con una conoscenza dell'app e delle relative funzionalità, si apprenderà quindi come distribuire l'app in Servizio app di Azure usando GitHub Actions, .NET e ClI di Azure e Azure Bicep. Si apprenderà anche come configurare la rete virtuale per l'app in Azure.
In questa esercitazione verranno illustrate le procedure per:
- Distribuire un'applicazione Orleans in Servizio app di Azure
- Automatizzare la distribuzione con GitHub Actions e Azure Bicep
- Configurare la rete virtuale per l'app in Azure
Prerequisiti
- Un account GitHub
- Leggere un'introduzione a Orleans
- .NET 7 SDK
- L'interfaccia della riga di comando di Azure
- Ambiente di sviluppo integrato .NET (IDE)
- È possibile usare Visual Studio o Visual Studio Code
Eseguire l'app in locale
Per eseguire l'app in locale, creare una copia tramite fork del cluster Azure Samples: Orleans in Servizio app di Azure repository e clonarla nel computer locale. Dopo la clonazione, aprire la soluzione in un IDE di propria scelta. Se si usa Visual Studio, fare clic con il pulsante destro del mouse sul progetto Orleans.ShoppingCart.Silo e scegliere Imposta come progetto di avvio, quindi eseguire l'app. In caso contrario, è possibile eseguire l'app usando il comando dell'interfaccia della riga di comando di .NET seguente:
dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj
Per altre informazioni, vedere dotnet run. Con l'app in esecuzione, è possibile spostarsi ed è possibile testarne le funzionalità. Tutte le funzionalità dell'app durante l'esecuzione in locale si basano sulla persistenza in memoria, sul clustering locale e usa il pacchetto NuGet Bogus per generare prodotti falsi. Arrestare l'app selezionando l'opzione Arresta debug in Visual Studio oppure premendo CTRL+C nell'interfaccia della riga di comando di .NET.
All'interno dell'app carrello acquisti
Orleans è un framework affidabile e scalabile per la creazione di applicazioni distribuite. Per questa esercitazione si distribuirà una semplice app carrello acquisti creata usando Orleans per Servizio app di Azure. L'app espone la possibilità di gestire l'inventario, aggiungere e rimuovere articoli in un carrello e acquistare i prodotti disponibili. Il client viene compilato usando Blazor con un modello di hosting del server. L'app è progettata come segue:
Il diagramma precedente mostra che il client è l'app Blazor lato server. È composto da diversi servizi che utilizzano un grano Orleans corrispondente. Ogni servizio è associato a una granularità di Orleans come indicato di seguito:
InventoryService
: utilizza la posizione in cui l'inventarioIInventoryGrain
viene partizionato per categoria di prodotti.ProductService
: utilizza laIProductGrain
posizione in cui un singolo prodotto viene sottoposto a tethering in una singola istanza di granularità daId
.ShoppingCartService
: utilizza l'oggettoIShoppingCartGrain
in cui un singolo utente ha una sola istanza del carrello acquisti indipendentemente dall'utilizzo dei client.
La soluzione contiene tre progetti:
Orleans.ShoppingCart.Abstractions
: libreria di classi che definisce i modelli e le interfacce per l'app.Orleans.ShoppingCart.Grains
: libreria di classi che definisce i granelli che implementano la logica di business dell'app.Orleans.ShoppingCart.Silos
: un'app Blazor sul lato server che ospita il silo Orleans.
Esperienza utente client
L'app client del carrello acquisti ha diverse pagine, ognuna delle quali rappresenta un'esperienza utente diversa. L'interfaccia utente dell'app viene compilata usando il pacchetto NuGet MudBlazor .
Home page
Alcune frasi semplici per l'utente per comprendere lo scopo dell'app e aggiungere il contesto a ogni voce di menu di spostamento.
Pagina inventario negozio
Pagina che visualizza tutti i prodotti disponibili per l'acquisto. Gli elementi possono essere aggiunti al carrello da questa pagina.
Pagina del carrello vuota
Quando non hai aggiunto nulla al carrello, la pagina esegue il rendering di un messaggio che indica che non hai elementi nel carrello.
Articoli aggiunti al carrello durante la pagina inventario negozio
Quando gli articoli vengono aggiunti al carrello nella pagina dell'inventario negozio, l'app visualizza un messaggio che indica che l'articolo è stato aggiunto al carrello.
Pagina di gestione dei prodotti
Un utente può gestire l'inventario da questa pagina. I prodotti possono essere aggiunti, modificati e rimossi dall'inventario.
Pagina Gestione prodotti - Creazione di una nuova finestra di dialogo
Quando un utente fa clic sul pulsante Crea nuovo prodotto , l'app visualizza una finestra di dialogo che consente all'utente di creare un nuovo prodotto.
Elementi nella pagina del carrello
Quando gli articoli sono nel carrello, è possibile visualizzarli e modificarne la quantità e persino rimuoverli dal carrello. L'utente visualizza un riepilogo degli elementi nel carrello e il costo totale pretax.
Importante
Quando questa app viene eseguita in locale, in un ambiente di sviluppo, l'app userà il clustering localhost, l'archiviazione in memoria e un silo locale. Esegue anche il seeding dell'inventario con dati falsi generati automaticamente usando il pacchetto NuGet Bogus . Questo è tutto intenzionale per dimostrare la funzionalità.
Distribuire nel Servizio app di Azure
Una tipica applicazione Orleans è costituita da un cluster di processi server (silo) in cui risiedono grani e un set di processi client, in genere server Web, che ricevono richieste esterne, li trasformano in chiamate di metodo granulari e restituiscono risultati. Di conseguenza, la prima cosa da fare per eseguire un'applicazione Orleans consiste nell'avviare un cluster di silo. A scopo di test, un cluster può essere costituito da un singolo silo.
Nota
Per una distribuzione di produzione affidabile, è necessario più di un silo in un cluster per la tolleranza di errore e la scalabilità.
Prima di distribuire l'app, è necessario creare un gruppo di risorse di Azure oppure scegliere di usarne uno esistente. Per creare un nuovo gruppo di risorse di Azure, usare uno degli articoli seguenti:
Prendere nota del nome del gruppo di risorse scelto, sarà necessario in un secondo momento per distribuire l'app.
Creare un'entità servizio
Per automatizzare la distribuzione dell'app, è necessario creare un'entità servizio. Si tratta di un account Microsoft autorizzato a gestire le risorse di Azure per conto dell'utente.
az ad sp create-for-rbac --sdk-auth --role Contributor \
--name "<display-name>" --scopes /subscriptions/<your-subscription-id>
Le credenziali JSON create avranno un aspetto simile al seguente, ma con i valori effettivi per il client, la sottoscrizione e il 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"
}
Copiare l'output del comando negli Appunti e continuare con il passaggio successivo.
Creare un segreto GitHub
GitHub offre un meccanismo per la creazione di segreti crittografati. I segreti creati sono disponibili per l'uso nei flussi di lavoro GitHub Actions. Si vedrà come usare GitHub Actions per automatizzare la distribuzione dell'app, insieme ad Azure Bicep. Bicep è un linguaggio specifico del dominio che usa una sintassi dichiarativa per distribuire le risorse di Azure. Per altre informazioni, vedere Informazioni su Bicep. Usando l'output dal passaggio Crea un'entità servizio , è necessario creare un segreto GitHub denominato AZURE_CREDENTIALS
con le credenziali formattate JSON.
All'interno del repository GitHub selezionare Impostazioni>segreti>Crea un nuovo segreto. Immettere il nome AZURE_CREDENTIALS
e incollare le credenziali JSON dal passaggio precedente nel campo Valore .
Per altre informazioni, vedere GitHub: Segreti crittografati.
Preparare la distribuzione di Azure
L'app deve essere in pacchetto per la distribuzione. Orleans.ShoppingCart.Silos
Nel progetto viene definito un Target
elemento eseguito dopo il Publish
passaggio. Verrà zip la directory di pubblicazione in un file disilo.zip :
<Target Name="ZipPublishOutput" AfterTargets="Publish">
<Delete Files="$(ProjectDir)\..\silo.zip" />
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>
Esistono molti modi per distribuire un'app .NET in Servizio app di Azure. In questa esercitazione si usano GitHub Actions, Azure Bicep e .NET e clI di Azure. Considerare il file ./github/workflow/deploy.yml nella radice del repository GitHub:
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
Il flusso di lavoro GitHub precedente:
- Pubblicare l'app carrello acquisti come file zip usando il comando dotnet publish .
- Accedere ad Azure usando le credenziali dal passaggio Crea un'entità servizio .
- Valutare il file main.bicep e avviare un gruppo di distribuzione usando az deployment group create.
- Distribuire il file silo.zip in Servizio app di Azure usando az webapp deploy.
- Viene configurata anche una distribuzione aggiuntiva per la gestione temporanea.
Il flusso di lavoro viene attivato da un push nel ramo principale . Per altre informazioni, vedere GitHub Actions e .NET.
Suggerimento
Se si verificano problemi durante l'esecuzione del flusso di lavoro, potrebbe essere necessario verificare che l'entità servizio disponga di tutti gli spazi dei nomi del provider necessari registrati. Sono necessari gli spazi dei nomi del provider seguenti:
Microsoft.Web
Microsoft.Network
Microsoft.OperationalInsights
Microsoft.Insights
Microsoft.Storage
Per altre informazioni, vedere Risolvere gli errori per la registrazione del provider di risorse.
Azure impone restrizioni di denominazione e convenzioni per le risorse. È necessario aggiornare i valori del file deploy.yml per quanto segue:
UNIQUE_APP_NAME
AZURE_RESOURCE_GROUP_NAME
AZURE_RESOURCE_GROUP_LOCATION
Impostare questi valori sul nome dell'app univoca e sul nome e sulla posizione del gruppo di risorse di Azure.
Per altre informazioni, vedere Regole di denominazione e restrizioni per le risorse di Azure.
Esplorare i modelli Bicep
Quando viene eseguito il az deployment group create
comando, valuta il file main.bicep . Questo file contiene le risorse di Azure da distribuire. Un modo per pensare a questo passaggio è che effettua il provisioning di tutte le risorse per la distribuzione.
Importante
Se si usa Visual Studio Code, l'esperienza di creazione bicep viene migliorata quando si usa l'estensione Bicep.
Esistono molti file bicep, ognuno contenente risorse o moduli (raccolte di risorse). Il file main.bicep è il punto di ingresso ed è costituito principalmente dalle module
definizioni:
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
}
}
Il file bicep precedente definisce quanto segue:
- Due parametri per il nome del gruppo di risorse e il nome dell'app.
- Definizione
storageModule
, che definisce l'account di archiviazione. - Definizione
logsModule
che definisce le risorse di Azure Log Analytics e Application Insights. - Risorsa
vnet
, che definisce la rete virtuale. - Definizione
siloModule
, che definisce la Servizio app di Azure.
Una cosa molto importante resource
è quella della Rete virtuale. La vnet
risorsa consente alla Servizio app di Azure di comunicare con il cluster Orleans.
Ogni volta che viene module
rilevato un oggetto nel file bicep, viene valutato tramite un altro file bicep che contiene le definizioni delle risorse. Il primo modulo rilevato è , storageModule
definito nel file 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}'
I file Bicep accettano parametri, dichiarati usando la param
parola chiave. Analogamente, possono anche dichiarare output usando la output
parola chiave. L'archiviazione resource
si basa sul tipo e sulla Microsoft.Storage/storageAccounts@2021-08-01
versione. Verrà eseguito il provisioning nella posizione del gruppo di risorse, come e StorageV2
Standard_LRS
SKU. Il bicep di archiviazione definisce la stringa di connessione come output
. Questa operazione connectionString
viene usata in seguito dal silo bicep per connettersi all'account di archiviazione.
Il file logs-and-insights.bicep definisce quindi le risorse di Azure Log Analytics e Application Insights:
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
Questo file bicep definisce le risorse di Azure Log Analytics e Application Insights. La appInsights
risorsa è un tipo e la logs
risorsa è un web
PerGB2018
tipo. Sia la appInsights
risorsa che la logs
risorsa vengono sottoposte a provisioning nella posizione del gruppo di risorse. La appInsights
risorsa è collegata alla logs
risorsa tramite la WorkspaceResourceId
proprietà . Esistono due output definiti in questo bicep, usati più avanti dal servizio app module
.
Infine, il file app-service.bicep definisce la risorsa Servizio app di Azure:
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'
}
}
Questo file bicep configura l'Servizio app di Azure come applicazione .NET 7. Sia la appServicePlan
risorsa che la appService
risorsa vengono sottoposte a provisioning nella posizione del gruppo di risorse. La appService
risorsa è configurata per usare lo S1
SKU, con una capacità di 1
. Inoltre, la risorsa è configurata per usare la vnetSubnetId
subnet e per usare HTTPS. Configura anche la appInsightsInstrumentationKey
chiave di strumentazione, la appInsightsConnectionString
stringa di connessione e la storageConnectionString
stringa di connessione. Questi vengono usati dall'app carrello acquisti.
L'estensione di Visual Studio Code precedente per Bicep include un visualizzatore. Tutti questi file bicep vengono visualizzati come segue:
Ambienti di staging
L'infrastruttura di distribuzione può essere distribuita in ambienti di staging, che sono di breve durata, incentrati sui test e sugli ambienti non modificabili. Questi ambienti sono molto utili per testare le distribuzioni prima di promuoverle all'ambiente di produzione.
Nota
Se il servizio app è in esecuzione in Windows, ogni servizio app deve trovarsi nel proprio piano di servizio app separato. In alternativa, per evitare tale configurazione, è possibile usare Servizio app in Linux e questo problema verrà risolto.
Riepilogo
Durante l'aggiornamento del codice sorgente e push
le modifiche apportate al main
ramo del repository, verrà eseguito il flusso di lavoro deploy.yml . Fornisce le risorse definite nei file bicep e distribuisce l'applicazione. L'applicazione può essere espansa in modo da includere nuove funzionalità, ad esempio l'autenticazione o il supporto di più istanze dell'applicazione. L'obiettivo principale di questo flusso di lavoro è dimostrare la possibilità di effettuare il provisioning e distribuire le risorse in un singolo passaggio.
Oltre al visualizzatore dall'estensione bicep, la pagina del gruppo di risorse portale di Azure sarà simile all'esempio seguente dopo il provisioning e la distribuzione dell'applicazione: