Desenvolvendo integrações resilientes com o Lumis Portal 11

1) Introdução

Sempre que desenvolvemos projetos com integração entre sistemas, devemos prever e tratar cenários de lentidão e falhas nas chamadas entre eles. A forma de tratamento, no entanto, pode variar de acordo com as características da solução.

Algumas opções muito utilizadas são a definição de um tempo limite em que o sistema de origem vai aguardar a resposta do sistema sendo chamado (timeout) ou limitar o número de chamadas que o sistema sendo chamado suporta, negando requisições que extrapolem esse limite. Além disso, também pode ser necessário determinar depois de quanto tempo de uma chamada malsucedida deve ser realizada nova tentativa.

Mecanismos como estes ajudam a tornar a solução mais resiliente à problemas na conexão entre os sistemas integrados, evitando que o enfileiramento de chamadas cause erros em cascata nos servidores o que poderia levar inclusive a uma interrupção completa dos serviços para os usuários. E uma boa opção para isso é a aplicação do padrão Circuit Breaker.

 

2) O padrão Circuit Breaker

É comum que sistemas de software realizem chamadas remotas para outros sistemas hospedados em diferentes máquinas ao longo da rede. Uma das grandes diferenças entre chamadas locais e chamadas remotas, é que as remotas podem falhar ou ficar suspensas sem uma resposta até que o tempo limite seja atingido.

E o pior é que um grande volume de chamadas para um sistema que não seja capaz de suportá-las pode levar a um esgotamento de recursos de máquina, e não somente da máquina onde está hospedado o sistema alvo da chamada, causando erros em cascata e possivelmente a interrupção dos serviços. O padrão Circuit Breaker existe justamente com o propósito de prevenir esse tipo de situação.

A ideia básica por trás do padrão é bastante simples. Com ele, você encapsula uma determinada função de um sistema que deve ser protegida com um objeto do tipo Circuit Breaker. Este, constantemente monitora o sucesso ou falhas das chamadas realizadas a essa função. Uma vez que o número de falhas atinja um determinado limite pré-estabelecido, o Circuit Breaker interrompe o acesso à função, impedindo que as próximas chamadas a ela cheguem ao seu destino e entregando uma mensagem de erro para todas as tentativas realizadas enquanto o sistema estiver nesse estado. Usualmente, o fato do Circuit Breaker ser ativado gera um alerta de monitoramento para que o problema causador das falhas seja investigado.

sketch 2.png

O principal objetivo é evitar que recursos de hardware sejam consumidos e fiquem ocupados com operações que provavelmente vão falhar. Evita-se que os sistemas que realizam as chamadas fiquem parados aguardando até que se atinja o tempo limite estabelecido para eles (e que receberia um erro de qualquer forma) e também que os sistemas que estão sendo chamados, que provavelmente estão sobrecarregados, já que estão retornando erro nas chamadas realizadas a eles, recebam uma carga ainda maior.

O cenário típico de utilização desse padrão é o de chamadas remotas, mas ele também pode ser utilizado em outras situações em que se deseje proteger determinadas partes de um sistema de serem afetadas por falhas em outras partes. Dessa forma, a aplicação de um Circuit Breaker pode auxiliar bastante no monitoramento de ambientes, lançando alertas que podem auxiliar a equipe de operações a detectar e tratar problemas na infraestrutura.

 

3) Aplicação do padrão Circuit Breaker no Lumis Portal 11

O Lumis Portal, a partir da versão 11.0, vem com um framework para implementação de Circuit Breakers para melhorar a resiliência em projetos que possuam requisitos de integração com outros sistemas, o Hystrix.

O Hystrix é uma biblioteca de gerenciamento de latência e tolerância a falhas projetada para isolar pontos de acessos a sistemas remotos, serviços e bibliotecas externas, evitando erros em cascata e aumentando a resiliência em sistemas distribuídos complexos onde algum nível de falhas é inevitável. Trata-se de um framework bem maduro e de valor comprovado, pelo uso extensivo na Netflix.

Em sua essência, o Hystrix é um Circuit Breaker que, baseado em parâmetros estabelecidos, detecta problemas de integração e gerencia quando o circuito que conecta os dois sistemas deve ser aberto (desconectado) para evitar a escalada de problemas e quando deve ser mantido fechado (conectado) e permitindo que as chamadas aconteçam normalmente.

 

4) Utilização do Hystrix em soluções

Abaixo apresentamos um exemplo de código que mostra um pedaço da implementação de uma camada de Circuit Braker com o Lumis Portal:

public class CommandHelloWorld extends HystrixCommand<String> {

    private final String name;

    public CommandHelloWorld(String name) {

        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));

        this.name = name;

    }

    @Override

    protected String run() {

        return "Hello " + name + "!";

    }

}

======================

if("Hello World!".equals(new CommandHelloWorld("World").execute()))

response.getWriter().println("<br/>Synchoronous execution <strong>succeeded</strong>!<br/><br/>");

else

response.getWriter().println("<br/>Synchoronous execution <strong>failed</strong>!<br/><br/>");

 

if("Hello Bob!".equals(new CommandHelloWorld("Bob").queue().get()))

response.getWriter().println("<br/>Asynchoronous execution <strong>succeeded</strong>!<br/><br/>");

else

response.getWriter().println("<br/>Asynchoronous execution <strong>failed</strong>!<br/><br/>");

 

 

O exemplo completo pode ser obtido aqui.

Para mais informações sobre o uso do Hystrix, acesse https://github.com/Netflix/Hystrix#hystrix-latency-and-fault-tolerance-for-distributed-systems.

 

5) Referências

https://martinfowler.com/bliki/CircuitBreaker.html