evento
17/03, 21 - 21/03, 10
Junte-se à série meetup para criar soluções de IA escaláveis com base em casos de uso do mundo real com outros desenvolvedores e especialistas.
Registe-se agoraEste browser já não é suportado.
Atualize para o Microsoft Edge para tirar partido das mais recentes funcionalidades, atualizações de segurança e de suporte técnico.
Neste artigo, você aprenderá sobre os vários padrões para configurar e criar um Host Genérico .NET disponível no pacote NuGet Microsoft.Extensions.Hosting . O Host Genérico .NET é responsável pela inicialização do aplicativo e pelo gerenciamento do tempo de vida. Os modelos do Serviço de Trabalho criam um Host Genérico .NET, HostApplicationBuilder. O Host Genérico pode ser usado com outros tipos de aplicativos .NET, como aplicativos de console.
Um host é um objeto que encapsula os recursos e a funcionalidade de tempo de vida de um aplicativo, como:
IHostedService
ImplementaçõesQuando um host é iniciado, ele chama IHostedService.StartAsync cada implementação de IHostedService registrado na coleção de serviços hospedados do contêiner de serviço. Em um aplicativo de serviço de trabalho, todas as IHostedService
implementações que contêm BackgroundService instâncias têm seus BackgroundService.ExecuteAsync métodos chamados.
A principal razão para incluir todos os recursos interdependentes do aplicativo em um objeto é o gerenciamento do tempo de vida: controle sobre a inicialização do aplicativo e desligamento normal.
O host é normalmente configurado, criado e executado por código na Program
classe. O Main
método:
Os modelos do .NET Worker Service geram o seguinte código para criar um host genérico:
using Example.WorkerService;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
IHost host = builder.Build();
host.Run();
Para obter mais informações sobre os Serviços do Trabalhador, consulte Serviços do Trabalhador no .NET.
O CreateApplicationBuilder método:
DOTNET_
.Development
ambiente.Development
.O HostApplicationBuilder.Services é um Microsoft.Extensions.DependencyInjection.IServiceCollection exemplo. Esses serviços são usados para criar um IServiceProvider que é usado com injeção de dependência para resolver os serviços registrados.
Quando você liga para um IHostBuilder.Build() ou HostApplicationBuilder.Build(), os seguintes serviços são registrados automaticamente:
Se você estiver criando para a Web ou escrevendo um aplicativo distribuído, talvez seja necessário usar um construtor de host diferente. Considere a seguinte lista de construtores de host adicionais:
IWebHost
. Para obter mais informações, consulte ASP.NET host principal.Injete o IHostApplicationLifetime serviço em qualquer classe para lidar com tarefas pós-inicialização e de desligamento normal. Três propriedades na interface são tokens de cancelamento usados para registrar métodos de manipulador de eventos de início de aplicativo e parada de aplicativo. A interface também inclui um StopApplication() método.
O exemplo a seguir é uma IHostedService implementação e IHostedLifecycleService que registra IHostApplicationLifetime
eventos:
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace AppLifetime.Example;
public sealed class ExampleHostedService : IHostedService, IHostedLifecycleService
{
private readonly ILogger _logger;
public ExampleHostedService(
ILogger<ExampleHostedService> logger,
IHostApplicationLifetime appLifetime)
{
_logger = logger;
appLifetime.ApplicationStarted.Register(OnStarted);
appLifetime.ApplicationStopping.Register(OnStopping);
appLifetime.ApplicationStopped.Register(OnStopped);
}
Task IHostedLifecycleService.StartingAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("1. StartingAsync has been called.");
return Task.CompletedTask;
}
Task IHostedService.StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("2. StartAsync has been called.");
return Task.CompletedTask;
}
Task IHostedLifecycleService.StartedAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("3. StartedAsync has been called.");
return Task.CompletedTask;
}
private void OnStarted()
{
_logger.LogInformation("4. OnStarted has been called.");
}
private void OnStopping()
{
_logger.LogInformation("5. OnStopping has been called.");
}
Task IHostedLifecycleService.StoppingAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("6. StoppingAsync has been called.");
return Task.CompletedTask;
}
Task IHostedService.StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("7. StopAsync has been called.");
return Task.CompletedTask;
}
Task IHostedLifecycleService.StoppedAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("8. StoppedAsync has been called.");
return Task.CompletedTask;
}
private void OnStopped()
{
_logger.LogInformation("9. OnStopped has been called.");
}
}
O modelo Serviço de Trabalho pode ser modificado para adicionar a ExampleHostedService
implementação:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using AppLifetime.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<ExampleHostedService>();
using IHost host = builder.Build();
await host.RunAsync();
O aplicativo gravaria a seguinte saída de exemplo:
// Sample output:
// info: AppLifetime.Example.ExampleHostedService[0]
// 1.StartingAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 2.StartAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 3.StartedAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 4.OnStarted has been called.
// info: Microsoft.Hosting.Lifetime[0]
// Application started. Press Ctrl+C to shut down.
// info: Microsoft.Hosting.Lifetime[0]
// Hosting environment: Production
// info: Microsoft.Hosting.Lifetime[0]
// Content root path: ..\app-lifetime\bin\Debug\net8.0
// info: AppLifetime.Example.ExampleHostedService[0]
// 5.OnStopping has been called.
// info: Microsoft.Hosting.Lifetime[0]
// Application is shutting down...
// info: AppLifetime.Example.ExampleHostedService[0]
// 6.StoppingAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 7.StopAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 8.StoppedAsync has been called.
// info: AppLifetime.Example.ExampleHostedService[0]
// 9.OnStopped has been called.
A saída mostra a ordem de todos os vários eventos do ciclo de vida:
IHostedLifecycleService.StartingAsync
IHostedService.StartAsync
IHostedLifecycleService.StartedAsync
IHostApplicationLifetime.ApplicationStarted
Quando o aplicativo é interrompido, por exemplo, com Ctrl+C, os seguintes eventos são gerados:
IHostApplicationLifetime.ApplicationStopping
IHostedLifecycleService.StoppingAsync
IHostedService.StopAsync
IHostedLifecycleService.StoppedAsync
IHostApplicationLifetime.ApplicationStopped
A IHostLifetime implementação controla quando o host é iniciado e quando ele para. É utilizada a última implementação registada.
Microsoft.Extensions.Hosting.Internal.ConsoleLifetime
é a implementação padrão IHostLifetime
. Para obter mais informações sobre a mecânica de tempo de vida do desligamento, consulte Desligamento do host.
A IHostLifetime
interface expõe um IHostLifetime.WaitForStartAsync método, que é chamado no início do qual irá esperar até que esteja completo antes de IHost.StartAsync
continuar. Isso pode ser usado para atrasar a inicialização até ser sinalizado por um evento externo.
Além disso, a IHostLifetime
interface expõe um IHostLifetime.StopAsync método, que é chamado de para indicar que o host está parando e é hora de IHost.StopAsync
desligar.
Injete o IHostEnvironment serviço em uma classe para obter informações sobre as seguintes configurações:
Além disso, o IHostEnvironment
serviço expõe a capacidade de avaliar o ambiente com a ajuda destes métodos de extensão:
A configuração do host é usada para configurar as propriedades da implementação IHostEnvironment .
A configuração do host está disponível na HostApplicationBuilderSettings.Configuration propriedade e a implementação do ambiente está disponível na IHostApplicationBuilder.Environment propriedade. Para configurar o host, acesse a Configuration
propriedade e chame qualquer um dos métodos de extensão disponíveis.
Para adicionar a configuração do host, considere o seguinte exemplo:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
HostApplicationBuilderSettings settings = new()
{
Args = args,
Configuration = new ConfigurationManager(),
ContentRootPath = Directory.GetCurrentDirectory(),
};
settings.Configuration.AddJsonFile("hostsettings.json", optional: true);
settings.Configuration.AddEnvironmentVariables(prefix: "PREFIX_");
settings.Configuration.AddCommandLine(args);
HostApplicationBuilder builder = Host.CreateApplicationBuilder(settings);
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
O código anterior:
PREFIX_
.A configuração do aplicativo é criada chamando ConfigureAppConfiguration um IHostApplicationBuilderarquivo . A propriedade pública IHostApplicationBuilder.Configuration permite aos consumidores ler e alterar a configuração existente usando métodos de extensão disponíveis.
Para obter mais informações, consulte Configuração no .NET.
Há várias maneiras pelas quais um processo hospedado é interrompido. Mais comumente, um processo hospedado pode ser interrompido das seguintes maneiras:
Main
a conclusão.O código de hospedagem não é responsável por lidar com esses cenários. O proprietário do processo precisa lidar com eles da mesma forma que qualquer outro aplicativo. Há várias outras maneiras pelas quais um processo de serviço hospedado pode ser interrompido:
ConsoleLifetime
for usado (UseConsoleLifetime), ele escuta os seguintes sinais e tenta parar o host graciosamente.
A lógica de hospedagem interna lida com esses cenários, especificamente a ConsoleLifetime
classe.
ConsoleLifetime
tenta lidar com os sinais de "desligamento" SIGINT, SIGQUIT e SIGTERM para permitir uma saída graciosa para o aplicativo.
Antes do .NET 6, não havia uma maneira de o código .NET lidar graciosamente com o SIGTERM. Para contornar esta limitação, ConsoleLifetime
subscreveria o System.AppDomain.ProcessExit. Quando ProcessExit
era levantado, ConsoleLifetime
sinalizava ao host para parar e bloquear o ProcessExit
thread, esperando que o host parasse.
O manipulador de saída do processo permitiria que o código de limpeza no aplicativo fosse executado — por exemplo, IHost.StopAsync e codificasse depois HostingAbstractionsHostExtensions.Run no Main
método.
No entanto, havia outros problemas com esta abordagem, porque o SIGTERM não era a única maneira ProcessExit
de ser levantado. SIGTERM também é gerado quando o código do aplicativo chama Environment.Exit
.
Environment.Exit
não é uma maneira graciosa de encerrar um processo no Microsoft.Extensions.Hosting
modelo de aplicativo. Ele levanta o ProcessExit
evento e, em seguida, sai do processo. O final do Main
método não é executado. Os threads em segundo plano e em primeiro plano são encerrados e finally
os blocos não são executados.
Uma vez que ConsoleLifetime
bloqueado ProcessExit
enquanto aguardava o desligamento do host, esse comportamento levou a bloqueios de Environment.Exit
também blocos aguardando a chamada para ProcessExit
. Além disso, uma vez que a manipulação SIGTERM estava tentando encerrar graciosamente o processo, ConsoleLifetime
definiria o ExitCode para 0
, que clobbered o código de saída do usuário passado para Environment.Exit
.
No .NET 6, os sinais POSIX são suportados e manipulados. O ConsoleLifetime
manipula SIGTERM graciosamente, e não se envolve mais quando Environment.Exit
é invocado.
Sugestão
Para o .NET 6+, ConsoleLifetime
não tem mais lógica para lidar com o cenário Environment.Exit
. Os aplicativos que chamam Environment.Exit
e precisam executar a lógica de limpeza podem se inscrever.ProcessExit
A hospedagem não tentará mais parar o host nesses cenários.
Se o seu aplicativo usa hospedagem e você deseja parar o host normalmente, você pode chamar IHostApplicationLifetime.StopApplication em vez de Environment.Exit
.
O diagrama de sequência a seguir mostra como os sinais são tratados internamente no código de hospedagem. A maioria dos usuários não precisa entender esse processo. Mas para desenvolvedores que precisam de um entendimento profundo, um bom visual pode ajudá-lo a começar.
Depois que o host for iniciado, quando um usuário chamar Run
ou WaitForShutdown
, um manipulador será registrado para IApplicationLifetime.ApplicationStopping. A execução é pausada em WaitForShutdown
, aguardando que o ApplicationStopping
evento seja levantado. O Main
método não retorna imediatamente e o aplicativo permanece em execução até Run
ou WaitForShutdown
retorna.
Quando um sinal é enviado para o processo, ele inicia a seguinte sequência:
ConsoleLifetime
para ApplicationLifetime
elevar o ApplicationStopping
evento. Isso sinaliza WaitForShutdownAsync
para desbloquear o código de Main
execução. Enquanto isso, o manipulador de sinal POSIX retorna com Cancel = true
desde que o sinal POSIX foi manipulado.Main
código de execução começa a ser executado novamente e informa ao host para StopAsync()
, que, por sua vez, interrompe todos os serviços hospedados e gera quaisquer outros eventos interrompidos.WaitForShutdown
sai, permitindo que qualquer código de limpeza de aplicativo seja executado e que o método saia Main
normalmente.Existem vários outros cenários comuns em que o desligamento normal funciona no Kestrel para os protocolos HTTP/1.1 e HTTP/2, e como você pode configurá-lo em diferentes ambientes com um balanceador de carga para drenar o tráfego sem problemas. Embora a configuração do servidor Web esteja além do escopo deste artigo, você pode encontrar mais informações sobre Configurar opções para a documentação do servidor Web ASP.NET Core Kestrel.
Quando o Host recebe um sinal de desligamento (por exemplo, Ctrl+C ou StopAsync
), ele notifica o aplicativo sinalizando ApplicationStopping. Você deve se inscrever neste evento se tiver alguma operação de longa duração que precise terminar normalmente.
Em seguida, o Host chama IServer.StopAsync com um tempo limite de desligamento que você pode configurar (padrão 30s). Kestrel (e Http.Sys) fecham suas ligações de porta e param de aceitar novas conexões. Eles também dizem às conexões atuais para parar de processar novas solicitações. Para HTTP/2 e HTTP/3, uma mensagem preliminar GOAWAY
é enviada ao cliente. Para HTTP/1.1, eles param o loop de conexão porque as solicitações são processadas em ordem. O IIS se comporta de forma diferente, rejeitando novas solicitações com um código de status 503.
As solicitações ativas têm até o tempo limite de desligamento para serem concluídas. Se todos estiverem concluídos antes do tempo limite, o servidor devolverá o controle ao host mais cedo. Se o tempo limite expirar, as conexões e solicitações pendentes serão abortadas com força, o que pode causar erros nos logs e nos clientes.
Para garantir uma transição suave de clientes para um novo destino ao trabalhar com um balanceador de carga, você pode seguir estas etapas:
Comentários do .NET
O .NET é um projeto código aberto. Selecione um link para fornecer comentários:
evento
17/03, 21 - 21/03, 10
Junte-se à série meetup para criar soluções de IA escaláveis com base em casos de uso do mundo real com outros desenvolvedores e especialistas.
Registe-se agoraFormação
Percurso de aprendizagem
Executar aplicações de computação de alto desempenho (HPC) no Azure - Training
O Azure HPC é um recurso de nuvem criado especificamente para a carga de trabalho HPC & AI, usando processadores de ponta e interconexão InfiniBand de classe HPC, para oferecer o melhor desempenho, escalabilidade e valor de aplicativos. O Azure HPC permite que os utilizadores desbloqueiem a inovação, a produtividade e a agilidade empresarial, através de uma gama altamente disponível de tecnologias de HPC ou IA que podem ser alocadas dinamicamente à medida que as suas necessidades empresariais e técnicas mud