Uma introdução a Resiliência em Sistemas Distribuídos bem como o uso de padrões e políticas de resiliência com o Polly.
Código fonte e animações em:
https://github.com/maiconcp/polly-meetup
Apresentação realizada no evento:
https://www.meetup.com/pt-BR/qualyteam/events/258072791/
3. “É a capacidade da aplicação de se recuperar de falhas e continuar a
funcionar”
- melhor cenário: Sem o usuário perceber
- Pior cenário: “graceful degradation” do serviço, ou seja, oferecer o serviço de
forma limitada (algo como ser tolerante a falhas)
4. • Transiente
• Ocorre uma vez e depois desaparece
• Se a operação for repetida, a falha não acontecerá novamente
• Intermitente
• Ocorre e desaparece por “sua própria vontade”. Ex.: conector com problemas
• Difícil de diagnosticar
• Permanente:
• Continua a existir até que o componente faltoso seja substituído
• Exs: bugs de software, chips queimados
http://www.fisiocomp.ufjf.br/anapaula/SD/SD_aula_13.pdf
6. 1. A rede é confiável
2. A latência é zero
3. A banda é infinita
4. A rede é segura
5. A topologia é imutável
6. Existe apenas um administrador
7. Não há custo para transporte de dados
8. A rede é homogênea
https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing
14. • Aplicado à: Falhas curtas, como por exemplo:
• quando se está movendo um container de nó
• ou falhas nas rede;
• Como: Realizando novas tentativas quando um serviço estiver
indisponível por um período de tempo
Premissa Aka Como a politica ajuda?
Muitas falhas são
transitórias e podem se
auto-corrigir após um
pequeno tempo.
“Talvez seja apenas um
episódio”
Permite configurar re-
tentativas automáticas
16. Variações
• RetryForever: Tentar indefinidamente
• Retry(X): Tentar X vezes
• WaitAndRetry(x,y): Tentar X vezes com um intervalo de Y entre
tentativas
23. // Retry a specified number of times, using a function to
// calculate the duration to wait between retries based on
// the current retry attempt (allows for exponential backoff)
// In this case will wait for
// 2 ^ 1 = 2 seconds then
// 2 ^ 2 = 4 seconds then
// 2 ^ 3 = 8 seconds then
// 2 ^ 4 = 16 seconds then
// 2 ^ 5 = 32 seconds
Policy
.Handle<SomeException>()
.WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)))
.Execute(() =>
{
// do....
});
25. • Manter a integridade do sistema
Premissa Aka
Como a política
ajuda?
Quando um Sistema está
sobrecarregado, falhar
rápido é melhor do que
fazer o chamador esperar.
Protejer o Sistema, pode
ajudá-lo a se recuperar
“Dê um tempo ao sistema"
Quebra o circuito
(bloqueia execuções)
por um período,
quando as falhas
excedem algum limite
pré-configurado..
27. // Break the circuit after the specified number of consecutive exceptions
// and keep circuit broken for the specified duration.
Policy
.Handle<SomeExceptionType>()
.CircuitBreaker(2, TimeSpan.FromMinutes(1));
Policy
.Handle<TException>(...)
.AdvancedCircuitBreaker(
failureThreshold: 0.5,
samplingDuration: TimeSpan.FromSeconds(5),
minimumThroughput: 20,
durationOfBreak: TimeSpan.FromSeconds(30))
28.
29. • Todos as aplicações clientes deveriam trabalhar com um tempo limite
para não ficarem bloqueadas indeterminadamente esperando uma
resposta;
Premissa Aka Como a política ajuda?
Depois um certo tempo,
um resultado de sucesso é
improvável.
“Não espere para sempre”
Garante que o chamador
não terá que esperar além
do tempo limite.
31. // Timeout after 30 seconds, if the executed delegate has not completed.
// Enforces this timeout even if the executed code has no cancellation mechanism.
Policy
.Timeout(30, TimeoutStrategy.Pessimistic)
32.
33. Premissa Aka Como a política ajuda?
As coisas ainda falharão -
planeje o que você fará
quando isso acontecer.
“Falha graciosamente”
Define um valor alternativo
a ser retornado (ou ação a
ser executada) em caso de
falha.
35. // Provide a substitute value, if an execution faults.
Policy<UserAvatar>
.Handle<Whatever>()
.Fallback<UserAvatar>(UserAvatar.Blank)
.Execute...
36.
37. • Cache de Leitura
• Reduz o tempo da chamada
• Reduz o tráfego na rede
• Reduz a sobrecarga do destinatário
Premissa Aka Como a política ajuda?
Algumas solicitações
serão semelhantes.
"Você pediu isso antes"
Fornece uma resposta do cache, se conhecido.
Armazena as respostas automaticamente no cache,
quando recuperadas pela primeira vez.
39. public class PollyCacheSample
{
public CachePolicy<string> CachePolicy =>
Policy.Cache<string>(_memoryCacheProvider, TimeSpan.FromMinutes(5));
private readonly MemoryCacheProvider _memoryCacheProvider;
public PollyCacheSample()
{
// This approach creates a CachePolicy directly,
// with its own Microsoft.Extensions.Caching.Memory.MemoryCache instance:
var memoryCache = new MemoryCache(new MemoryCacheOptions());
_memoryCacheProvider = new MemoryCacheProvider(memoryCache);
}
public void GetSomeThingById(int id)
{
var policyResult = CachePolicy.Execute(context =>
{
return new ClientService().GetSomeThing(id);
}, new Context(operationKey: id.ToString()));
}
CriandoacachePolíticaExecução
40.
41. • Isolar as partes da aplicação em pools para que, se um falhar, os
outros continuarão a funcionar.
• Limita a paralelização
"Uma falha não deve afundar
o navio inteiro"
42.
43. • “Falhas diferentes requerem estratégias diferentes; resiliência
significa usar uma combinação.”
// Define a combined policy strategy, built of previously-defined policies.
var policyWrap = Policy
.Wrap(fallback, cache, retry, breaker, timeout, bulkhead);
// (wraps the policies around any executed delegate: fallback outermost ...
bulkhead innermost)
policyWrap.Execute(...)
// Define a standard resilience strategy ...
PolicyWrap commonResilience = Policy.Wrap(retry, breaker, timeout);
45. • Mesmo após o dispose do HttpClient, o soquete não é liberado imediatamente e pode
causar um problema sério chamado 'esgotamento de soquetes'.
• Portanto, HttpClient deve ser instanciado uma única vez e reutilizado durante a vida útil
da aplicação
• O uso do HttpClient como um Singleton ou Static pode ocasionar um outro problema
quando há alteração de DNS (ver documentação no site da Microsoft)
https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
using (var httpCliente = new HttpClient())
{
...
}
https://docs.microsoft.com/pt-br/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
46. O HttpClientFactory é um recurso do ASPNET Core 2.1
É uma factory facilita o uso do HttpClient
47. Install-Package Microsoft.Extensions.Http
// Startup.cs
//Add http client services at ConfigureServices(IServiceCollection services)
services.AddHttpClient<ICatalogService, CatalogService>();
services.AddHttpClient<IBasketService, BasketService>();
services.AddHttpClient<IOrderingService, OrderingService>();
public void ConfigureServices(IServiceCollection services)
{
O código criará um HttpClient configurado especificamente para cada serviço,
https://docs.microsoft.com/pt-br/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
48. public class CatalogService : ICatalogService
{
private readonly HttpClient _httpClient;
private readonly string _remoteServiceBaseUrl;
public CatalogService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<Catalog> GetCatalogItems(int page, int take,
int? brand, int? type)
{
var uri = API.Catalog.GetAllCatalogItems(_remoteServiceBaseUrl,
page, take, brand, type);
var responseString = await _httpClient.GetStringAsync(uri);
...
}
} https://docs.microsoft.com/pt-br/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
54. • Um método é considerado idempotente se o resultado de uma
requisição realizada com sucesso é independente do número de vezes
que é executada.
http://www.elemarjr.com/pt/2018/01/lidando-com-falhas-de-conexao-em-microsservicos/