Circuit break: Resiliência em arquitetura microservices

Quando entrei no iCasei, lá em 2016, a palavra que mais se ouvia falar no escritório era: MicroServices, como se fosse a solução para os problemas da empresa.

Sim, adotar essa arquitetura para todos os nossos novos serviços trouxe muitos benefícios para nossa área de desenvolvimento, mas cara, como deu trabalho manter tudo trabalhando em conjunto e operando numa boa, sem gargalos.

Ta bom, você ainda não esta ligado no que significa MicroServices?
Vou dar um resumão então:

MicroServices

É uma forma de desenvolver software onde você tenta quebrar sua aplicação em N serviços que teoricamente precisam ter apenas uma responsabilidade e que quando requisitados, grande parte das vezes através de chamadas utilizando o padrão Restful, forneçam as informações necessária para todos consigam se comunicar.

Benefícios

A galera vem adotando esse modelo de desenvolvimento por esses motivos:

Escalabilidade

Com serviços espalhados, você consegue, por exemplo, escalar horizontalmente apenas da API que cuida do upload de fotos para o album, uma vez que chegaram a conclusão que ela é a que mais consome recursos em determinado momento do dia.

Deploys menos traumáticos

Como sua aplicação esta toda quebrada em pequenos pedaços, a equipe consegue realizar pequenos deploys sem afetar todas funcionalidades do sistema

Entrega contínua

As equipes conseguem trabalhar em paralelo uma vez que você não tem serviços e projetos muito dependentes.

Manutenção mais fácil

Quem nunca ficou com medo do cA$@%#$@ de alterar uma linha de código e quebrar várias funcionalidades de um legadão brabo?
Se você tem várias aplicações bem pequenas o impacto sempre vai ser menor.

Resiliência, cada segundo é muito tempo

Daora, são muitos os benefícios de se adotar essa arquitetura, né?

Se você está afim de encarar a brincadeira e começar a criar seus serviços, não se esqueça de uma coisa: Você pode e vai sofrer com problemas de rede(tempo de resposta).

Como 1, 2 segundos a mais no tempo de resposta de uma API fazem uma diferença absurda no teu eco-sistema, chegando ao ponto de ficar tão instável que muitos serviços não conseguem parar de pé devido ao empilhamento de processos que ficam esperando, esperando, esperando…até tudo cair.

É ai que entram a tal da tática Resiliência!

Quando um serviço sair do ar ou demorar demais para responder, tua aplicação precisa de uma alternativa para tratar esse erro até que tudo volte ao normal, senão, ela também pode cair.

Como já é de se esperar, outras pessoas já passaram pelo mesmo problema e criaram um padrão para que todos possam utilizar em seus projetos.

Circuit Break

Martin Fowler já escreveu um pouco sobre o assunto em seu blog e a ideia consiste em ficar monitorando um bloco de código esperando possíveis falhas. Quando o número de falhas chegar no limite configurado pelo desenvolvedor o circuito é aberto e as próximas requisições da fila não irão executar o bloco por um tempo também pre-definido.

Para fazer a decisão de quando executar ou não o bloco o Pattern Circuit Break utiliza 3 propriedades que devem ser sempre configuradas:

failure_threshold

Quantas falhas devem ocorrer para que o circuito seja aberto?

duration

Por quanto tempo as requisições não irão executar o bloco com falha?

timeout

Qual o tempo de resposta limite que um bloco pode demorar para então explodir a Exception?

Exemplo prático

Para quem trabalha com Rails, existe um Gem chamada circuit_breakage que já tem toda uma implementação do Pattern e vou utiliza-la para mostrar como tudo funciona, beleza?

No final do artigo tem o link do repositório no Github para quem quiser brincar um pouco.

No GemFile adicionei a chamada da para a circuit_breakage

gem ‘circuit_breakage’

Criei uma classe na minha API chamada list_posts.rb que vai ser responsável por realizar o Request para buscar os posts.

class ListPosts
include Singleton
API_POSTS_URL = ‘https://jsonplaceholder.typicode.com/posts’
….

Aproveito para instanciar meu Circuit Break no construtor da classe e configurar o limite de falhas, duração e timeout.

def initialize
@circuit_breaker = CircuitBreakage::Breaker.new
@circuit_breaker.failure_threshold = 2
@circuit_breaker.duration = 3
@circuit_breaker.timeout = 3
end

Feito isso, crio um método chamado request_posts que realiza uma requisição HTTP e faz o parse da resposta:

def request_posts
response = RestClient.get API_POSTS_URL
JSON.parse response.body, symbolize_names: true
end

E crio dois métodos para salvar resultado em uma chave no cache do Rails:

def to_cache(posts)
Rails.cache.write(‘posts’, posts)
end

def posts_cached
Rails.cache.read(‘posts’)
end

Para orquestrar tudo isso crio o método execute:

def execute
posts = []

begin
@circuit_breaker.call do
posts = request_posts
to_cache posts
end
end
rescue CircuitBreakage::CircuitOpen
posts = posts_cached
rescue CircuitBreakage::CircuitTimeout
posts = posts_cached
end

posts
end

Como vocês podem perceber, realizei a chamada do método request_posts em um bloco dentro do meu Circuit Break, ou seja, caso o Request ultrapasse o limite de timeout que informei lá na instancia, o circuito vai alterar a sua propriedade state para Open e todas as requisições vão buscar a informação no cache fornecido pelo método posts_cached.

Na Controller, não tem nenhum mistério, apenas utilizo minha instancia do ListPosts para pegar os posts e repassar via JSON.

def index
posts = ListPosts.instance.execute
render json: posts
end

Fiz um teste unitário para provar que o negócio funciona:

describe ‘list_posts’ do
it “when execute success” do
posts = ListPosts.instance.execute
expect(posts.length).to_not eq(0)
end

it “when to_cache received” do
expect(ListPosts.instance).to receive(:to_cache)
ListPosts.instance.execute
end

it “when circuit is open” do
ListPosts.instance.circuit_breaker.timeout = 0.1
ListPosts.instance.execute

expect(ListPosts.instance.circuit_breaker.state).to eq(‘open’)
end
end

O que eu fiz foi diminuir muito limite de tempo de resposta induzindo o erro e assim consigo validar se o circuito realmente mudou seu estado para Open.

Bom, é isso, espero que gostem, é uma prática que me ajuda e pode te ajudar muito nos projetos que vier enfrentar pela frente. O source completo esta lá no meu Github, beleza?

Para acessar, clique aqui.

 

Claro, não esquece de dar uma olhadinha lá no Clube do Código, olha o último Meetup que saiu:

O que te limita? – Camila Primasi
Não é segredo. A área de tecnologia da informação (TI) é composta por muito mais homens do que mulheres, fazendo com que elas tenham de lidar, todos os dias, com situações de preconceito e, muitas vezes, exclusão….

ImageBoss: gerando thumbs de forma inteligente.

Dias atrás estava travado em mais um daqueles problemões, que a gente sempre enfrenta quando decide colocar uma ideia em prática.
Esse não foi o primeiro que encontramos pela frente aqui no Clube do Código…

Já sei…vou fazer aquela ligação direta para Portugal, mais precisamente Lisboa, para trocar aquela ideia com meu grande amigo Igor Escobar e quem sabe entre os vários assuntos que irão surgir ele resolva meu problema como sempre.

O final a gente já sabe, o erro estava na minha cara, como acontece com a grande maioria dessas “tretas brabas” e só de sair um pouco do foco e falar sobre outras tecnologias o negócio clareou…

Bem vindo ao mundo ImageBoss

Nesse vai e vem de assuntos Igor me apresentou seu mais novo projeto(filho) o ImageBoss, que tem como objetivo tomar conta do processamento e entrega das imagens do teu site para você.

On-demand image processing.

Grande parte dos sites hoje em dia em algum momento da sua vida vai precisar gerar algum thumb, nem que seja para exibir a foto do perfil de um usuário, não tem como escapar.

É na hora que o ImageBoss entra no jogo!

Através de parâmetros configurados via url você consegue processar o thumb do teu usuário para infinitos tamanhos ex: [200×200], [350×350] e aplicar efeitos como Blur e Grayscale.

Saca só:

antes
antes
depois
depois

 

https://service.imageboss.me/cover/150×150/grayscale:true/http://imageboss.me/examples/01.jpg

O que fizemos nessas poucas linhas de comando foi utilizar 3 efeitos diferentes para gerar uma thumb perfeita, vou explicar:

Cover

Esse filtro é doidão…ele encontra o ponto mais importante da foto na hora de gerar o thumb. No exemplo utilizamos uma foto onde o casal esta no canto direito da foto e a nova imagem de [150×150] foi gerada com os dois no centro.

Largura x Altura

No caso estamos definido que a imagem processada terá 150 de largura e 150 de altura. Existe a possibilidade de definir apenas a largura ou só altura, mas vou deixar essa parte contigo, ele explicou tudo lá no docs.

Grayscale

O próprio nome já diz, simples e didático: grayscale:true  e pronto, sua foto esta em preto e branco.

CDN

Todos nós aqui sabemos da importância de utilizar uma CDN hoje em dia, certo?
Essa é uma das features que estamos utilizando aqui no Clube do Código e acho que é umas das mais importantes pelo custo/benefício.
Caso ainda exista algumas dúvidas, vou explicar:

Latência

Imagina o seguinte: teus clientes estão aqui no Brasil e teu site está hospedado lá na China, o download das imagens para essa galera vai demorar um pouco né?
Com sua imagem hospedada em uma CDN ela vai estar distribuída geograficamente, ou seja, sempre que for requisitada ela vai ser entregue pelo servidor mais perto possível do cliente.

Downloads paralelos

Os navegadores não gostam de fazer download de muitos arquivos do mesmo domínio, causando aquele travamento de tela, atrapalhando a experiência do usuário e ferrando até mesmo o SEO da página.

Para driblar isso a galera gosta de servir JS, CSS e imagens de domínios diferentes do principal, deixando o carregamento do site muito mais rápido e fluido.

Cache

Uma vez que o Cliente 1 requisitou a imagem, na próxima vez que ele entrar no site, ao invés, de processar e aplicar todos os filtros novamente o navegador vai utilizar uma versão salva em cache para exibi-lá sem nenhum custo de processamento.

Progressive Images

Essa também estamos utilizando e melhora muito a experiência do usuário.

Imagina que você tem uma imagem com uma qualidade muito boa, mas sempre demora muito para ser entregue para seus usuários. Será que se ela não for aparecendo aos poucos o usuário não vai ficar tão irritado?

Essa é a ideia da Progressive Images, vou deixar um exemplo para ficar mais claro:

processando...
processando…
carregada
carregada

 

É coisa pra caramba, né? E não falei sobre a compressão que ele faz nas imagens, mas dai fica contigo conhecer um pouco mais do serviço, tu pode testar por 10 dias!

Entra lá!

Crie aplicações mais rápidas utilizando Redis

Aprender, esse foi o verbo que mais conjuguei desde que entrei no iCasei, muito se deve por ter trocado Microsoft por Ruby on Rails, que é uma mudança “pesada” vamos concordar? Resumindo…hoje me encontro melhor em um terminal cheio de comandos do que em um Wizard de instalação repetitivo e chato!

Voltando ao assunto…outra coisa valiosa que aprendi lá foi em como saber trabalhar com cache é extremamente importante.

Mas porquê cara?

  • Só assim para aguentar um volume alto de acessos
  • Você ganha performance (teu site fica rápido pra ca$#@$@)
  • A conta da AW… fica mais barata no final do mês

Como a mágica funciona?

É como se você criasse um atalho para uma informação específica, entende?
Ao invés de procurar uma conexão com o banco, executar uma consulta e esperar a resposta você guarda esse dado em uma chave no cache que pode estar salvo em um arquivo físico na própria aplicação (In-Process) ou até em um Redis ou Meamcached (Distributed Cache).

In-Process

Acho que todas as linguagens tem um provider de FileSystem nativo para armazenar informações em cache e que pode te ajudar muito dependendo da situação. A ideia é gerar um arquivo físico em uma pasta temporária da aplicação para facilitar o acesso via IO, mas essa opção pode gerar um aumento significativo de processamento da máquina.

Distributed Cache

Em algumas situações você vai querer compartilhar esse atalho entre aplicações e ai que o Cache Distribuído entra na história.
Imagina o seguinte, no iCasei o casal de noivos vai criar todo o site do casamento em poucos dias… ele vai subir imagens, textos, informar o local da festa e estilizar cores e depois só os convidados que vão entrar admirar o site e muitas das vezes comprar um presente.
Preciso ficar sempre perguntando lá no banco de dados como é o site do casamento?

Não! Vamos criar um atalho para que a aplicação que exibe o site não precise ficar consumindo tanto hardware assim. Mas e se o casal resolver mudar alguma informação?

Tudo tranquilo, como meu cache está armazenado de forma distribuída, quando o casal alterar a informação na aplicação Painel, vamos limpar essa chave e a outra aplicação que renderiza o site customizado vai recria-lá com os dados atualizados e vai seguir assim até que a aplicação Painel limpe a informação novamente.

Opções do mercado

Vamos falar sobre Redis nesse artigo, mas não existe só ele no mercado e dependendo do que você pretende fazer, talvez nem seja a melhor opção, resumindo, não existe bala de prata, para cada situação uma tecnologia vai se comportar melhor do que outra e por isso resolvi abrir um tópico para “comparar” os dois mais conhecidos do mercado.

Memcached

O Memcached foi desenvolvido inicialmente por Brad Fitzpatrick para seu site em 2003 o  LiveJournal tem como princípio a arquitetura cliente-servidor onde o cliente sempre vai buscar a chave que procura. Para ficar rápido ele resolveu salvar essas informações em memória RAM, ou seja, pouco custo de hardware para encontra-las.

Redis

O Redis foi criado por Salvatore Sanfilippo em 2009 e em muitos momentos o consideram um banco NoSql.  Tem suporte para diversos Clients e também se beneficia da memória RAM para buscar as informações de forma rápida, mas pode facilmente ser configurado para trabalhar com dados persistentes.

Comparando…

Redis Memcached
Modelo chave/valor Sim Sim
Salvam em memória Sim Sim
Pouca latência Sim Sim
Compatível com n/linguagens Sim Sim

Coisas legais do Redis

Aqui estão listados alguns dos motivos pelos quais muitos desenvolvedores vem escolhendo o Redis para trabalhar:

  • Dados estruturados (lists, sets, sorted sets, bitmaps…)
  • Master/Slave e Sentinel (crescimento horizontal)
  • Binary safe (muito mais espaço)
  • Single-threaded (um de cada vez)
  • Push/Pop (integração com Sidekiq, Resque, RestMQ…)
  • Pubsub nativo (Action Cable do Rails 5 se beneficia disso)

Operações atômicas

Sem dúvidas essa é uma das características mais importantes do Redis e entender ela pode te ajudar bastante na hora de decidir como escalar sua aplicação.

Por ser Single-threaded o Redis executa uma operação de cada vez, ou seja, nada é executado paralelamente. Isso faz com que seu core seja mais simples por não precisar lidar com concorrências e sync de informações.

Sabendo disso, quando trabalhar com Redis tenha em mente que para ter uma boa performance muitas vezes você vai precisar escalar sempre de forma horizontal, ou seja, mais maquinas trabalhando para executar mais operações.

Para conseguir fazer o shared das informações entre os nós o Redis pode ser configurado para trabalhar com Master/Slave + Sentinel, mas isso vai ficar para um próximo post, beleza?

Porque escolheu o Redis?

Escolhemos ele por dois motivos:

Dados estruturados  – ajudam muito na hora de incrementar números, salvar listar e  não ter a necessidade de realizar uma conversão implícita para isso.

O que isso quer dizer?

Nas outras opções do mercado você vai buscar a informação salva em texto e se isso for um array ou um inteiro, antes de trabalhar com o dado uma conversão necessariamente precisa ser realizada.

Push/pop – Enfileiramos os envios de  push notification e e-mails no Sidekiq que é uma boa pratica para remover a carga de ações que precisão ser rápidas e ficar esperando um e-mail ser enviado não é tão legal.

Instalação

https://redis.io/download

$ wget http://download.redis.io/releases/redis-4.0.1.tar.gz
$ tar xzf redis-4.0.1.tar.gz
$ cd redis-4.0.1
$ make

redis-cli

Já vem na instalação e é um client em linha de comando para você realizar consultas, criar e deletar chaves.

redis-cli -h 127.0.0.1

Alguns comandos…

Setando e buscando informação

$ redis> set casamento:1 ‘Evandro e Evandra’
$ redis> get casamento:1
$ redis> incr contador
$ redis> get contador

Encontrando chaves….

$ redis> keys *
$ redis> keys ‘casamento:*’

Limpando informações

$ redis> flushall
redis> del ‘casamento:1’

Benchmarks

https://redis.io/topics/benchmarks

Esse é bem legal para quem quer medir a performance da instancia, no exemplo abaixo estamos realizando um teste com 1000 requisições utilizando 10 clients diferentes para isso:

$ redis-benchmark -n 1000 -c 10

Conectando aplicação Rails

Agora vou mostrar como é simples colocar o Redis para trabalhar junto com uma aplicação Rails.
Para entender o exemplo você precisa saber o básico de Ruby on Rails como por exemplo o que é uma RubyGem e um pouco da estrutura de pastas e como funciona o carregamento de uma aplicação RoR.

Gemfile

Vamos instalar a gem redis-rails que vai nos fornecer os providers para realizar a comunicação com o servidor Redis.

gem ‘redis-rails’

Configurando acesso

Agora vamos criar um arquivo chamado redis.yml dentro da nossa pasta /config.
No modelo yml abaixo estamos dizendo onde encontrar o Redis dependendo do ambiente que a aplicação estiver rodando.

development:
host: 127.0.0.1
port: 6379
test:
host: 127.0.0.1
port: 6379
production:
host: sua-host
port: 6379

Instanciando uma variável global

Vamos criar um arquivo chamado redis.rb em /config/initializers/ com isso nossa variável global $redis será instanciada no momento que a aplicação for inicializada.

Buscamos o arquivos de configuração e convertemos ele salvando na constante REDIS_CONF e depois utilizamos os dados para instanciar a classe Redis.

REDIS_CONF = YAML.load_file(File.join(Rails.root, “config/redis.yml”))[Rails.env]
$redis = Redis.new({
host: REDIS_CONF[“host”],
port: REDIS_CONF[“port”])

Pronto, agora é só utilizar

Vamos criar um método que realiza um Request (que é uma ação bastante custosa) para buscar o total de comentários enviados.

def countComments(url)
length = 0
begin
response = RestClient::Request.execute(method: :get, url: url)
if response.code == 200
length = JSON.parse(response.body).length
end
rescue => e
Rails.logger.error(e.backtrace)
end
length
end

Agora, na exibição dessa informação em uma View por exemplo, vamos primeiro perguntar para o Redis se ele tem essa informação antes de executar o Request.

def index
@totalComments = $redis.get(“totalComments”)
if @totalComments.nil?
if $redis.set(“totalComments”, countComments(‘https://jsonplaceholder.typicode.com/comments’))
@totalComments = $redis.get(“totalComments”)
end
end
render layout: nil
end

O que fizemos aqui foi tentar poupar um pouco de processamento indo buscar uma informação que não vai mudar com frequência na memória ao invés de sempre ter que perguntar para a API quantos comentários existem.

Estamos preparando um curso online aqui no Clube do Código sobre tudo isso, fiquem ligados!

Já assistiu as últimas meetups que gravamos?

 

Escrito por: Evandro Passos – CTO no Clube do Código e Ruby on Rails Developer no iCasei

Delete o Facebook!

“Delete o Facebook” – Esse foi o conselho pelo fundador do WhatsApp para a galera depois do escândalo do roubo de dados de mais de 50 milhões de dados de usuários do Facebook.

Entenda o caso

Sábado foi noticiado que a empresa Cambridge Analytic utilizou de forma indevida dados de mais de 50 milhões de usuários, principalmente para a campanha política de Donald Trump nos EUA.
Com isso o Facebook já perdeu US$ 49,2 bilhões em valor de mercado só essa semana e quem mais perdeu com isso foi  Mark Zuckerberg que além de fundador é o detentor de maior parte das ações da empresa.

Como conseguiram os dados

Cambridge Analytic conseguiu reunir esse volume de informação de uma forma muito simples, eles criaram alguns anos antes um Aplicativo na plataforma que remunerava os usuários que respondessem um Quiz que inicialmente seria utilizado de forma acadêmica, coisa que não aconteceu. No final aproximadamente 360 mil pessoas responderam e tiveram seus dados e de todos seus amigos na rede coletados e utilizados para entender e mandar notícias para induzir votos nas eleições.

O mais intrigante é que até agora Mark não se pronunciou sobre o escândalo, até os funcionários do Facebook não sabem responder onde ele está.

Vamos aguardar os próximos capítulos…

Últimos cursos do Clube:

Mulheres na Tecnologia : Margaret Hamilton

Margaret Heafield Hamilton – cientista de computação responsável por desenvolver o conceito moderno de software e criar o programa de voo utilizado na Apollo 11 (a primeira missão tripulada à Lua).

Em 1960, as mulheres não eram encorajadas a estudar assuntos técnicos ou computação, porém isso não foi um empecilho para que Hamilton se aprimorasse. Com apenas 24 anos, ela foi trabalhar como programadora no MIT, o Instituto de Tecnologia de Massachusetts, depois de obter um diploma em Matemática. Nesse período, o Projeto Apollo foi lançado pela NASA, e toda a ajuda de engenheiros, programadores e matemáticos estava sendo requisitada.

Logo Hamilton estava dentro do projeto, contribuindo em um dos laboratórios do MIT com os códigos de voo que seriam necessários para levar o homem à Lua. Hamilton levava a pequena filha Lauren (de somente 4 anos) ao escritório nos finais de semana e quase todas as noites para poder trabalhar mais na programação da Missão Apollo 11.

Continuar lendo:
https://www.tecmundo.com.br/nasa/88012-margaret-hamilton-mulher-que-homem-pisasse-lua.htm