Acesso a dados remotos
Gorjeta
Este conteúdo é um excerto do eBook, Enterprise Application Patterns Using .NET MAUI, disponível no .NET Docs ou como um PDF para download gratuito que pode ser lido offline.
Muitas soluções modernas baseadas na Web fazem uso de serviços da Web, hospedados por servidores da Web, para fornecer funcionalidade para aplicativos cliente remotos. As operações que um serviço Web expõe constituem uma API Web.
Os aplicativos cliente devem ser capazes de utilizar a API da Web sem saber como os dados ou operações que a API expõe são implementados. Isso requer que a API respeite padrões comuns que permitam que um aplicativo cliente e um serviço Web concordem sobre quais formatos de dados usar e a estrutura dos dados que são trocados entre aplicativos cliente e o serviço Web.
Introdução à Transferência Representativa do Estado
Representational State Transfer (REST) é um estilo arquitetônico para a construção de sistemas distribuídos baseados em hipermídia. Uma das principais vantagens do modelo REST é que ele é baseado em padrões abertos e não vincula a implementação do modelo ou dos aplicativos cliente que o acessam a qualquer implementação específica. Portanto, um serviço Web REST pode ser implementado usando o Microsoft ASP.NET Core, e os aplicativos cliente podem ser desenvolvidos usando qualquer linguagem e conjunto de ferramentas que possam gerar solicitações HTTP e analisar respostas HTTP.
O modelo REST usa um esquema de navegação para representar objetos e serviços em uma rede, conhecidos como recursos. Os sistemas que implementam REST normalmente usam o protocolo HTTP para transmitir solicitações para acessar esses recursos. Nesses sistemas, um aplicativo cliente envia uma solicitação na forma de um URI que identifica um recurso e um método HTTP (como GET, POST, PUT ou DELETE) que indica a operação a ser executada nesse recurso. O corpo da solicitação HTTP contém todos os dados necessários para executar a operação.
Nota
REST define um modelo de solicitação sem monitoração de estado. Portanto, as solicitações HTTP devem ser independentes e podem ocorrer em qualquer ordem.
A resposta de uma solicitação REST usa códigos de status HTTP padrão. Por exemplo, uma solicitação que retorna dados válidos deve incluir o código de resposta HTTP 200 (OK
), enquanto uma solicitação que não consegue localizar ou excluir um recurso especificado deve retornar uma resposta que inclua o código de status HTTP 404 (Not Found
).
Uma API Web RESTful expõe um conjunto de recursos conectados e fornece as operações principais que permitem que um aplicativo manipule esses recursos e navegue facilmente entre eles. Por esse motivo, os URIs que constituem uma API da Web RESTful típica são orientados para os dados que ela expõe e usam os recursos fornecidos pelo HTTP para operar nesses dados.
Os dados incluídos por um aplicativo cliente em uma solicitação HTTP e as mensagens de resposta correspondentes do servidor Web podem ser apresentados em uma variedade de formatos, conhecidos como tipos de mídia. Quando um aplicativo cliente envia uma solicitação que retorna dados no corpo de uma mensagem, ele pode especificar os tipos de mídia que pode manipular no cabeçalho Accept da solicitação. Se o servidor Web oferecer suporte a esse tipo de mídia, ele poderá responder com uma resposta que inclua o cabeçalho Content-Type que especifica o formato dos dados no corpo da mensagem. Em seguida, é responsabilidade do aplicativo cliente analisar a mensagem de resposta e interpretar os resultados no corpo da mensagem adequadamente.
Para obter mais informações sobre REST, consulte Design de API e implementação de API no Microsoft Docs.
Consumindo APIs RESTful
O aplicativo multiplataforma eShop usa o padrão Model-View-ViewModel (MVVM) e os elementos de modelo do padrão representam as entidades de domínio usadas no aplicativo. As classes de controlador e repositório no aplicativo de referência eShop aceitam e retornam muitos desses objetos de modelo. Portanto, eles são usados como objetos de transferência de dados (DTOs) que armazenam todos os dados que são passados entre o aplicativo e os microsserviços em contêiner. O principal benefício de usar DTOs para passar e receber dados de um serviço Web é que, ao transmitir mais dados em uma única chamada remota, o aplicativo pode reduzir o número de chamadas remotas que precisam ser feitas.
Fazer pedidos na Web
O aplicativo multiplataforma eShop usa a HttpClient
classe para fazer solicitações via HTTP, com JSON sendo usado como o tipo de mídia. Essa classe fornece funcionalidade para enviar solicitações HTTP de forma assíncrona e receber respostas HTTP de um recurso identificado por URI. A classe HttpResponseMessage representa uma mensagem de resposta HTTP recebida de uma API REST após uma solicitação HTTP ter sido feita. Ele contém informações sobre a resposta, incluindo o código de status, cabeçalhos e qualquer corpo. A classe HttpContent representa o corpo HTTP e os cabeçalhos de conteúdo, como Content-Type e Content-Encoding. O conteúdo pode ser lido usando qualquer um dos ReadAs
métodos, como ReadAsStringAsync
e ReadAsByteArrayAsync
, dependendo do formato dos dados.
Fazer um pedido GET
A CatalogService
classe é usada para gerenciar o processo de recuperação de dados do microsserviço de catálogo. RegisterViewModels
No método na MauiProgram
classe, a CatalogService
classe é registrada como um mapeamento de tipo em relação ao ICatalogService
tipo com o contêiner de injeção de dependência. Em seguida, quando uma instância da classe é criada, seu construtor aceita um ICatalogService type
, que o contêiner de CatalogViewModel
injeção de dependência resolve, retornando uma instância da CatalogService
classe. Para obter mais informações sobre injeção de dependência, consulte Injeção de dependência.
A imagem abaixo mostra a interação de classes que leem dados de catálogo do microsserviço de catálogo para exibição pelo CatalogView.
Quando o CatalogView
é navegado para, o OnInitialize
método na classe CatalogViewModel é chamado. Esse método recupera dados de catálogo do microsserviço de catálogo, conforme demonstrado no exemplo de código a seguir:
public override async Task InitializeAsync()
{
Products = await _productsService.GetCatalogAsync();
}
Esse método chama o GetCatalogAsync
CatalogService
método da instância que foi injetada no CatalogViewModel
contêiner de injeção de dependência. O exemplo de código a seguir mostra o GetCatalogAsync
método:
public async Task<ObservableCollection<CatalogItem>> GetCatalogAsync()
{
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);
builder.Path = "api/v1/catalog/items";
string uri = builder.ToString();
CatalogRoot? catalog = await _requestProvider.GetAsync<CatalogRoot>(uri);
return catalog?.Data;
}
Esse método cria o URI que identifica o recurso para o qual a solicitação será enviada e usa a RequestProvider
classe para invocar o método HTTP GET no recurso, antes de retornar os resultados para o CatalogViewModel
. A RequestProvider
classe contém funcionalidade que envia uma solicitação na forma de um URI que identifica um recurso, um método HTTP que indica a operação a ser executada nesse recurso e um corpo que contém todos os dados necessários para executar a operação. Para obter informações sobre como a classe é injetada CatalogService
RequestProvider
na classe, consulte Injeção de dependência.
O exemplo de RequestProvider
código a seguir mostra o GetAsync
método na classe:
public async Task<TResult> GetAsync<TResult>(string uri, string token = "")
{
HttpClient httpClient = GetOrCreateHttpClient(token);
HttpResponseMessage response = await httpClient.GetAsync(uri);
await HandleResponse(response);
TResult result = await response.Content.ReadFromJsonAsync<TResult>();
return result;
}
Esse método chama o GetOrCreateHttpClient
método, que retorna uma instância da HttpClient
classe com os cabeçalhos apropriados definidos. Em seguida, ele envia uma solicitação assíncrona GET
para o recurso identificado pelo URI, com a resposta sendo armazenada na HttpResponseMessage
instância. O HandleResponse
método é então invocado, o que lança uma exceção se a resposta não incluir um código de status HTTP bem-sucedido. Em seguida, a resposta é lida como uma cadeia de caracteres, convertida de JSON para um CatalogRoot
objeto e retornada para o CatalogService
.
O GetOrCreateHttpClient
método é mostrado no exemplo de código a seguir:
private readonly Lazy<HttpClient> _httpClient =
new Lazy<HttpClient>(
() =>
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return httpClient;
},
LazyThreadSafetyMode.ExecutionAndPublication);
private HttpClient GetOrCreateHttpClient(string token = "")
{
var httpClient = _httpClient.Value;
if (!string.IsNullOrEmpty(token))
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
else
{
httpClient.DefaultRequestHeaders.Authorization = null;
}
return httpClient;
}
Esse método usa cria uma nova instância ou recupera uma instância em cache da HttpClient
classe e define o cabeçalho Accept de todas as solicitações feitas pela HttpClient
instância como , o application/json
que indica que ele espera que o conteúdo de qualquer resposta seja formatado usando JSON. Em seguida, se um token de acesso foi passado como um argumento para o GetOrCreateHttpClient
método, ele é adicionado ao Authorization
cabeçalho de todas as solicitações feitas pela instância, prefixadas HttpClient
com a cadeia de caracteres Bearer
. Para obter mais informações sobre autorização, consulte Autorização.
Gorjeta
É altamente recomendável armazenar em cache e reutilizar instâncias do para um melhor desempenho do HttpClient
aplicativo. Criar um novo HttpClient
para cada operação pode levar a problemas com a exaustão do soquete. Para obter mais informações, consulte HttpClient Instanciing no Microsoft Developer Center.
Quando o GetAsync
método na RequestProvider
classe chama HttpClient.GetAsync
, o Items
método na CatalogController
classe no Catalog.API
projeto é invocado, que é mostrado no exemplo de código a seguir:
[HttpGet]
[Route("[action]")]
public async Task<IActionResult> Items(
[FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
{
var totalItems = await _catalogContext.CatalogItems
.LongCountAsync();
var itemsOnPage = await _catalogContext.CatalogItems
.OrderBy(c => c.Name)
.Skip(pageSize * pageIndex)
.Take(pageSize)
.ToListAsync();
itemsOnPage = ComposePicUri(itemsOnPage);
var model = new PaginatedItemsViewModel<CatalogItem>(
pageIndex, pageSize, totalItems, itemsOnPage);
return Ok(model);
}
Esse método recupera os dados do catálogo do banco de dados SQL usando EntityFramework e os retorna como uma mensagem de resposta que inclui um código de status HTTP de sucesso e uma coleção de instâncias formatadas JSON CatalogItem
.
Fazer um pedido POST
A BasketService
classe é usada para gerenciar o processo de recuperação e atualização de dados com o microsserviço da cesta. RegisterAppServices
No método na MauiProgram
classe, a BasketService
classe é registrada como um mapeamento de tipo em relação ao IBasketService
tipo com o contêiner de injeção de dependência. Em seguida, quando uma instância da classe é criada, seu construtor aceita um IBasketService
tipo, que o contêiner de injeção de BasketViewModel
dependência resolve, retornando uma instância da BasketService
classe. Para obter mais informações sobre injeção de dependência, consulte Injeção de dependência.
A imagem abaixo mostra a interação das classes que enviam os dados da cesta exibidos pelo BasketView, para o microsserviço da cesta.
Quando um item é adicionado ao carrinho de compras, o ReCalculateTotalAsync
método na BasketViewModel
classe é chamado. Esse método atualiza o valor total dos itens na cesta e envia os dados da cesta para o microsserviço da cesta, conforme demonstrado no exemplo de código a seguir:
private async Task ReCalculateTotalAsync()
{
// Omitted for brevity...
await _basketService.UpdateBasketAsync(
new CustomerBasket
{
BuyerId = userInfo.UserId,
Items = BasketItems.ToList()
},
authToken);
}
Esse método chama o UpdateBasketAsync
BasketService
método da instância que foi injetada no BasketViewModel
contêiner de injeção de dependência. O método a seguir mostra o UpdateBasketAsync
método:
public async Task<CustomerBasket> UpdateBasketAsync(
CustomerBasket customerBasket, string token)
{
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint);
string uri = builder.ToString();
var result = await _requestProvider.PostAsync(uri, customerBasket, token);
return result;
}
Esse método cria o URI que identifica o recurso para o qual a solicitação será enviada e usa a RequestProvider
classe para invocar o método HTTP POST no recurso, antes de retornar os resultados para o BasketViewModel
. Observe que um token de acesso, obtido durante o processo de autenticação, é necessário para autorizar solicitações ao microsserviço da IdentityServer
cesta. Para obter mais informações sobre autorização, consulte Autorização.
O exemplo de código a seguir mostra um dos PostAsync
métodos na RequestProvider
classe:
public async Task<TResult> PostAsync<TResult>(
string uri, TResult data, string token = "", string header = "")
{
HttpClient httpClient = GetOrCreateHttpClient(token);
var content = new StringContent(JsonSerializer.Serialize(data));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await httpClient.PostAsync(uri, content);
await HandleResponse(response);
TResult result = await response.Content.ReadFromJsonAsync<TResult>();
return result;
}
Esse método chama o GetOrCreateHttpClient
método, que retorna uma instância da HttpClient
classe com os cabeçalhos apropriados definidos. Em seguida, ele envia uma solicitação POST assíncrona para o recurso identificado pelo URI, com os dados da cesta serializada sendo enviados no formato JSON e a resposta sendo armazenada na HttpResponseMessage
instância. O HandleResponse
método é então invocado, o que lança uma exceção se a resposta não incluir um código de status HTTP bem-sucedido. Em seguida, a resposta é lida como uma cadeia de caracteres, convertida de JSON para um CustomerBasket
objeto e retornada para o BasketService. Para obter mais informações sobre o GetOrCreateHttpClient
método, consulte Fazendo uma solicitação GET.
Quando o PostAsync
método na RequestProvider
classe chama HttpClient.PostAsync
, o Post
método na BasketController
classe no Basket.API
projeto é invocado, que é mostrado no exemplo de código a seguir:
[HttpPost]
public async Task<IActionResult> Post([FromBody] CustomerBasket value)
{
var basket = await _repository.UpdateBasketAsync(value);
return Ok(basket);
}
Esse método usa uma instância da classe para persistir os dados da cesta no cache Redis e os retorna como uma mensagem de resposta que inclui um código de status HTTP bem-sucedido e uma instância formatada RedisBasketRepository
JSON CustomerBasket
.
Fazer um pedido DELETE
A imagem abaixo mostra as interações das classes que excluem os dados da cesta do microsserviço da cesta, para o CheckoutView
.
Quando o processo de check-out é invocado, o CheckoutAsync
método na CheckoutViewModel
classe é chamado. Este método cria uma nova ordem, antes de limpar o carrinho de compras, como demonstrado no exemplo de código a seguir:
private async Task CheckoutAsync()
{
// Omitted for brevity...
await _basketService.ClearBasketAsync(
_shippingAddress.Id.ToString(), authToken);
}
Esse método chama o ClearBasketAsync
BasketService
método da instância que foi injetada no CheckoutViewModel
contêiner de injeção de dependência. O método a seguir mostra o ClearBasketAsync
método:
public async Task ClearBasketAsync(string guidUser, string token)
{
UriBuilder builder = new(GlobalSetting.Instance.BasketEndpoint);
builder.Path = guidUser;
string uri = builder.ToString();
await _requestProvider.DeleteAsync(uri, token);
}
Esse método cria o URI que identifica o recurso para o qual a solicitação será enviada e usa a RequestProvider
classe para invocar o DELETE
método HTTP no recurso. Observe que um token de acesso, obtido durante o processo de autenticação, é necessário para autorizar solicitações ao microsserviço da IdentityServer
cesta. Para obter mais informações sobre autorização, consulte Autorização.
O exemplo de RequestProvider
código a seguir mostra o DeleteAsync
método na classe:
public async Task DeleteAsync(string uri, string token = "")
{
HttpClient httpClient = GetOrCreateHttpClient(token);
await httpClient.DeleteAsync(uri);
}
Esse método chama o GetOrCreateHttpClient
método, que retorna uma instância da HttpClient
classe com os cabeçalhos apropriados definidos. Em seguida, ele envia uma solicitação assíncrona DELETE
para o recurso identificado pelo URI. Para obter mais informações sobre o GetOrCreateHttpClient
método, consulte Fazendo uma solicitação GET.
Quando o DeleteAsync
método na RequestProvider
classe chama HttpClient.DeleteAsync
, o Delete
método na BasketController
classe no Basket.API
projeto é invocado, que é mostrado no exemplo de código a seguir:
[HttpDelete("{id}")]
public void Delete(string id) =>
_repository.DeleteBasketAsync(id);
Esse método usa uma instância da RedisBasketRepository
classe para excluir os dados da cesta do cache Redis.
Colocar dados em cache
O desempenho de um aplicativo pode ser melhorado armazenando em cache dados acessados com frequência em um armazenamento rápido localizado próximo ao aplicativo. Se o armazenamento rápido estiver localizado mais perto do aplicativo do que a fonte original, o cache pode melhorar significativamente os tempos de resposta ao recuperar dados.
A forma mais comum de cache é o cache de leitura, em que um aplicativo recupera dados fazendo referência ao cache. Se os dados não estiverem na cache, são obtidos a partir do arquivo de dados e adicionados à cache. Os aplicativos podem implementar o cache de leitura com o padrão cache-side. Esse padrão determina se o item está atualmente no cache. Se o item não estiver no cache, ele será lido do armazenamento de dados e adicionado ao cache. Para obter mais informações, consulte o padrão Cache-Aside no Microsoft Docs.
Gorjeta
Armazene em cache dados lidos com frequência e alterados com pouca frequência.
Esses dados podem ser adicionados ao cache sob demanda na primeira vez que são recuperados por um aplicativo. Isso significa que o aplicativo precisa buscar os dados apenas uma vez no armazenamento de dados e que o acesso subsequente pode ser satisfeito usando o cache.
Os aplicativos distribuídos, como o aplicativo de referência eShop, devem fornecer um ou ambos os seguintes caches:
- Um cache compartilhado, que pode ser acessado por vários processos ou máquinas.
- Um cache privado, onde os dados são mantidos localmente no dispositivo que executa o aplicativo.
O aplicativo multiplataforma eShop usa um cache privado, onde os dados são mantidos localmente no dispositivo que está executando uma instância do aplicativo.
Gorjeta
Pense no cache como um armazenamento de dados transitório que pode desaparecer a qualquer momento.
Certifique-se de que os dados são mantidos no armazenamento de dados original, bem como no cache. As chances de perda de dados são minimizadas se o cache ficar indisponível.
Gerenciando a expiração de dados
É impraticável esperar que os dados armazenados em cache sejam sempre consistentes com os dados originais. Os dados no armazenamento de dados original podem ser alterados depois de serem armazenados em cache, fazendo com que os dados armazenados em cache se tornem obsoletos. Portanto, os aplicativos devem implementar uma estratégia que ajude a garantir que os dados no cache estejam o mais atualizados possível, mas também possam detetar e lidar com situações que surgem quando os dados no cache se tornaram obsoletos. A maioria dos mecanismos de cache permite que o cache seja configurado para expirar dados e, portanto, reduzir o período durante o qual os dados podem estar desatualizados.
Gorjeta
Defina um tempo de expiração padrão ao configurar um cache.
Muitos caches implementam a expiração, que invalida os dados e os remove do cache se não forem acessados por um período especificado. No entanto, é preciso ter cuidado ao escolher o período de validade. Se for muito curto, os dados expirarão muito rapidamente e os benefícios do cache serão reduzidos. Se for feito por muito tempo, os dados correm o risco de se tornarem obsoletos. Portanto, o tempo de expiração deve corresponder ao padrão de acesso para aplicativos que usam os dados.
Quando os dados armazenados em cache expirarem, eles devem ser removidos do cache e o aplicativo deve recuperar os dados do armazenamento de dados original e colocá-los de volta no cache.
Também é possível que um cache fique cheio se os dados puderem permanecer por um período muito longo. Portanto, solicitações para adicionar novos itens ao cache podem ser necessárias para remover alguns itens em um processo conhecido como remoção. Os serviços de cache normalmente removem dados em uma base menos usada recentemente. No entanto, existem outras políticas de despejo, incluindo as mais recentes e as mais recentes. Para obter mais informações, consulte Diretrizes de cache no Microsoft Docs.
Armazenamento em cache de imagens
A aplicação multiplataforma eShop consome imagens de produtos remotos que beneficiam de serem armazenadas em cache. Essas imagens são exibidas pelo controle Image. O controle de imagem .NET MAUI suporta o cache de imagens baixadas que tem o cache habilitado por padrão e armazenará a imagem localmente por 24 horas. Além disso, o tempo de expiração pode ser configurado com a propriedade CacheValidity. Para obter mais informações, consulte Cache de imagens baixado no Microsoft Developer Center.
Aumentar a resiliência
Todos os aplicativos que se comunicam com serviços e recursos remotos devem ser sensíveis a falhas transitórias. As falhas transitórias incluem a perda momentânea de conectividade de rede para serviços, a indisponibilidade temporária de um serviço ou tempos limite que surgem quando um serviço está ocupado. Essas falhas geralmente são autocorretivas e, se a ação for repetida após um atraso adequado, é provável que tenha sucesso.
Falhas transitórias podem ter um enorme impacto na qualidade percebida de um aplicativo, mesmo que ele tenha sido exaustivamente testado em todas as circunstâncias previsíveis. Para garantir que um aplicativo que se comunica com serviços remotos opere de forma confiável, ele deve ser capaz de fazer o seguinte:
- Detete falhas quando elas ocorrerem e determine se elas provavelmente serão transitórias.
- Repita a operação se determinar que a falha provavelmente será transitória e acompanhe o número de vezes que a operação foi repetida.
- Use uma estratégia de repetição apropriada, que especifica o número de tentativas, o atraso entre cada tentativa e as ações a serem tomadas após uma tentativa falhada.
Esse tratamento de falhas transitórias pode ser alcançado encapsulando todas as tentativas de acessar um serviço remoto no código que implementa o padrão de repetição.
Padrão de Repetição
Se um aplicativo detetar uma falha ao tentar enviar uma solicitação para um serviço remoto, ele poderá lidar com a falha de qualquer uma das seguintes maneiras:
- Repetindo a operação. O aplicativo pode repetir a solicitação com falha imediatamente.
- Repetir a operação após um atraso. O aplicativo deve aguardar por um período de tempo adequado antes de tentar novamente a solicitação.
- Cancelamento da operação. O aplicativo deve cancelar a operação e relatar uma exceção.
A estratégia de repetição deve ser ajustada para corresponder aos requisitos de negócios do aplicativo. Por exemplo, é importante otimizar a contagem de repetições e o intervalo de repetição para a operação que está sendo tentada. Se a operação fizer parte de uma interação do usuário, o intervalo de repetição deve ser curto e apenas algumas tentativas devem ser tentadas para evitar que os usuários esperem por uma resposta. Se a operação fizer parte de um fluxo de trabalho de longa execução, em que cancelar ou reiniciar o fluxo de trabalho é caro ou demorado, é apropriado esperar mais tempo entre as tentativas e tentar novamente mais vezes.
Nota
Uma estratégia agressiva de repetição com atraso mínimo entre as tentativas e um grande número de tentativas pode degradar um serviço remoto que está sendo executado perto ou na capacidade. Além disso, essa estratégia de repetição também pode afetar a capacidade de resposta do aplicativo se ele estiver continuamente tentando executar uma operação com falha.
Se uma solicitação ainda falhar após várias tentativas, é melhor para o aplicativo impedir que novas solicitações vão para o mesmo recurso e relatar uma falha. Em seguida, após um período definido, o aplicativo pode fazer uma ou mais solicitações ao recurso para ver se elas são bem-sucedidas. Para obter mais informações, consulte Padrão do disjuntor.
Gorjeta
Nunca implemente um mecanismo de repetição permanente. Em vez disso, prefira um recuo exponencial.
Use um número finito de tentativas ou implemente o padrão Disjuntor para permitir a recuperação de um serviço.
O aplicativo de referência eShop implementa o padrão de repetição.
Para obter mais informações sobre o padrão de repetição, consulte o padrão de repetição no Microsoft Docs.
Padrão do disjuntor
Em algumas situações, as falhas podem ocorrer devido a eventos antecipados que levam mais tempo para serem corrigidos. Essas falhas podem variar de uma perda parcial de conectividade até a falha completa de um serviço. Nessas situações, é inútil para um aplicativo tentar novamente uma operação que provavelmente não terá êxito e, em vez disso, deve aceitar que a operação falhou e lidar com essa falha de acordo.
O padrão de disjuntor pode impedir que um aplicativo tente executar repetidamente uma operação que provavelmente falhará, ao mesmo tempo em que permite que o aplicativo detete se a falha foi resolvida.
Nota
A finalidade do padrão do disjuntor é diferente do padrão de repetição. O padrão de repetição permite que um aplicativo tente novamente uma operação na expectativa de que ela seja bem-sucedida. O padrão do disjuntor impede que um aplicativo execute uma operação que provavelmente falhará.
Um disjuntor automático atua como proxy para operações suscetíveis de falhar. O proxy deve monitorar o número de falhas recentes que ocorreram e usar essas informações para decidir se permite que a operação prossiga ou se retorna uma exceção imediatamente.
Atualmente, o aplicativo multiplataforma eShop não implementa o padrão de disjuntor. No entanto, a eShop sim.
Gorjeta
Combine os padrões de repetição e disjuntor.
Um aplicativo pode combinar os padrões de repetição e disjuntor usando o padrão de repetição para invocar uma operação por meio de um disjuntor. No entanto, a lógica de repetição deve ser sensível a eventuais exceções devolvidas pelo disjuntor automático e abandonar tentativas de repetição se o disjuntor automático indicar que uma falha não é transitória.
Para obter mais informações sobre o padrão do disjuntor, consulte o padrão do disjuntor no Microsoft Docs.
Resumo
Muitas soluções modernas baseadas na Web fazem uso de serviços da Web, hospedados por servidores da Web, para fornecer funcionalidade para aplicativos cliente remotos. As operações que um serviço Web expõe constituem uma API da Web, e os aplicativos cliente devem ser capazes de utilizar a API da Web sem saber como os dados ou operações que a API expõe são implementados.
O desempenho de um aplicativo pode ser melhorado armazenando em cache dados acessados com frequência em um armazenamento rápido localizado próximo ao aplicativo. Os aplicativos podem implementar o cache de leitura com o padrão cache-side. Esse padrão determina se o item está atualmente no cache. Se o item não estiver no cache, ele será lido do armazenamento de dados e adicionado ao cache.
Ao se comunicar com APIs da Web, os aplicativos devem ser sensíveis a falhas transitórias. As falhas transitórias incluem a perda momentânea de conectividade de rede para serviços, a indisponibilidade temporária de um serviço ou tempos limite que surgem quando um serviço está ocupado. Essas falhas geralmente são autocorretivas e, se a ação for repetida após um atraso adequado, é provável que tenha sucesso. Portanto, os aplicativos devem encapsular todas as tentativas de acessar uma API da Web em código que implemente um mecanismo transitório de tratamento de falhas.