Implementar Orleans no Serviço de Aplicações do Azure
Neste tutorial, vai aprender a implementar uma aplicação de carrinho de compras em Orleans para Serviço de Aplicações do Azure. O tutorial orienta-o através de uma aplicação de exemplo que suporta as seguintes funcionalidades:
Carrinho de compras: uma aplicação de carrinho de compras simples que utiliza Orleans para o suporte de arquitetura entre plataformas e as suas capacidades de aplicações distribuídas dimensionáveis.
- Gestão de inventário: Editar e/ou criar inventário de produtos.
- Inventário de lojas: explore os produtos que podem comprar e adicione-os ao carrinho.
- Carrinho: veja um resumo de todos os itens no carrinho e faça a gestão destes itens; remover ou alterar a quantidade de cada item.
Com uma compreensão da aplicação e das respetivas funcionalidades, irá aprender a implementar a aplicação para Serviço de Aplicações do Azure com GitHub Actions, as CLIs do .NET e do Azure e o Azure Bicep. Além disso, irá aprender a configurar a rede virtual para a aplicação no Azure.
Neste tutorial, ficará a saber como:
- Implementar uma aplicação orleans para Serviço de Aplicações do Azure
- Automatizar a implementação com o GitHub Actions e o Azure Bicep
- Configurar a rede virtual para a aplicação no Azure
Pré-requisitos
- Uma conta do GitHub
- Ler uma introdução a Orleans
- O SDK .NET 7
- CLI do Azure
- Um ambiente de desenvolvimento integrado do .NET (IDE)
- Não se sinta à vontade para utilizar o Visual Studio ou o Visual Studio Code
Executar a aplicação localmente
Para executar a aplicação localmente, fork the Azure Samples: Orleans Cluster on Serviço de Aplicações do Azure repository and clone it to your local machine. Depois de clonada, abra a solução num IDE à sua escolha. Se estiver a utilizar o Visual Studio, clique com o botão direito do rato no projeto Orleans.ShoppingCart.Silo e selecione Definir Como Projeto de Arranque e, em seguida, execute a aplicação. Caso contrário, pode executar a aplicação com o seguinte comando da CLI de .NET:
dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj
Para obter mais informações, consulte Executar dotnet. Com a aplicação em execução, pode navegar e pode testar as respetivas capacidades. Todas as funcionalidades da aplicação ao executar localmente dependem da persistência dentro da memória, do clustering local e utiliza o pacote NuGet Bogus para gerar produtos falsos. Pare a aplicação selecionando a opção Parar Depuração no Visual Studio ou premindo Ctrl+C na CLI .NET.
Dentro da aplicação do carrinho de compras
Orleans é uma arquitetura fiável e dimensionável para a criação de aplicações distribuídas. Para este tutorial, vai implementar uma aplicação de carrinho de compras simples criada com Orleans para Serviço de Aplicações do Azure. A aplicação expõe a capacidade de gerir o inventário, adicionar e remover itens num carrinho e comprar produtos disponíveis. O cliente é criado com o Blazor com um modelo de alojamento de servidor. A aplicação é arquiteta da seguinte forma:
O diagrama anterior mostra que o cliente é a aplicação Blazor do lado do servidor. É composto por vários serviços que consomem um grão de Orleans correspondente. Cada serviço emparelha com um grão de Orleans da seguinte forma:
InventoryService
: consome o local onde oIInventoryGrain
inventário é particionado por categoria de produto.ProductService
: consome oIProductGrain
local em que um único produto está amarrado a uma única instância de grão porId
.ShoppingCartService
: consome oIShoppingCartGrain
local em que um único utilizador tem apenas uma única instância de carrinho de compras, independentemente de consumir clientes.
A solução contém três projetos:
Orleans.ShoppingCart.Abstractions
: uma biblioteca de classes que define os modelos e as interfaces da aplicação.Orleans.ShoppingCart.Grains
: uma biblioteca de classes que define os grãos que implementam a lógica de negócio da aplicação.Orleans.ShoppingCart.Silos
: uma aplicação Blazor do lado do servidor que aloja o silo orleans.
A experiência de utilizador do cliente
A aplicação cliente do carrinho de compras tem várias páginas, cada uma das quais representa uma experiência de utilizador diferente. A IU da aplicação é criada com o pacote NuGet MudBlazor .
Home page
Algumas expressões simples para o utilizador compreender o objetivo da aplicação e adicionar contexto a cada item de menu de navegação.
Página de inventário da loja
Uma página que apresenta todos os produtos disponíveis para compra. Os itens podem ser adicionados ao carrinho a partir desta página.
Página do carrinho vazio
Quando não adicionou nada ao carrinho, a página compõe uma mensagem que indica que não tem itens no carrinho.
Itens adicionados ao carrinho na página de inventário da loja
Quando os itens são adicionados ao carrinho na página de inventário da loja, a aplicação apresenta uma mensagem que indica que o item foi adicionado ao carrinho.
Página de gestão de produtos
Um utilizador pode gerir o inventário a partir desta página. Os produtos podem ser adicionados, editados e removidos do inventário.
Caixa de diálogo criar nova página de gestão de produtos
Quando um utilizador clica no botão Criar novo produto , a aplicação apresenta uma caixa de diálogo que permite ao utilizador criar um novo produto.
Itens na página do carrinho
Quando os itens estiverem no carrinho, pode vê-los e alterar a respetiva quantidade e até removê-los do carrinho. É apresentado ao utilizador um resumo dos itens no carrinho e o custo total pré-imposto.
Importante
Quando esta aplicação é executada localmente, num ambiente de desenvolvimento, a aplicação utilizará clustering localhost, armazenamento dentro da memória e um silo local. Também elimina o inventário com dados falsos gerados automaticamente com o pacote NuGet Bogus . Tudo isto é intencional para demonstrar a funcionalidade.
Implementar no Serviço de Aplicações do Azure
Uma aplicação típica de Orleans consiste num cluster de processos de servidor (silos) onde os grãos vivem e um conjunto de processos de cliente, normalmente servidores Web, que recebem pedidos externos, transformam-nos em chamadas de método granulado e devolvem resultados. Por isso, a primeira coisa a fazer para executar uma aplicação orleans é iniciar um cluster de silos. Para fins de teste, um cluster pode consistir num único silo.
Nota
Para uma implementação de produção fiável, quer mais do que um silo num cluster para tolerância e dimensionamento de falhas.
Antes de implementar a aplicação, tem de criar um Grupo de Recursos do Azure (ou pode optar por utilizar um existente). Para criar um novo Grupo de Recursos do Azure, utilize um dos seguintes artigos:
Tome nota do nome do grupo de recursos que escolher, precisará dele mais tarde para implementar a aplicação.
Criar um principal de serviço
Para automatizar a implementação da aplicação, terá de criar um principal de serviço. Esta é uma conta Microsoft que tem permissão para gerir recursos do Azure em seu nome.
az ad sp create-for-rbac --sdk-auth --role Contributor \
--name "<display-name>" --scopes /subscriptions/<your-subscription-id>
As credenciais JSON criadas terão um aspeto semelhante ao seguinte, mas com valores reais para o seu cliente, subscrição e inquilino:
{
"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"
}
Copie a saída do comando para a área de transferência e avance para o passo seguinte.
Criar um segredo do GitHub
O GitHub fornece um mecanismo para criar segredos encriptados. Os segredos que criar estão disponíveis para utilização em fluxos de trabalho GitHub Actions. Verá como GitHub Actions podem ser utilizadas para automatizar a implementação da aplicação, em conjunto com o AzureBicep. Bicep é uma linguagem específica do domínio (DSL) que utiliza uma sintaxe declarativa para implementar recursos do Azure. Para obter mais informações, veja O que é o Bicep. Com a saída do passo Criar um principal de serviço , terá de criar um segredo do GitHub com o nome AZURE_CREDENTIALS
com as credenciais formatadas em JSON.
No repositório do GitHub, selecione Definições Segredos>>Criar um novo segredo. Introduza o nome AZURE_CREDENTIALS
e cole as credenciais JSON do passo anterior no campo Valor .
Para obter mais informações, consulte GitHub: Segredos Encriptados.
Preparar a implementação do Azure
A aplicação terá de ser empacotada para implementação. Orleans.ShoppingCart.Silos
No projeto, definimos um Target
elemento que é executado após o Publish
passo. Isto irá zipar o diretório de publicação num ficheiro desilo.zip :
<Target Name="ZipPublishOutput" AfterTargets="Publish">
<Delete Files="$(ProjectDir)\..\silo.zip" />
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>
Existem várias formas de implementar uma aplicação .NET para Serviço de Aplicações do Azure. Neste tutorial, vai utilizar o GitHub Actions, o Azure Bicep e as CLIs do .NET e do Azure. Considere o ficheiro ./github/workflows/deploy.yml na raiz do repositório do 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
O fluxo de trabalho do GitHub anterior:
- Publique a aplicação do carrinho de compras como um ficheiro zip com o comando dotnet publish .
- Inicie sessão no Azure com as credenciais do passo Criar um principal de serviço .
- Avalie o ficheiro main.bicep e inicie um grupo de implementação com az deployment group create.
- Implemente o ficheiro silo.zip para Serviço de Aplicações do Azure com az webapp deploy.
- Também está configurada uma implementação adicional para teste.
O fluxo de trabalho é acionado por um push para o ramo principal . Para obter mais informações, veja GitHub Actions e .NET.
Dica
Se encontrar problemas ao executar o fluxo de trabalho, poderá ter de verificar se o principal de serviço tem todos os espaços de nomes de fornecedor necessários registados. São necessários os seguintes espaços de nomes de fornecedor:
Microsoft.Web
Microsoft.Network
Microsoft.OperationalInsights
Microsoft.Insights
Microsoft.Storage
Para obter mais informações, veja Resolver erros de registo do fornecedor de recursos.
O Azure impõe restrições de nomenclatura e convenções para recursos. Tem de atualizar os valores de ficheiro deploy.yml para o seguinte:
UNIQUE_APP_NAME
AZURE_RESOURCE_GROUP_NAME
AZURE_RESOURCE_GROUP_LOCATION
Defina estes valores para o nome exclusivo da aplicação e o nome e localização do grupo de recursos do Azure.
Para obter mais informações, veja Regras de nomenclatura e restrições para recursos do Azure.
Explorar os modelos do Bicep
Quando o az deployment group create
comando for executado, avaliará o ficheiro main.bicep . Este ficheiro contém os recursos do Azure que pretende implementar. Uma forma de pensar neste passo é que aprovisiona todos os recursos para implementação.
Importante
Se estiver a utilizar o Visual Studio Code, a experiência de criação de bíceps é melhorada ao utilizar a Extensão bicep.
Existem muitos ficheiros bíceps, cada um com recursos ou módulos (coleções de recursos). O ficheiro main.bicep é o ponto de module
entrada e é composto principalmente por definições:
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
}
}
O ficheiro bicep anterior define o seguinte:
- Dois parâmetros para o nome do grupo de recursos e o nome da aplicação.
- A
storageModule
definição, que define a conta de armazenamento. - A
logsModule
definição, que define os recursos do Azure Log Analytics e do Application Insights. - O
vnet
recurso, que define a rede virtual. - A
siloModule
definição, que define o Serviço de Aplicações do Azure.
Um muito importante resource
é o da Rede Virtual. O vnet
recurso permite que o Serviço de Aplicações do Azure comunique com o cluster de Orleans.
Sempre que um module
é encontrado no ficheiro bicep, é avaliado através de outro ficheiro bicep que contém as definições de recursos. O primeiro módulo encontrado foi o storageModule
, que é definido no ficheiro 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}'
Os ficheiros bicep aceitam parâmetros, que são declarados com a param
palavra-chave. Da mesma forma, também podem declarar saídas com a output
palavra-chave. O armazenamento resource
depende do Microsoft.Storage/storageAccounts@2021-08-01
tipo e da versão. Será aprovisionado na localização do grupo de recursos, como um StorageV2
E Standard_LRS
SKU. O bíceps de armazenamento define a respetiva cadeia de ligação como um output
. Esta connectionString
ação é posteriormente utilizada pelo silo bicep para ligar à conta de armazenamento.
Em seguida, o ficheiro logs-and-insights.bicep define os recursos do Azure Log Analytics e do 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
Este ficheiro bicep define os recursos do Azure Log Analytics e do Application Insights. O appInsights
recurso é um web
tipo e o logs
recurso é um PerGB2018
tipo. Tanto o appInsights
recurso como o logs
recurso são aprovisionados na localização do grupo de recursos. O appInsights
recurso está ligado ao logs
recurso através da WorkspaceResourceId
propriedade . Existem duas saídas definidas neste bíceps, utilizadas mais tarde pelo Serviço de Aplicações module
.
Por fim, o ficheiro app-service.bicep define o recurso Serviço de Aplicações do 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'
}
}
Este ficheiro bicep configura o Serviço de Aplicações do Azure como uma aplicação .NET 7. Tanto o appServicePlan
recurso como o appService
recurso são aprovisionados na localização do grupo de recursos. O appService
recurso está configurado para utilizar o S1
SKU, com uma capacidade de 1
. Além disso, o recurso está configurado para utilizar a vnetSubnetId
sub-rede e para utilizar HTTPS. Também configura a appInsightsInstrumentationKey
chave de instrumentação, a appInsightsConnectionString
cadeia de ligação e a storageConnectionString
cadeia de ligação. Estes são utilizados pela aplicação do carrinho de compras.
A extensão do Visual Studio Code para Bicep acima mencionada inclui um visualizador. Todos estes ficheiros bicep são visualizados da seguinte forma:
Ambientes de teste
A infraestrutura de implementação pode ser implementada em ambientes de teste, que são ambientes descartáveis de curta duração, centrados em testes e imutáveis. Estes ambientes são muito úteis para testar implementações antes de promovê-las para produção.
Nota
Se o seu Serviço de Aplicações estiver em execução no Windows, cada Serviço de Aplicações tem de estar no seu próprio Plano de Serviço de Aplicações separado. Em alternativa, para evitar essa configuração, pode, em vez disso, utilizar Serviço de Aplicações no Linux e este problema seria resolvido.
Resumo
À medida que atualiza o código fonte e push
muda para o main
ramo do repositório, o fluxo de trabalho deploy.yml será executado. Fornecerá os recursos definidos nos ficheiros bíceps e implementará a aplicação. A aplicação pode ser expandida para incluir novas funcionalidades, como a autenticação, ou para suportar várias instâncias da aplicação. O principal objetivo deste fluxo de trabalho é demonstrar a capacidade de aprovisionar e implementar recursos num único passo.
Além do visualizador da extensão bicep, a página portal do Azure grupo de recursos teria um aspeto semelhante ao seguinte exemplo após o aprovisionamento e implementação da aplicação: