Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
Importante
Estas informações referem-se a um produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado comercialmente. A Microsoft não oferece garantias, expressas ou implícitas, em relação às informações fornecidas aqui.
Para a versão atual, consulte a versão .NET 9 deste artigo.
Este artigo explica como hospedar e implantar aplicativos Blazor do lado do servidor (aplicativosBlazor Web Apps e Blazor Server) usando o ASP.NET Core.
Valores de configuração do host
Os aplicativos Blazor do lado do servidor podem aceitar valores de configuração de Host Genérico.
Implantação
Usando um modelo de hospedagem do lado do servidor, Blazor é executado no servidor de dentro de um aplicativo ASP.NET Core. Atualizações da interface do usuário, manipulação de eventos e chamadas JavaScript são tratadas por meio de uma conexão SignalR.
É necessário um servidor Web capaz de hospedar um aplicativo ASP.NET Core. O Visual Studio inclui um modelo de projeto de aplicativo do lado do servidor. Para mais informações sobre os modelos de projeto Blazor, consulte a estrutura do projeto ASP.NET Core Blazor.
Publique uma aplicação na configuração Release e implante o conteúdo da pasta bin/Release/{TARGET FRAMEWORK}/publish
, onde o espaço reservado {TARGET FRAMEWORK}
é o framework de destino.
Escalabilidade
Ao considerar a escalabilidade de um único servidor (scale-up), a memória disponível para um aplicativo é provavelmente o primeiro recurso que o aplicativo esgota à medida que as demandas do usuário aumentam. A memória disponível no servidor afeta o:
- Número de circuitos ativos que um servidor pode suportar.
- Latência da interface do usuário no cliente.
Para obter orientação sobre como criar aplicativos Blazor do lado do servidor seguros e escaláveis, consulte os seguintes recursos:
- Diretrizes de mitigação de ameaças para ASP.NET Core Blazor renderização estática no lado do servidor
- Orientações para mitigação de ameaças em ASP.NET Core Blazor renderização interativa do lado do servidor
Cada circuito usa aproximadamente 250 KB de memória para uma aplicação mínima ao estilo Hello World. O tamanho de um circuito depende do código do aplicativo e dos requisitos de manutenção de estado associados a cada componente. Recomendamos que você meça as demandas de recursos durante o desenvolvimento para seu aplicativo e infraestrutura, mas a linha de base a seguir pode ser um ponto de partida no planejamento de sua meta de implantação: Se você espera que seu aplicativo ofereça suporte a 5.000 usuários simultâneos, considere orçar pelo menos 1,3 GB de memória do servidor para o aplicativo (ou ~273 KB por usuário).
SignalR configuração
As condições de hospedagem e dimensionamento de SignalRdo aplicam-se a aplicativos Blazor que usam SignalR.
Para obter mais informações sobre SignalR em aplicativos Blazor, incluindo diretrizes de configuração, consulte ASP.NET Core BlazorSignalR guidance.
Transportes
Blazor funciona melhor ao usar WebSockets como transporte de SignalR devido à menor latência, maior fiabilidade e melhor segurança. Sondagem Longa é utilizada por SignalR quando WebSockets não está disponível ou quando a aplicação está explicitamente configurada para usar Sondagem Longa.
Um aviso de console será exibido se for utilizado o Long Polling.
Falhou ao conectar via WebSockets, utilizando o transporte de reserva Long Polling. Isso pode ser devido a uma VPN ou proxy bloqueando a conexão.
Falhas globais de implantação e conexão
Recomendações para implantações globais em data centers geográficos:
- Implante o aplicativo nas regiões onde a maioria dos usuários reside.
- Leve em consideração o aumento da latência para o tráfego entre continentes. Para controlar a aparência da interface do usuário de reconexão, consulte ASP.NET Core BlazorSignalR guidance.
- Considere usar o Azure SignalR Service.
Serviço de Aplicações do Azure
A hospedagem no Serviço de Aplicações do Azure requer a configuração de WebSockets e afinidade de sessão, também conhecida como afinidade ARR (Application Request Routing).
Habilite o seguinte para o registro do aplicativo no Serviço de Aplicativo do Azure:
- WebSockets para permitir que o transporte WebSockets funcione. A configuração padrão é Desativado.
- Afinidade de sessão para direcionar as solicitações de um utilizador de volta para a mesma instância do App Service. A configuração padrão é On.
- No portal do Azure, navegue até a aplicação web em Serviços de Aplicações.
- Abra Configurações>Configurações.
- Definir soquetes da Web para Ativado.
- Verifique se a afinidade de sessão está definida como On.
Azure SignalR Serviço
O SignalR Serviço Azure funciona em conjunto com o hub SignalR da aplicação para dimensionar uma aplicação do lado do servidor para um grande número de conexões simultâneas. Além disso, o alcance global do serviço e os data centers de alto desempenho ajudam significativamente na redução da latência devido à geografia.
O serviço não é necessário para Blazor aplicativos hospedados no Serviço de Aplicativo do Azure ou nos Aplicativos de Contêiner do Azure, mas pode ser útil em outros ambientes de hospedagem:
- Para permitir a expansão da conexão.
- Gerir a distribuição global.
O Serviço SignalR do Azure com SDK v1.26.1 ou posterior dá suporte a SignalR de reconexão com monitoração de estado (WithStatefulReconnect).
Caso o aplicativo use Sondagem Longa ou volte para Sondagem Longa em vez de WebSockets, talvez seja necessário configurar o intervalo máximo de sondagem (MaxPollIntervalInSeconds
, padrão: 5 segundos, limite: 1-300 segundos), que define o intervalo máximo de sondagem permitido para conexões de Sondagem Longa no Serviço de SignalR do Azure. Se a próxima solicitação de sondagem não chegar dentro do intervalo máximo de sondagem, o serviço fechará a conexão do cliente.
Para obter orientação sobre como adicionar o serviço como uma dependência a uma implantação de produção, consulte Publicar um aplicativo ASP.NET Core SignalR no Serviço de Aplicativo do Azure.
Para obter mais informações, consulte:
- Serviço do Azure SignalR
- O que é o Azure SignalR Service?
- ASP.NET Core SignalR hospedagem e dimensionamento de produção
- Publicar um aplicativo ASP.NET Core SignalR no Serviço de Aplicativo do Azure
Aplicativos de contêiner do Azure
Para uma análise aprofundada do dimensionamento de apps do lado do servidor no serviço de Aplicativos de Contentor do Azure, consulte Blazor. O tutorial explica como criar e integrar os serviços necessários para hospedar aplicativos em Aplicativos de Contêiner do Azure. As etapas básicas também são fornecidas nesta seção.
Configure o serviço Aplicativos de Contêiner do Azure para afinidade de sessão seguindo as orientações em Afinidade de Sessão em Aplicativos de Contêiner do Azure (documentação do Azure).
O serviço ASP.NET Core Data Protection (DP) deve ser configurado para manter chaves em um local centralizado que todas as instâncias de contêiner possam acessar. As chaves podem ser armazenadas no Armazenamento de Blobs do Azure e protegidas com o Cofre de Chaves do Azure. O serviço DP usa as chaves para desserializar os componentes Razor. Para configurar o serviço de DP para usar o Armazenamento de Blobs do Azure e o Cofre de Chaves do Azure, faça referência aos seguintes pacotes NuGet:
-
Azure.Identity
: Fornece classes para trabalhar com os serviços de gerenciamento de identidade e acesso do Azure. -
Microsoft.Extensions.Azure
: Fornece métodos de extensão úteis para executar configurações principais do Azure. -
Azure.Extensions.AspNetCore.DataProtection.Blobs
: Permite armazenar chaves de Proteção de Dados do ASP.NET Core no Armazenamento de Blobs do Azure para que as chaves possam ser partilhadas entre várias instâncias de uma aplicação web. -
Azure.Extensions.AspNetCore.DataProtection.Keys
: Permite proteger chaves em repouso usando o recurso Criptografia/encapsulamento de chaves do Cofre de Chaves do Azure.
Observação
Para obter orientação sobre como adicionar pacotes a aplicativos .NET, consulte os artigos na seção Instalar e gerenciar pacotes em Workflow de utilização de pacotes (documentação do NuGet). Confirme as versões corretas do pacote em NuGet.org.
-
Atualize
Program.cs
com o seguinte código destacado:using Azure.Identity; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Azure; var builder = WebApplication.CreateBuilder(args); var BlobStorageUri = builder.Configuration["AzureURIs:BlobStorage"]; var KeyVaultURI = builder.Configuration["AzureURIs:KeyVault"]; builder.Services.AddRazorPages(); builder.Services.AddHttpClient(); builder.Services.AddServerSideBlazor(); builder.Services.AddAzureClientsCore(); builder.Services.AddDataProtection() .PersistKeysToAzureBlobStorage(new Uri(BlobStorageUri), new DefaultAzureCredential()) .ProtectKeysWithAzureKeyVault(new Uri(KeyVaultURI), new DefaultAzureCredential()); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
As alterações anteriores permitem que o aplicativo gerencie o serviço de PD usando uma arquitetura centralizada e escalável. DefaultAzureCredential descobre a identidade gerida do aplicativo de contêiner após o código ser implementado no Azure e usa-a para se conectar ao armazenamento de blobs e ao cofre de chaves do aplicativo.
Para criar a identidade gerenciada do aplicativo contêiner e conceder-lhe acesso ao armazenamento de blob e a um cofre de chaves, conclua as seguintes etapas:
- No Portal do Azure, navegue até a página de visão geral do aplicativo de contêiner.
- Selecione Service Connector na navegação à esquerda.
- Selecione e depois Criar na navegação superior.
- No menu de expansão Criar conexão, insira os seguintes valores:
- Container: Selecione o aplicativo de contêiner que você criou para hospedar seu aplicativo.
- Tipo de serviço: Selecione Blob Storage.
- Subscrição: Selecione a subscrição proprietária da aplicação do contentor.
-
Nome da conexão: Digite um nome de
scalablerazorstorage
. - Tipo de cliente: Selecione .NET e, em seguida, selecione Avançar.
- Selecione Identidade gerida atribuída pelo sistema e selecione Avançar.
- Use as configurações de rede padrão e selecione Avançar.
- Quando Azure validar as configurações, selecione Criar.
Repita as configurações anteriores para o cofre de chaves. Selecione o serviço de cofre de chaves apropriado e a chave na guia Noções básicas.
Observação
O exemplo anterior usa DefaultAzureCredential para simplificar a autenticação ao desenvolver aplicativos que implantam no Azure combinando credenciais usadas em ambientes de hospedagem do Azure com credenciais usadas no desenvolvimento local. Ao passar para a produção, uma alternativa é uma escolha melhor, como ManagedIdentityCredential. Para obter mais informações, consulte Autenticar aplicativos .NET hospedados no Azure em recursos do Azure usando uma identidade gerenciada atribuída ao sistema.
IIS
Ao usar o IIS, habilite:
Para obter mais informações, consulte as orientações e os links cruzados de recursos externos do IIS em Publicar um aplicativo ASP.NET Core no IIS.
Kubernetes
Crie uma definição de ingresso com as seguintes anotações do Kubernetes para afinidade de sessão:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: <ingress-name>
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "affinity"
nginx.ingress.kubernetes.io/session-cookie-expires: "14400"
nginx.ingress.kubernetes.io/session-cookie-max-age: "14400"
Linux com Nginx
Siga as orientações para um aplicativo ASP.NET Core SignalR com as seguintes alterações:
- Altere o caminho
location
de/hubroute
(location /hubroute { ... }
) para o caminho raiz/
(location / { ... }
). - Remova a configuração para buffer de proxy (
proxy_buffering off;
) porque a configuração só se aplica a Eventos Enviados pelo Servidor (SSE), que não são relevantes para as interações cliente-servidor do Blazor aplicativo.
Para obter mais informações e orientações de configuração, consulte os seguintes recursos:
- ASP.NET Core SignalR hospedagem e dimensionamento de produção
- Alojamento do ASP.NET Core no Linux com Nginx
- Configurar o ASP.NET Core para trabalhar com servidores proxy e balanceadores de carga
- NGINX como um proxy WebSocket
- Proxyização de WebSocket
- Consulte desenvolvedores em fóruns de suporte que não sejam da Microsoft:
Linux com Apache
Para hospedar um aplicativo Blazor atrás do Apache no Linux, configure ProxyPass
para tráfego HTTP e WebSockets.
No exemplo a seguir:
- Kestrel servidor está em execução na máquina host.
- O aplicativo escuta o tráfego na porta 5000.
ProxyPreserveHost On
ProxyPassMatch ^/_blazor/(.*) http://localhost:5000/_blazor/$1
ProxyPass /_blazor ws://localhost:5000/_blazor
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
Habilite os seguintes módulos:
a2enmod proxy
a2enmod proxy_wstunnel
Verifique se há erros de WebSockets no console do navegador. Exemplos de erros:
- O Firefox não consegue estabelecer uma conexão com o servidor em ws://the-domain-name.tld/_blazor?id=XXX
- Erro: Falha ao iniciar o transporte 'WebSockets': Erro: Houve um erro com o transporte.
- Erro: Falha ao iniciar o transporte 'LongPolling': TypeError: this.transport não está definido
- Erro: Não é possível conectar-se ao servidor com qualquer um dos transportes disponíveis. WebSockets falharam
- Erro: Não é possível enviar dados se a conexão não estiver no estado 'Conectado'.
Para obter mais informações e orientações de configuração, consulte os seguintes recursos:
- Configurar o ASP.NET Core para trabalhar com servidores proxy e balanceadores de carga
- Documentação do Apache
- Consulte desenvolvedores em fóruns de suporte que não sejam da Microsoft:
Meça a latência da rede
JS interoperabilidade podem ser usados para medir a latência da rede, como o exemplo a seguir demonstra.
MeasureLatency.razor
:
@inject IJSRuntime JS
<h2>Measure Latency</h2>
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
@inject IJSRuntime JS
<h2>Measure Latency</h2>
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
@inject IJSRuntime JS
<h2>Measure Latency</h2>
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
@inject IJSRuntime JS
<h2>Measure Latency</h2>
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
@inject IJSRuntime JS
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
Para uma experiência de interface do usuário razoável, recomendamos uma latência sustentada da interface do usuário de 250 ms ou menos.