Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo descreve as práticas recomendadas para implementar, implantar e operar uma API Web RESTful. Ele se concentra no tratamento de solicitações, desempenho, confiabilidade, publicação e monitoramento. Para obter diretrizes sobre modelagem de recursos e design de API, consulte o design da API Web.
As diretrizes arquitetônicas se aplicam a todas as linguagens e frameworks de implementação. Os exemplos de C# ilustram controladores do ASP.NET Core.
Processamento de solicitações
Considere os pontos a seguir ao implementar o código para processar solicitações.
Preservar a semântica do método HTTP e implementar a idempotência
Use GET para retornar dados de recursos e HEAD para retornar cabeçalhos de resposta sem corpo. Não use nenhum dos métodos para criar, atualizar ou excluir recursos.
GET, HEAD, PUT e DELETE devem ser idempotentes, portanto, repetir uma solicitação idêntica tem o mesmo efeito pretendido que executá-la uma vez. Por exemplo, DELETE altera o estado do recurso, mas repeti-lo não exclui recursos adicionais. A primeira solicitação DELETE pode retornar 204 (sem conteúdo), enquanto uma solicitação subsequente retorna 404 (Não encontrada).
POST e PATCH não são inerentemente idempotentes. Uma operação PATCH que define uma propriedade como um valor pode ser idempotente, mas uma que incrementa um contador não é. Documente quais operações de alteração de estado os clientes podem repetir com segurança. Se você oferecer suporte a novas tentativas para operações que não são naturalmente idempotentes, implemente e documente como o serviço impede efeitos duplicados. Para a semântica do método, consulte os métodos de requisição HTTP.
Observação
Para obter diretrizes de implementação, consulte o padrão de consumidor Idempotente. Na prática, primeiro identifique se uma operação é naturalmente idempotente. Se não estiver, aplique a idempotência artificial rastreando IDs de mensagens processadas e tratando duplicatas de forma proativa ou reativamente.
Valide os dados da requisição e controle o acesso aos campos
Defina modelos de solicitação e resposta que expõem apenas os campos no contrato de API. Mapeie esses modelos para os dados armazenados em vez de associar corpos de solicitação diretamente a entidades de banco de dados ou retornar todas as propriedades armazenadas. Impedir que os chamadores alterem as propriedades protegidas enviando campos adicionais e omitir as propriedades que eles não estão autorizados a ler. Os DTOs (objetos de transferência de dados) são uma maneira de impor essa fronteira. Para obter mais informações, consulte Impedir a postagem excessiva em ASP.NET Core.
Valide os campos obrigatórios, tipos, intervalos e regras de negócios antes de salvar as alterações. Se você oferece suporte à seleção de campos, valide os campos solicitados em relação a uma lista de permissões e às permissões do chamador antes de projetar a resposta. Aplique limites documentados à filtragem e à classificação também. Para as opções de contrato correspondentes, consulte Implementar paginação e filtragem.
Limitar os efeitos colaterais das ações POST que criam recursos
Quando uma solicitação POST cria um recurso, limite seus efeitos para esse recurso e recursos diretamente relacionados. Por exemplo, a criação de um pedido também pode atualizar o inventário e gerar informações de cobrança. Ele não deve modificar informações não relacionadas.
Evite implementar operações POST, PUT e DELETE prolixas
Evite projetar sua API com base em operações de conversação. Cada solicitação vem com sobrecarga de protocolo, rede e computação. Por exemplo, executar 100 solicitações menores em vez de uma solicitação de lote maior incorre em sobrecarga adicional no cliente, na rede e no servidor de recursos. Para cargas de trabalho que precisam de operações em massa, considere solicitações de lote limitadas em vez de muitas solicitações individuais.
- Uma solicitação GET para uma coleção pode recuperar vários recursos ao mesmo tempo.
- Uma solicitação POST pode conter os detalhes de vários novos recursos e adicioná-los todos à mesma coleção.
- Uma solicitação PUT pode substituir todo o conjunto de recursos em uma coleção.
- Uma solicitação DELETE pode remover uma coleção inteira.
Defina tamanhos máximos de lote, tamanhos de payload, tempos de execução e concorrência. Especifique se um lote é atômico ou pode ser parcialmente concluído e retorne um resultado para cada operação. Autorize e valide cada operação no lote.
Se você usar o OData, poderá usar ASP.NET Core OData para implementar solicitações em lote. Para obter mais informações, consulte ASP.NET Core visão geral do OData.
Siga a especificação de HTTP ao enviar uma resposta
Retorne o código de status HTTP apropriado, os cabeçalhos e o formato do corpo para que os clientes possam interpretar e manipular a resposta.
Por exemplo, uma operação POST que cria um recurso de forma síncrona deve retornar 201 (Criado) e identificar o recurso no cabeçalho de resposta Location. Uma operação que aceita trabalho para processamento posterior pode retornar 202 (Aceito), mas essa resposta não indica que o trabalho foi bem-sucedido. Não inclua um corpo de resposta com 204 (Sem Conteúdo) ou 304 (Não Modificado). Para obter mais informações, consulte os métodos de solicitação HTTP.
Ofereça suporte à negociação de conteúdo
Um corpo de resposta pode conter dados em formatos diferentes, como JSON ou XML. Os clientes podem usar o cabeçalho da solicitação Accept para especificar tipos de mídia compatíveis. Por exemplo, um cliente que solicita uma imagem pode especificar image/jpeg, image/gif, image/png. Retorne uma representação compatível e identifique seu tipo de mídia no cabeçalho de resposta Content-Type.
Se o cliente não especificar um cabeçalho Accept, use um formato padrão documentado. Controladores do ASP.NET Core usam formatadores JSON por padrão. Defina o que acontece quando a API não pode produzir uma representação solicitada. Por exemplo, configure a API para retornar 406 (Não Aceitável) em vez de retornar silenciosamente um formato sem suporte. Para obter mais informações, consulte Formatar dados de resposta em ASP.NET Core API Web.
Para requisições com corpo, verifique o Content-Type da requisição e aceite apenas os formatos que a operação suporta. Retornar 415 (tipo de mídia sem suporte) para um formato sem suporte. Essa verificação é separada da negociação de resposta por meio de Accept. Em ASP.NET Core, configure os formatadores de entrada e use [Consumes] quando precisar restringir os formatos de solicitação de uma operação. Para obter mais informações, consulte Criar APIs Web com ASP.NET Core.
Implementar a estratégia de controle de versão da API selecionada
Aplique a estratégia de controle de versão escolhida durante o design de forma consistente no aplicativo e no gateway. Encaminhe as requisições para o manipulador e o esquema de resposta da versão selecionada. Defina o comportamento para identificadores de versão omitidos, malformados e sem suporte, em vez de alterar silenciosamente qual contrato um chamador existente recebe.
Preservar os contratos de solicitação e resposta de versões com suporte. Ao introduzir uma alteração significativa, forneça uma nova versão e mantenha as versões anteriores com suporte disponíveis. Lide com requisições de chamadores mais antigos que omitem campos opcionais recém-adicionados. Para obter mais informações, consulte versionamento e compatibilidade da API.
Mantenha os links de recursos gerados e as representações armazenadas em cache consistentes com a versão selecionada. Para controle de versão baseado em cabeçalho, certifique-se de que os caches distinguem solicitações para versões diferentes em vez de depender apenas do URI.
Resolver e autorizar o contexto do locatário
Para uma API multilocatária, determine o locatário para cada solicitação e verifique se o chamador autenticado pode acessar esse locatário. Trate os identificadores de locatário em caminhos, nomes de host e cabeçalhos apenas como entradas de roteamento. Para saber mais, confira Mapear solicitações para locatários em uma solução multilocatário.
Use o contexto do locatário autorizado de forma consistente ao consultar ou atualizar dados e ao delegar tarefas a processadores em segundo plano. Se os caches de aplicativo ou gateway armazenarem dados específicos do tenant, inclua o identificador do tenant na chave de cache. Para obter diretrizes específicas do gateway, consulte os recursos de Gerenciamento de API que dão suporte à multilocação.
Forneça links para dar suporte à navegação no estilo HATEOAS e à descoberta de recursos.
O Hypertext as the Engine of Application State (HATEOAS) usa links para ajudar os clientes a descobrir e navegar pelos recursos. Por exemplo, uma resposta que contém detalhes do cliente pode incluir links para os pedidos desse cliente. Descreva as operações que cada recurso vinculado dá suporte, como GET, POST, PUT e DELETE, e forneça as URIs correspondentes. Para obter mais informações, consulte o design da API.
O exemplo a seguir usa uma representação de link definida pelo aplicativo. Documente suas convenções em vez de assumir que os clientes podem interpretar campos de link personalizados. Uma solicitação GET para um cliente retorna links para os pedidos desse cliente:
GET https://api.contoso.com/customers/2 HTTP/1.1
Accept: application/json
HTTP/1.1 200 OK
...
Content-Type: application/json; charset=utf-8
...
Content-Length: ...
{"customerId": 2,"customerName": "Bert","links": [
{"rel": "self",
"href": "https://api.contoso.com/customers/2",
"action": "GET",
"types": ["text/xml","application/json"]},
{"rel": "self",
"href": "https://api.contoso.com/customers/2",
"action": "PUT",
"types": ["application/x-www-form-urlencoded"]},
{"rel": "self",
"href": "https://api.contoso.com/customers/2",
"action": "DELETE",
"types": []},
{"rel": "orders",
"href": "https://api.contoso.com/customers/2/orders",
"action": "GET",
"types": ["text/xml","application/json"]},
{"rel": "orders",
"href": "https://api.contoso.com/customers/2/orders",
"action": "POST",
"types": ["application/x-www-form-urlencoded"]}
]}
O registro a seguir Customer representa os dados do cliente. Sua propriedade Links contém os links HATEOAS.
public sealed record Customer(
int CustomerId,
string CustomerName,
IReadOnlyList<Link> Links);
public sealed record Link(
string Rel,
string Href,
string Action,
IReadOnlyList<string> Types);
A operação GET recupera os dados do cliente do armazenamento, constrói um Customer registro com seus links e retorna uma resposta JSON. Cada link inclui os seguintes campos:
- A relação (
Rel) entre o recurso retornado e o recurso vinculado. Neste exemplo,selfrefere-se ao cliente eordersrefere-se à coleção de pedidos do cliente. - O hiperlink (
Href) para o objeto que está sendo descrito pelo link, na forma de um URI. - O tipo de solicitação HTTP (
Action) que pode ser enviada para o URI. - O formato de quaisquer dados (
Types) que devam ser fornecidos na solicitação HTTP ou que possam ser retornados na resposta, dependendo do tipo da solicitação.
Os links HATEOAS mostrados no exemplo de resposta HTTP indicam que um aplicativo cliente pode executar as seguintes operações:
- Uma solicitação HTTP GET para
https://api.contoso.com/customers/2recuperar os detalhes do cliente como XML ou JSON. - Uma solicitação HTTP PUT para
https://api.contoso.com/customers/2modificar os detalhes do cliente. O corpo da solicitação usa este formato:application/x-www-form-urlencoded. - Uma solicitação HTTP DELETE para
https://api.contoso.com/customers/2excluir o registro do cliente. Esta operação não requer nenhum corpo da solicitação e não retorna nenhum corpo de resposta. - Uma solicitação HTTP GET para
https://api.contoso.com/customers/2/ordersrecuperar os pedidos do cliente como XML ou JSON. - Uma solicitação HTTP POST para
https://api.contoso.com/customers/2/orderscriar um pedido para o cliente. O corpo da solicitação usa este formato:application/x-www-form-urlencoded.
Tratamento de exceções
Se uma operação gerar uma exceção que não é tratada, considere as diretrizes a seguir.
Capture exceções e retorne uma resposta significativa para os clientes
Manipule as exceções de forma consistente e retorne uma resposta de erro significativa que seja segura para compartilhar com os clientes. Não retorne objetos de exceção, rastreamentos de pilha ou detalhes de implementação interna em respostas de produção. Retorne um código de status HTTP que reflita a falha em vez de retornar o código de status 500 para cada situação. Por exemplo, se uma solicitação de usuário causar uma atualização de banco de dados que viole uma restrição (como tentar excluir um cliente que tenha pedidos pendentes), retorne 409 (Conflito) e uma explicação segura. Retornar 400 (Solicitação Incorreta) para entrada malformada ou falhas na validação da solicitação, não para falhas inesperadas do servidor. Para definições de status HTTP, consulte Códigos de Status. Para obter diretrizes de implementação, consulte Manipular erros em ASP.NET Core.
O controlador a seguir mapeia os resultados de domínio esperados para respostas HTTP. Sua operação de repositório verifica a autorização e os pedidos pendentes como parte da operação de exclusão. Falhas inesperadas se propagam para tratamento centralizado de exceções em vez de serem silenciosamente capturadas em cada ação.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Authorize]
[Route("customers")]
public sealed class CustomersController(ICustomerRepository repository) : ControllerBase
{
[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteCustomer(int id, CancellationToken cancellationToken)
{
var outcome = await repository.DeleteAuthorizedAsync(id, User, cancellationToken);
return outcome switch
{
DeleteOutcome.Deleted => NoContent(),
DeleteOutcome.NotFound => NotFound(),
DeleteOutcome.HasOutstandingOrders => Conflict(new ProblemDetails
{
Status = StatusCodes.Status409Conflict,
Title = "The customer has outstanding orders."
}),
_ => throw new InvalidOperationException("Unknown deletion outcome.")
};
}
}
public enum DeleteOutcome
{
Deleted,
NotFound,
HasOutstandingOrders
}
Importante
Não inclua informações que possam ser úteis para um invasor que tenta obter acesso não autorizado à sua API.
A camada de hospedagem pode rejeitar solicitações antes que elas cheguem à API. Por exemplo, falhas de autenticação podem resultar em respostas 401 (não autorizadas). Após a autenticação, verifique se o chamador está autorizado a acessar o recurso solicitado. Retornar 403 (Proibido) quando a autorização falhar.
Trate exceções de modo consistente e registre em log as informações referentes a erros
Para lidar com exceções de forma consistente, considere implementar uma estratégia global de tratamento de erros em toda a API Web. Registre informações de diagnóstico no servidor, mas exclua segredos, tokens de acesso e dados pessoais confidenciais. Ocultar valores sensíveis antes de gravar entradas de log e limitar o acesso ao log a usuários autorizados. Para obter mais informações, consulte estratégias de arquitetura para monitoramento e detecção de ameaças.
No ASP.NET Core, use middleware de tratamento de exceções e respostas de Detalhes do Problema para um contrato de erro consistente. Configure as respostas de produção para omitir detalhes de diagnóstico e inclua um identificador de correlação que as equipes de suporte podem usar para localizar os logs correspondentes. Para obter mais informações, confira Manipular erros no ASP.NET Core.
Diferencie erros no lado do cliente de erros no lado do servidor
Use códigos de status HTTP 4xx para erros do cliente e códigos de status HTTP 5xx para erros do servidor. Mantenha essa distinção em respostas de erro.
Otimizando o acesso a dados do lado do cliente
Solicitações frequentes e respostas grandes podem tornar a rede um gargalo. Reduza transferências desnecessárias ao implementar a recuperação e a atualização de recursos.
Ofereça suporte a cache no lado do cliente
Use o Cache-Control cabeçalho de resposta para especificar se clientes e servidores intermediários podem armazenar uma resposta e por quanto tempo ela permanece válida.
O exemplo a seguir mostra uma solicitação HTTP GET e a resposta correspondente, que inclui um cabeçalho Cache-Control:
GET https://api.contoso.com/orders/2 HTTP/1.1
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: application/json
Content-Length: 59
{"orderId":2,"productId":4,"quantity":2,"orderValue":10.00}
Neste exemplo, a resposta permanece atualizada por 600 segundos. A private diretiva permite o armazenamento em um cache privado, como um cache do navegador, mas proíbe o armazenamento em um cache compartilhado. Use public somente para respostas que podem ser compartilhadas com segurança entre os chamadores. Use no-store para respostas sensíveis que não devem ser armazenadas.
Em um controlador de ASP.NET Core, defina cabeçalhos de cache antes de retornar a resposta:
Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
{
Private = true,
MaxAge = TimeSpan.FromMinutes(10)
};
Observação
A no-cache diretiva permite o armazenamento, mas requer revalidação antes da reutilização. Use no-store para proibir o armazenamento.
A API controla a política de cache e os validadores em suas respostas. Clientes e servidores intermediários usam essas informações para gerenciar seus caches. Defina esses cabeçalhos de forma consistente para que os chamadores possam reutilizar respostas sem transferências de dados desnecessárias.
Para determinar max-age, considere a desatualização que a carga de trabalho pode tolerar. Um recurso pode ser alterado enquanto uma resposta armazenada em cache ainda está válida. Quando o período de atualização expira, um cache pode revalidar a resposta em vez de descartá-la e baixar toda a representação novamente. Não use um período de atualização longo para dados que exigem visibilidade imediata das alterações.
Forneça ETags para otimizar o processamento de consulta
Uma marca de entidade (ETag) é um validador opaco para uma representação de recurso selecionada. Os clientes podem retê-la com uma resposta armazenada em cache e enviá-la em If-None-Match para verificar se a representação foi alterada. Uma solicitação GET ou HEAD correspondente retorna 304 (Não modificado) sem um corpo de resposta.
Gere um validador que permaneça consistente entre instâncias do aplicativo e mude quando a representação for alterada.
O controlador a seguir calcula o hash dos bytes JSON exatos que retorna e reutiliza as opções JSON configuradas do aplicativo.
FileContentResult aplica o tratamento de resposta condicional do ASP.NET Core sem wrappers de resultados personalizados. O repositório retorna apenas um pedido que o chamador está autorizado a ler. Configure a autenticação e a autorização no aplicativo host.
using System.Security.Cryptography;
using System.Text.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
[ApiController]
[Authorize]
[Route("orders")]
public sealed class OrdersController(IOrderRepository repository,IOptions<JsonOptions> jsonOptions) : ControllerBase
{
[HttpGet("{id:int}")]
[HttpHead("{id:int}")]
public async Task<IActionResult> GetOrder(int id, CancellationToken cancellationToken)
{
var order = await repository.FindAuthorizedAsync(id, User, cancellationToken);
if (order is null)
{
return NotFound();
}
var payload = JsonSerializer.SerializeToUtf8Bytes(order, jsonOptions.Value.JsonSerializerOptions);
var etag = new EntityTagHeaderValue($"\"{Convert.ToHexString(SHA256.HashData(payload))}\"");
Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
{
Private = true,
MaxAge = TimeSpan.FromMinutes(10)
};
return new FileContentResult(payload, "application/json")
{
EntityTag = etag
};
}
}
Este exemplo armazena em buffer a representação e lê o pedido mesmo para uma solicitação condicional. Use-o apenas para respostas limitadas e não sensíveis. Para recursos grandes, considere usar um token de versão armazenado que é alterado sempre que a representação selecionada for alterada, para que você possa validar uma solicitação sem gerar o conteúdo completo. Se a negociação de conteúdo, a compactação ou as transformações de gateway alterarem a representação, verifique se os validadores e a variação de cache permanecem corretos para essa representação.
Uma resposta inclui a ETag e a política de cache. Os exemplos a seguir mostram os primeiros 16 caracteres hexadecimais (64 bits) do hash SHA-256 do corpo JSON exibido, seguidos de ... para fins de brevidade. Os cabeçalhos reais contêm o hash completo sem as reticências.
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: application/json
ETag: "3097D1FD51082205..."
Content-Length: 59
{"orderId":2,"productId":4,"quantity":2,"orderValue":10.00}
Dica
Use Cache-Control: no-store para respostas que contenham dados sensíveis. Para outras respostas específicas do usuário que podem ser armazenadas em cache, use private para impedir o armazenamento em caches compartilhados. Para considerações de implementação, consulte o middleware de cache de resposta em ASP.NET Core.
Dê suporte a solicitações GET condicionais para que os chamadores possam revalidar respostas armazenadas em cache sem baixar uma representação inalterada. Implemente o seguinte comportamento de solicitação e resposta:
Aceite solicitações GET condicionais que forneçam uma ETag no
If-None-Matchcabeçalho, como:GET https://api.contoso.com/orders/2 HTTP/1.1 If-None-Match: "3097D1FD51082205..."Compare o ETag atual do recurso solicitado (pedido 2 neste exemplo) com a condição
If-None-Match.Se a condição corresponder, retorne 304 (Não Modificado) sem um corpo de resposta.
Se a condição não corresponder, retorne 200 (OK) com a representação atual.
Se o recurso solicitado não existir mais, retorne 404 (Não encontrado).
Observação
Uma ETag não torna uma resposta segura para o cache. Aplique diretivas de cache de forma consistente, incluindo em respostas condicionais e de erro, e use no-store para dados confidenciais.
Use o suporte do framework para solicitações condicionais sempre que possível. Se você implementar comparações por conta própria, manipule todos os ETags fornecidos, condições curinga e regras de comparação fracas versus fortes, em vez de comparar apenas o primeiro ETag. Inclua os cabeçalhos ETag e cache apropriados em respostas 304 (Não Modificado) e execute a autorização antes de retornar metadados de recurso.
Dica
Um validador armazenado pode permitir que você verifique se uma representação foi alterada sem recuperar o recurso completo. Essa abordagem pode reduzir a transferência e o processamento de dados quando o recurso é grande ou caro de recuperar.
Usar ETags para dar suporte à concorrência otimista
Para evitar atualizações perdidas, avalie If-Match pré-condições em solicitações de alteração de estado em relação à ETag atual do recurso. Isso permite que a API rejeite uma alteração com base em uma representação que outra operação já modificou. Implemente o seguinte comportamento:
Aceite solicitações de atualização que identifiquem a versão esperada no
If-Matchcabeçalho. A solicitação PUT a seguir atualiza o pedido 2. Ele usa a ETag da resposta GET anterior, abreviada da mesma maneira. A etiqueta identifica a representação existente, não o novo corpo da solicitação:PUT https://api.contoso.com/orders/2 HTTP/1.1 If-Match: "3097D1FD51082205..." Content-Type: application/x-www-form-urlencoded Content-Length: 37 productId=3&quantity=5&orderValue=250Compare a ETag atual do recurso solicitado (ordem 2 neste exemplo) com a condição
If-Match.Se a pré-condição corresponder, execute a atualização atomicamente e retorne a resposta de sucesso documentada, como 204 (Sem Conteúdo). Um
Locationcabeçalho não é necessário apenas porque um recurso existente foi atualizado. Retorne uma ETag em uma resposta PUT bem-sucedida apenas quando ela atender aos requisitos do validador HTTP para a representação armazenada.Se a condição não corresponder, retorne 412 (Falha na pré-condição). Este exemplo não retorna nenhum corpo de resposta.
Se o recurso a ser atualizado não existir mais, retorne 404 (Não encontrado).
Documente o êxito e as respostas de conflito para que os chamadores possam determinar se uma atualização foi bem-sucedida ou se precisam recuperar a representação atual antes de enviar outra alteração.
Para operações que devem impedir atualizações perdidas, exija uma If-Match pré-condição e retorne 428 (Pré-condição necessária) quando ela estiver ausente. Use comparação forte para If-Match.
Verificar uma versão na memória do aplicativo e salvar incondicionalmente cria uma condição de corrida. Imponha a comparação de versão e a gravação atomicamente no armazenamento de dados. Por exemplo, use um token de concorrência de banco de dados para que a atualização seja bem-sucedida somente se a versão armazenada ainda corresponder à versão usada para avaliar a solicitação.
No Entity Framework (EF) Core, configure um token de concorrência e trate DbUpdateConcurrencyException em vez de sobrescrever uma alteração simultânea. No código de acesso a dados da API, não substitua automaticamente a versão esperada e repita uma atualização de banco de dados conflitante, a menos que a semântica da operação permita isso. Para obter mais informações, consulte Tratamento de conflitos de concorrência.
Tratamento de grandes solicitações e respostas
Grandes corpos de solicitação e resposta consomem memória de API, largura de banda e capacidade de conexão. Implemente streaming e limites de recursos para que transferências grandes não esgotem o serviço. Considere os seguintes pontos ao lidar com quantidades significativas de dados:
Otimize as solicitações e respostas que envolvem objetos grandes
Para objetos grandes, como imagens ou outros dados binários, dê suporte a uploads e downloads de streaming.
Use APIs de streaming assíncronas e permita que o servidor selecione o enquadramento de transferência para a versão HTTP negociada. Não adicione Transfer-Encoding: chunked manualmente a cada parte de uma resposta. O streaming não está limitado ao chunked encoding do HTTP/1.1. Evite armazenar em buffer uma solicitação ou resposta não limitada inteira na memória do aplicativo.
Defina limites de corpo da solicitação, limites de upload, tempos limite e políticas de cancelamento nas camadas de aplicativo e hospedagem. Rejeite uma solicitação superdimensionada com 413 (Conteúdo Muito Grande) antes de iniciar a resposta.
A compactação HTTP pode reduzir o tamanho da transferência, ao custo de processamento adicional no servidor e no cliente. Por exemplo, um cliente pode enviar Accept-Encoding: gzip. Se o servidor retornar conteúdo compactado por gzip, identifique a codificação usando Content-Encoding: gzip.
Configure a compactação por meio da plataforma de hospedagem ou middleware e meça suas compensações de CPU e largura de banda nos lados do cliente e do servidor.
- Evite recompactar formatos que já estão compactados.
- Antes de habilitar a compactação para respostas HTTPS geradas dinamicamente, avalie os riscos de compactação, como BREACH, e aplique mitigações apropriadas. Mesmo se você desabilitar a compactação HTTPS em seu middleware, o servidor de hospedagem poderá ser configurado para aplicar compactação.
- Verifique se a variação de cache e as ETags permanecem corretas quando a codificação de conteúdo é alterada.
Para obter diretrizes de implementação de compactação e considerações de segurança, consulte a compactação de resposta em ASP.NET Core.
Suporte a downloads parciais de recursos grandes
Se a API der suporte a downloads parciais de recursos grandes, anuncie essa funcionalidade com Accept-Ranges. Manipule solicitações HEAD retornando os metadados do recurso, incluindo o total Content-Length, sem um corpo de resposta. Para solicitações GET que especificam um intervalo de bytes com suporte, retorne 206 (Conteúdo Parcial), um Content-Length para a parte retornada e uma Content-Range que identifique essa parte do recurso. Esse contrato de resposta permite que os chamadores recuperem partes de um recurso sem exigir que a API retorne todo o objeto.
As solicitações HTTP HEAD e as respostas parciais são descritas mais detalhadamente em Design de API.
Manipular 100-Continue para uploads grandes
Para um upload HTTP/1.1 grande, um cliente pode enviar cabeçalhos de solicitação com Expect: 100-continue e aguardar antes de transmitir o corpo. O servidor pode enviar uma resposta provisória 100 (Continuar) ou rejeitar a solicitação sem receber o corpo completo. Essa troca faz parte de uma solicitação, não de uma solicitação vazia preliminar seguida de uma segunda solicitação completa.
Configure e teste como a pilha de hospedagem e o gateway lidam com solicitações com e sem Expect: 100-continue. Verifique o comportamento da API quando ela aceita ou rejeita um upload e meça os efeitos no uso de recursos do servidor e na latência de solicitação.
Paginação de suporte para solicitações que podem retornar um grande número de objetos
A recuperação de uma coleção grande inteira pode aumentar o processamento do servidor, o tráfego de rede e a latência.
Valide as entradas de paginação no servidor e imponha um tamanho máximo de página. O controller a seguir ilustra a validação da requisição. Ele usa como padrão 10 resultados e rejeita limites fora de 1 a 100 ou offsets fora de 0 a 10.000. Esses limites são ilustrativos. Escolha limites com base na carga de trabalho e nos testes de carga. Quando você usa [ApiController], falhas de validação produzem uma resposta 400. Para obter mais informações, consulte Criar APIs Web com ASP.NET Core.
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Authorize]
[Route("orders")]
public sealed class OrderCollectionsController(IOrderRepository repository) : ControllerBase
{
[HttpGet]
public async Task<ActionResult<IReadOnlyList<Order>>> GetOrders(
[FromQuery, Range(1, 100)] int limit = 10,
[FromQuery, Range(0, 10000)] int offset = 0,
CancellationToken cancellationToken = default)
{
var orders = await repository.ListAuthorizedAsync(limit, offset, User, cancellationToken);
return Ok(orders);
}
}
Um cliente pode solicitar 30 pedidos começando no deslocamento 50 usando https://api.contoso.com/orders?limit=30&offset=50.
Além da validação de solicitação mostrada no exemplo anterior, inclua um link de próxima página ou token de continuação no contrato de resposta. Por exemplo, retorne os pedidos com uma nextLink propriedade definida para https://api.contoso.com/orders?limit=30&offset=80 quando outra página estiver disponível. Preservar filtros, ordem de classificação e versão da API no link. Omita nextLink ou defina-o como null na última página. Para obter um exemplo de um contrato de nextLink, consulte Paginação no Microsoft Graph.
Aplique filtragem e paginação no armazenamento de dados, não depois de carregar toda a coleção. Use uma ordenação determinística. Para coleções grandes ou que mudam com frequência, avalie a paginação baseada em cursor para evitar offsets caros e limites de página instáveis.
Dica
Imponha limites documentados na complexidade da consulta, expressões de filtro e tamanho da solicitação. Teste os limites de cada gateway, proxy e servidor no caminho da solicitação.
Manutenção da capacidade de resposta, escalabilidade e disponibilidade
Defina os objetivos de latência, taxa de transferência e disponibilidade para as operações críticas da API. Projete e teste para tráfego esperado, picos e falhas de dependência. O escalonamento horizontal e o tratamento sem estado dão suporte a esses objetivos. Considere os seguintes requisitos de implementação.
Forneça suporte assíncrono para solicitações de execução longa
Para um processamento que supere uma solicitação HTTP normal, valide e autorize a solicitação, registre duravelmente o processamento e retorne 202 (Aceito). Não confie que uma tarefa em processo não rastreada termine após uma resposta: reinicializações do aplicativo, redução de escala e implantação podem interrompê-la. Use uma fila durável e um worker ou um fluxo de trabalho durável quando o trabalho deve continuar em execução, apesar desses eventos. Para obter a semântica HTTP completa e as diretrizes de implementação, consulte o padrão de Request-Reply assíncrono.
Forneça uma maneira para os chamadores recuperarem o status e o resultado da operação. A API também pode notificar os chamadores ao concluir o processamento.
Você pode fornecer um recurso de status que os clientes consultam periodicamente:
- O cliente envia a solicitação. Valide sua entrada e permissões antes de aceitar o trabalho.
- Persista um identificador de operação e o status no armazenamento durável, como Armazenamento de Tabelas do Azure, e enfileire o trabalho para um processador separado, por exemplo, usando Barramento de Serviço do Azure. Coordenar persistência e enfileiramento para que uma falha entre essas duas ações não resulte na perda do trabalho aceito.
- Retorne 202 com um
Locationcabeçalho que identifica o ponto de extremidade de status e umRetry-Aftercabeçalho que controla a frequência de sondagem. Aceite a solicitação somente depois que o trabalho for registrado de forma durável. - Um trabalhador processa a operação e atualiza seu estado durável. Torne o processamento idempotente porque um trabalhador pode receber o mesmo trabalho mais de uma vez. Aplique novas tentativas limitadas a falhas transitórias.
- O cliente consulta periodicamente o endpoint de status. Imponha autorização em nível de recurso nos pontos de extremidade de status e resultado. Um identificador impossível de adivinhar não é autorização.
- Retornar uma representação de status documentada enquanto o trabalho estiver em andamento. Após a conclusão, forneça o resultado ou um redirecionamento 303 (See Other) para um recurso de resultado. Relate falhas por meio de um contrato de erro consistente e seguro.
- Defina a retenção e a limpeza para os registros e resultados da operação. Documente a expiração da operação, envios duplicados e qualquer comportamento de cancelamento compatível.
Para clientes conectados, considere usar ASP.NET Core SignalR para notificações de conclusão. Mantenha o recurso de status durável disponível para que os clientes possam se recuperar após uma desconexão ou uma notificação perdida. Para obter mais informações, consulte Visão geral do ASP.NET Core SignalR.
Verifique se cada solicitação é sem estado
Não exija uma solicitação posterior para alcançar a mesma instância de aplicativo que uma solicitação anterior. Mantenha o fluxo de trabalho e o estado do recurso em repositórios compartilhados apropriados, não apenas na memória do processo. As solicitações podem depender do estado do recurso durável sem criar afinidade de instância de servidor. O tratamento de solicitações sem estado dá suporte à escalabilidade horizontal.
Entender suas dependências downstream
Defina um tempo limite para cada chamada downstream. Mantenha o tempo total para chamadas, novas tentativas e atrasos dentro do prazo da solicitação de API e propague o cancelamento da solicitação para operações downstream.
Tente novamente apenas falhas transitórias e operações que sejam seguras para repetir. Use repetições limitadas com retirada e tremulação. Limite o número total de tentativas por dependência, bem como as tentativas por solicitação. Para obter mais informações, confira Manipulação de falhas transitórias.
Use um disjuntor quando falhas repetidas de dependências puderem esgotar a capacidade da API.
Acompanhe os clientes e implemente controle de frequência para reduzir as chances de ataques DoS
Aplique limites de taxa de solicitação, simultaneidade, payload e tempo de execução. Limite as partições por chamador ou locatário autenticado, sempre que possível. Retorne 429 (Muitas solicitações) quando um chamador exceder uma taxa configurada e 503 (Serviço Indisponível) para indisponibilidade temporária do serviço. Inclua Retry-After quando apropriado. Se a API tentar novamente chamadas para dependências downstream, limite essas tentativas para que não amplifiquem a sobrecarga.
Os limites de gateway e aplicativo atendem a diferentes finalidades. Os limites de gateway podem proteger a capacidade compartilhada. Os limites do aplicativo podem refletir o custo operacional e a capacidade downstream. Nenhum dos dois substitui a proteção contra DDoS da camada de rede ou um firewall de aplicativo Web. Para obter mais informações, consulte Throttling pattern.
Gerencie as conexões HTTP persistentes cuidadosamente
Para conexões de entrada, configure tempos limite de keep-alive do servidor e do gateway, tempos limite de solicitação e limites de conexão simultâneos para a carga de trabalho e o caminho de rede. Não force rotineiramente o fechamento de conexões após cada resposta. Para obter informações sobre ASP.NET Core configurações de servidor, consulte Configurar opções para o servidor Web Kestrel.
Se a própria API chamar serviços HTTP downstream, reutilize essas conexões de saída. Em uma implementação de API .NET, use instâncias de longa duração de HttpClient com um PooledConnectionLifetime apropriado, ou use clientes criados por IHttpClientFactory. Descarte mensagens e fluxos de resposta de saída quando eles não forem mais necessários. Essas configurações se aplicam às chamadas downstream da API, não às conexões de cliente de entrada. Para obter detalhes e advertências de manipulação de cookie, consulte Diretrizes para usar o HttpClient.
Publicação e gerenciamento de uma API da Web
Implante a API em um ambiente de hospedagem que atenda aos seus requisitos operacionais. Considere as seguintes estratégias:
- Use o HTTPS. Autenticar solicitações para pontos de extremidade protegidos e impor autorização para cada recurso e operação.
- Dimensione o ambiente de hospedagem para atender aos compromissos de tempo de resposta conforme a demanda muda.
- Medir solicitações se o modelo de faturamento da API exigir.
- Regular o tráfego e impor cotas de cliente quando necessário.
- Registre os eventos de auditoria que a conformidade e a resposta a incidentes exigem, mas não registre credenciais, tokens ou corpos sensíveis das solicitações e respostas.
- Monitore a integridade do host e defina ações de recuperação, como reiniciar um host não íntegro.
Considere usar uma fachada separada que lida com preocupações de gerenciamento compartilhado e encaminha solicitações validadas para a API. Uma fachada pode fornecer os seguintes recursos:
- Agir como um ponto de integração para várias APIs da Web.
- Transformar mensagens e traduzir os protocolos de comunicação para clientes criados por meio de diferentes tecnologias.
- Armazenar solicitações e respostas em cache para reduzir a carga no servidor que hospeda a API da Web.
Mantenha os contratos de API e a configuração do gateway sob controle de versão, valide as alterações nos pipelines de implantação e defina os procedimentos de reversão. Alinhe a hospedagem, a identidade, a rede e a governança com a abordagem de landing zone da organização. Para obter mais informações, consulte o que é uma zona de destino do Azure?.
Teste de uma API da Web
Use testes unitários para validar a lógica da API e testes de integração para verificar seu comportamento HTTP.
Inclua as seguintes verificações:
Teste todas as rotas para verificar que elas invocam as operações corretas. Lembre-se especialmente do código de status HTTP 405 (Método Não Permitido) sendo retornado inesperadamente. Este código de status pode indicar uma incompatibilidade entre uma rota e os métodos HTTP (GET, POST, PUT, DELETE) que podem ser enviados para essa rota.
Enviar solicitações que usam métodos não suportados por cada rota e verificar a resposta 405 (Método Não Permitido) documentada e o cabeçalho
Allow.Verifique se todas as rotas são protegidas adequadamente e estão sujeitas às verificações apropriadas de autenticação e autorização.
Observação
Alguns aspectos da segurança, como a autenticação do usuário, provavelmente serão responsabilidade do ambiente do host em vez da API Web, mas você ainda precisa incluir testes de segurança como parte do processo de implantação.
Teste o processamento de exceção realizado por cada operação e verifique se uma resposta HTTP apropriada e significativa é passada de volta para o aplicativo cliente.
Verifique se as mensagens de solicitação e resposta são bem formadas. Por exemplo, para uma solicitação POST que cria um recurso, verifique a desserialização, a análise sintática, a criação do recurso e o cabeçalho
Locationda resposta.Testar tipos de mídia de solicitação com suporte e sem suporte separadamente da negociação de conteúdo de resposta. Verifique as respostas 415 (tipo de mídia sem suporte) para formatos de solicitação sem suporte e os erros de validação documentados para corpos malformados.
Teste todas as versões de API com suporte, incluindo seu roteamento, validação de solicitação e esquema de resposta. Teste identificadores de versão omitidos, malformados e não suportados e verifique se as respostas em cache não ultrapassam os limites de versão.
Verifique todos os links e URIs nas mensagens de resposta. Por exemplo, uma mensagem HTTP POST deve retornar o URI do recurso recém-criado. Todos os links HATEOAS devem ser válidos.
Certifique-se de que cada operação retorna os códigos de status corretos para diferentes combinações de entrada. Por exemplo:
- Se uma consulta for bem-sucedida, ela deverá retornar o código de status 200 (OK).
- Se um recurso não for encontrado, a operação deverá retornar o código de status HTTP 404 (Não encontrado).
- Se o cliente envia uma solicitação que exclui um recurso com êxito, o código de status deve ser 204 (Sem Conteúdo).
- Se o cliente envia uma solicitação que cria um novo recurso, o código de status deve ser 201 (Criado).
Investigue respostas inesperadas de 5xx do aplicativo ou da camada de hospedagem.
Teste as diferentes combinações de cabeçalho de solicitação que um aplicativo cliente pode especificar e certifique-se de que a API da Web retorna as informações esperadas nas mensagens de resposta.
Teste as cadeias de consulta. Se uma operação puder usar parâmetros opcionais (como solicitações de paginação), teste as diferentes combinações e a ordem dos parâmetros.
Verifique se as operações assíncronas são concluídas com êxito. Para respostas de streaming, verifique se a API não armazena em buffer todo o conteúdo e se lida corretamente com as desconexões e o cancelamento do cliente. Se a API fornecer recursos de status para operações de execução prolongada, verifique se elas relatam o progresso da operação e os resultados corretamente.
Teste os casos de falha e casos-limite que afetam a correção:
- Valide entradas de paginação e lote mínimas, máximas, negativas, malformadas e excessivas.
- Siga os links de paginação até a última página. Verifique se os links preservam as opções de consulta e se o sinal de conclusão documentado é retornado.
- Verifique se campos de entrada adicionais não podem alterar as propriedades protegidas e se a seleção de campo não pode expor dados não autorizados.
- Teste ETags correspondentes, não correspondentes, fracas, múltiplas e curinga, e verifique se respostas 304 não contêm corpo.
- Exerça atualizações simultâneas e confirme se o repositório de dados rejeita gravações obsoletas atomicamente.
- Verifique se os chamadores não podem ler recursos, registros de status ou respostas armazenadas em cache de outro chamador.
- Para APIs multilocatários, teste identificadores de locatários forjados ou incompatíveis. Quando o cache estiver habilitado, verifique se há solicitações para o mesmo URI de recurso de locatários diferentes.
- Simular tempos limite, cancelamento do cliente, falhas de dependência, reinicializações de workers e entrega duplicada de trabalho em segundo plano.
- Verifique os orçamentos de tempo limite e de novas tentativas downstream, cancelamento e recuperação de disjuntor.
- Verifique as respostas 429 (Muitas solicitações) e 503 (Serviço indisponível), o comportamento de nova tentativa e o custo de rejeitar solicitações em excesso.
Execute testes de carga em uma infraestrutura semelhante à de produção e com combinações de operações realistas. Defina critérios de aprovação e falha para taxa de transferência, percentis de latência, taxas de erro e saturação de recursos. Use Teste de Carga do Azure e integre verificações de regressão ao pipeline de implantação.
Usando o API Management
Considere usar Gerenciamento de API do Azure quando precisar de um gateway gerenciado com a imposição da política. Ele adiciona custo, outro salto de rede e uma dependência no caminho da solicitação. Escolha uma camada de serviço e topologia com base na capacidade, rede, disponibilidade e requisitos regionais; os recursos diferem por camada. A camada desenvolvedor não se destina a cargas de trabalho de produção. Siga as diretrizes do serviço Well-Architected para Gerenciamento de API.
Você pode publicar e gerenciar uma API Web concluindo estas etapas:
Implante a API Web em uma plataforma de hospedagem como Serviço de Aplicativo do Azure, Aplicativos de Contêiner do Azure, AKS (Serviço de Kubernetes do Azure) ou Máquinas Virtuais do Azure.
Configure o Gerenciamento de API para rotear solicitações de sua URL de gateway para a API de back-end. Uma instância de Gerenciamento de API pode rotear solicitações para várias APIs. Várias instâncias também podem expor a mesma API de back-end quando os aplicativos precisam de limites de acesso diferentes.
Observação
Links HATEOAS em respostas devem fazer referência à URL do gateway de Gerenciamento de API, não à URL do servidor de back-end.
Importe uma definição openAPI controlada por versão e valide se as operações, parâmetros, requisitos de segurança e esquemas de resposta importados correspondem à implementação. Verifique as versões do OpenAPI com suporte e as limitações de importação. Para obter mais informações, consulte Importar uma especificação openapi.
Configure a autenticação e a autorização para comunicações de cliente para gateway e gateway para back-end. Valide os tokens de acesso do OAuth 2.0 e imponha as permissões necessárias para solicitações de cliente. Para back-ends que dão suporte à autenticação Microsoft Entra ID, prefira uma identidade gerenciada do Gerenciamento de API apenas com as permissões necessárias. A autenticação de certificado é outra opção. Evite a autenticação básica quando houver opções mais seguras disponíveis. Para obter mais informações, consulte Autenticação e autorização para APIs no Gerenciamento de API do Azure.
Observação
Se você precisar de chaves de assinatura do Gerenciamento de API, não as use como um substituto para autenticação e autorização no nível do recurso.
Configure as políticas para autenticação, acesso entre origens, transformações de mensagem, filtragem de IP, limites de taxa e cotas, conforme necessário. Configure o cache de resposta apenas para dados seguros para armazenar em cache. Aplique políticas no escopo apropriado e verifique seu comportamento efetivo para cada operação.
Para obter mais informações, confira a Documentação do Gerenciamento de API.
Importante
Um gateway não torna o back-end privado nem substitui a autorização no nível do recurso. Projete controles de acesso de back-end, tratamento de falhas, capacidade e observabilidade para a carga de trabalho como um todo, incluindo o gateway. Avalie a redundância zonal e regional em relação aos recursos do nível selecionado. Inclua encargos de gateway, ingestão e retenção de telemetria e transferência de dados no modelo de custo.
Suporte a desenvolvedores do lado do cliente
Forneça aos consumidores de API documentação para autenticação, operações, parâmetros, tipos de dados e códigos de resposta.
Documentar as operações REST de uma API da Web
Publique uma definição de OpenAPI que descreve as operações, os parâmetros, os esquemas de solicitação e resposta da API e os requisitos de segurança. Mantenha-o sob controle de versão com a implementação e verifique se ele corresponde ao comportamento real da API.
Complemente a referência de API com orientações para que os consumidores usem a API corretamente:
- Requisitos e permissões de autenticação para cada operação.
- Solicitações representativas, respostas bem-sucedidas e respostas de erro.
- Regras de validação de entrada, limites de payload, paginação e limites de taxa.
- Comportamento de timeout, segurança de nova tentativa e requisitos de idempotência.
- Recuperação de status e resultado para operações de execução prolongada.
- Expectativas de controle de versão e compatibilidade.
Mantenha a documentação e os exemplos atualizados quando o contrato de API for alterado.
Implementar um SDK de cliente
Considere fornecer um SDK para consumidores de API. O SDK pode expor métodos tipados que constroem solicitações, analisam respostas e exibem os erros documentados da API.
Considere a geração de clientes tipado a partir da definição de OpenAPI da API, mas valide o comportamento gerado em relação ao serviço. Autenticação de documentos, tempos limite, cancelamento, paginação, respostas de erro e quais operações são seguras para tentar novamente. Mantenha a política de compatibilidade do cliente e da API alinhada. O código gerado não remove a necessidade de testes de integração.
Monitoramento de uma API da Web
Monitore a API, suas dependências e qualquer gateway em conjunto. Defina os objetivos e alertas no nível do serviço com base no impacto do cliente, em vez de depender apenas da integridade do host.
Monitorando uma API da Web diretamente
Use a instrumentação OpenTelemetry para coletar rastreamentos, métricas e logs e exportar os sinais para o Application Insights ou outro back-end com suporte. Para .NET, Node.js e instrumentação em Python, siga as diretrizes da Distribuição Microsoft OpenTelemetry. Java usa a distribuição Azure Monitor OpenTelemetry. Siga as diretrizes de habilitação do OpenTelemetry específicas do idioma.
Sinais de monitoramento que descrevem o comportamento da API:
- Volume de solicitações, taxa de falha e percentis de latência por operação
- Latência de dependências, falhas e timeouts
- Limite rejeições de taxa, trabalho simultâneo e saturação de recursos
- Idade da fila de operação em segundo plano, tempo de conclusão, falhas e novas tentativas
- Eficácia do cache, quando o cache faz parte do design
A telemetria que uma ferramenta de monitoramento coleta automaticamente varia dependendo do idioma, das bibliotecas e da configuração. Adicione instrumentação para operações de domínio e trabalho em segundo plano. Não suponha que as sessões do navegador, as funções de usuário ou todos os detalhes da solicitação estejam disponíveis automaticamente. Propagar o contexto de rastreamento entre o gateway, o aplicativo e os trabalhadores. Configure a amostragem e a retenção para equilibrar as necessidades de diagnóstico, a confidencialidade dos dados e o custo da telemetria.
Use os testes de disponibilidade padrão do Application Insights para verificações externas recorrentes, quando apropriado. Verifique um ponto de extremidade de operação ou integridade significativo sem expor dados confidenciais, defina alertas acionáveis e mantenha um runbook de resposta.
Monitorando uma API Web usando o API Management
Use as métricas, os logs, as análises e os diagnósticos do Azure Monitor compatíveis com o API Management para distinguir falhas de gateway de falhas de back-end. Correlacionar telemetria de gateway e aplicativo e monitorar falhas de política, capacidade, latência de solicitação e limitação. Os sinais disponíveis dependem da camada e da configuração do gateway.
Siga as recomendações de observabilidade e capacidade nas diretrizes do serviço Well-Architected para o Gerenciamento de API.
Próximas etapas
- Visão geral do OData no ASP.NET Core descreve como criar serviços de API REST em conformidade com o protocolo OData usando ASP.NET Core.
- Práticas recomendadas do ASP.NET Core abrangem E/S assíncrona, uso de recursos e tratamento de resposta.
- O padrão Idempotent Consumer fornece diretrizes de implementação para rastrear os IDs de mensagens processadas e lidar com a entrega duplicada.
- A Semântica HTTP define códigos de status HTTP.
- O padrão de Request-Reply assíncrono descreve trabalho durável em segundo plano e recursos de status.
- As práticas recomendadas de arquitetura para Gerenciamento de API do Azure abrangem confiabilidade, segurança, custo, operações e desempenho.
- Teste de Carga do Azure descreve a geração de carga e as verificações de desempenho automatizadas.
- Habilitar o OpenTelemetry fornece diretrizes de instrumentação e exportação específicas da linguagem.