Eventos
19 de nov., 23 - 21 de nov., 23
Participe de sessões online no Microsoft Ignite criadas para expandir suas habilidades e ajudá-lo a lidar com os problemas complexos de hoje.
Registrar agoraNão há mais suporte para esse navegador.
Atualize o Microsoft Edge para aproveitar os recursos, o suporte técnico e as atualizações de segurança mais recentes.
Por Tom Dykstra
Os aplicativos podem aplicar limites de tempo limite seletivamente às solicitações. O servidores do ASP.NET Core não fazem isso por padrão, pois os tempos de processamento de solicitação variam amplamente por cenário. Por exemplo, WebSockets, arquivos estáticos e APIs caras de chamada exigiriam um limite de tempo limite diferente. Portanto, o ASP.NET Core fornece middleware que configura tempos limite por ponto de extremidade, bem como um tempo limite global.
Quando um limite de tempo limite é atingido, um CancellationToken em HttpContext.RequestAborted tem IsCancellationRequested definido como true
. Abort() não é chamado automaticamente na solicitação, portanto, o aplicativo ainda pode produzir uma resposta de êxito ou falha. O comportamento padrão se o aplicativo não tratar a exceção e produzir uma resposta é retornar o código de status 504.
Esse artigo explica como configurar o middleware de tempo limite. O middleware de tempo limite pode ser usado em todos os tipos de aplicativos ASP.NET Core: API mínima, API Web com controladores, MVC e Páginas do Razor. O aplicativo de exemplo é uma API Mínima, mas todos os recursos de cache ilustrados por ele também têm suporte nos outros tipos de aplicativo.
Os tempos limite de solicitação estão no namespace Microsoft.AspNetCore.Http.Timeouts.
Observação: quando um aplicativo está em execução no modo de depuração, o middleware de tempo limite não é disparado. Esse comportamento semelhante aos tempos limite Kestrel. Para testar tempos limite, execute o aplicativo sem o depurador anexado.
Adicione o middleware de tempo limite de solicitação à coleção de serviços chamando AddRequestTimeouts.
Adicione o middleware ao pipeline de processamento de solicitação chamando UseRequestTimeouts.
Observação
UseRequestTimeouts
deve ser chamado após UseRouting
.Adicionar o middleware ao aplicativo não inicia automaticamente o disparo de tempos limite. Os limites de tempo limite precisam ser configurados explicitamente.
Para aplicativos de API mínima, configure um ponto de extremidade para o tempo limite chamando WithRequestTimeout ou aplicando o atributo [RequestTimeout]
, conforme mostrado nos exemplos a seguir:
using Microsoft.AspNetCore.Http.Timeouts;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRequestTimeouts();
var app = builder.Build();
app.UseRequestTimeouts();
app.MapGet("/", async (HttpContext context) => {
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch (TaskCanceledException)
{
return Results.Content("Timeout!", "text/plain");
}
return Results.Content("No timeout!", "text/plain");
}).WithRequestTimeout(TimeSpan.FromSeconds(2));
// Returns "Timeout!"
app.MapGet("/attribute",
[RequestTimeout(milliseconds: 2000)] async (HttpContext context) => {
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch (TaskCanceledException)
{
return Results.Content("Timeout!", "text/plain");
}
return Results.Content("No timeout!", "text/plain");
});
// Returns "Timeout!"
app.Run();
Para aplicativos com controladores, aplique o atributo [RequestTimeout]
ao método de ação. Para aplicativos de Páginas do Razor, aplique o atributo à classe de página Razor.
Crie políticas nomeadas para especificar a configuração de tempo limite que se aplica a vários pontos de extremidade. Adicione uma política chamando AddPolicy:
builder.Services.AddRequestTimeouts(options => {
options.DefaultPolicy =
new RequestTimeoutPolicy { Timeout = TimeSpan.FromMilliseconds(1500) };
options.AddPolicy("MyPolicy", TimeSpan.FromSeconds(2));
});
Um tempo limite pode ser especificado para um ponto de extremidade pelo nome da política:
app.MapGet("/namedpolicy", async (HttpContext context) => {
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch (TaskCanceledException)
{
return Results.Content("Timeout!", "text/plain");
}
return Results.Content("No timeout!", "text/plain");
}).WithRequestTimeout("MyPolicy");
// Returns "Timeout!"
O atributo [RequestTimeout]
também pode ser usado para especificar uma política nomeada.
Especifique uma política para a configuração de tempo limite padrão global:
builder.Services.AddRequestTimeouts(options => {
options.DefaultPolicy =
new RequestTimeoutPolicy { Timeout = TimeSpan.FromMilliseconds(1500) };
options.AddPolicy("MyPolicy", TimeSpan.FromSeconds(2));
});
O tempo limite padrão se aplica a pontos de extremidade que não têm um tempo limite especificado. O código de ponto de extremidade a seguir verifica se há um tempo limite, embora não chame o método de extensão ou aplique o atributo . A configuração de tempo limite global se aplica, portanto, o código verifica se há um tempo limite:
app.MapGet("/", async (HttpContext context) => {
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch
{
return Results.Content("Timeout!", "text/plain");
}
return Results.Content("No timeout!", "text/plain");
});
// Returns "Timeout!" due to default policy.
A classe RequestTimeoutPolicy tem uma propriedade que pode definir automaticamente o código status quando um tempo limite é disparado.
builder.Services.AddRequestTimeouts(options => {
options.DefaultPolicy = new RequestTimeoutPolicy {
Timeout = TimeSpan.FromMilliseconds(1000),
TimeoutStatusCode = 503
};
options.AddPolicy("MyPolicy2", new RequestTimeoutPolicy {
Timeout = TimeSpan.FromMilliseconds(1000),
WriteTimeoutResponse = async (HttpContext context) => {
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("Timeout from MyPolicy2!");
}
});
});
app.MapGet("/", async (HttpContext context) => {
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch (TaskCanceledException)
{
throw;
}
return Results.Content("No timeout!", "text/plain");
});
// Returns status code 503 due to default policy.
A classe RequestTimeoutPolicy
tem uma propriedade WriteTimeoutResponse que pode ser usada para personalizar a resposta quando um tempo limite é disparado.
builder.Services.AddRequestTimeouts(options => {
options.DefaultPolicy = new RequestTimeoutPolicy {
Timeout = TimeSpan.FromMilliseconds(1000),
TimeoutStatusCode = 503
};
options.AddPolicy("MyPolicy2", new RequestTimeoutPolicy {
Timeout = TimeSpan.FromMilliseconds(1000),
WriteTimeoutResponse = async (HttpContext context) => {
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("Timeout from MyPolicy2!");
}
});
});
app.MapGet("/usepolicy2", async (HttpContext context) => {
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch (TaskCanceledException)
{
throw;
}
return Results.Content("No timeout!", "text/plain");
}).WithRequestTimeout("MyPolicy2");
// Returns "Timeout from MyPolicy2!" due to WriteTimeoutResponse in MyPolicy2.
Para desabilitar todos os tempos limite, incluindo o tempo limite global padrão, use o atributo [DisableRequestTimeout]
ou o método de extensão DisableRequestTimeout:
app.MapGet("/disablebyattr", [DisableRequestTimeout] async (HttpContext context) => {
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch
{
return Results.Content("Timeout!", "text/plain");
}
return Results.Content("No timeout!", "text/plain");
});
// Returns "No timeout!", ignores default timeout.
app.MapGet("/disablebyext", async (HttpContext context) => {
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch
{
return Results.Content("Timeout!", "text/plain");
}
return Results.Content("No timeout!", "text/plain");
}).DisableRequestTimeout();
// Returns "No timeout!", ignores default timeout.
Para cancelar um tempo limite que já foi iniciado, use o método DisableTimeout() em IHttpRequestTimeoutFeature. Os tempos limite não podem ser cancelados depois de expirarem.
app.MapGet("/canceltimeout", async (HttpContext context) => {
var timeoutFeature = context.Features.Get<IHttpRequestTimeoutFeature>();
timeoutFeature?.DisableTimeout();
try
{
await Task.Delay(TimeSpan.FromSeconds(10), context.RequestAborted);
}
catch (TaskCanceledException)
{
return Results.Content("Timeout!", "text/plain");
}
return Results.Content("No timeout!", "text/plain");
}).WithRequestTimeout(TimeSpan.FromSeconds(1));
// Returns "No timeout!" since the default timeout is not triggered.
Comentários do ASP.NET Core
O ASP.NET Core é um projeto código aberto. Selecione um link para fornecer comentários:
Eventos
19 de nov., 23 - 21 de nov., 23
Participe de sessões online no Microsoft Ignite criadas para expandir suas habilidades e ajudá-lo a lidar com os problemas complexos de hoje.
Registrar agora