Microserviços em Machine Learning - Parte 1: Uma (nano)introdução

Este post é uma pequena reflexão sobre uma das melhores palestras do evento The Developers Conference (TDC/2016) de São Paulo que foi a do Gilmar Souza sobre modelos de Machine Learning em produção e de algumas notas do livro do Sam Newman (Building Microservices) além de algumas referências auxiliares.

Um dos assuntos mais discutidos nas comunidades de Data Science/Machine Learning é a atual necessidade da transposição dos modelos stand-alone para ambientes de produção; o que é chamado hoje de Core Machine Learning.

Dessa forma vamos abstrair essa questão da transposição ou não e falaremos direto sobre modelos de arquitetura para Core Machine Learning.

Na palestra do Gilmar ele coloca uma série de potenciais implementações de modelos de ML em produção como (a) re-implementação do modelo via linguagem de programação nativa da plataforma; (b) exportação do modelo em PMML para o ambiente de produção e load em uma suíte de ML para devolver o resultado das predições; (c) Projeção; e finalmente (d) Microserviço que pode ser tanto via chamadas HTTP e/ou REST API dentro de serviços nativos e/ou plataformas de Machine Learning as a Service como Google Prediction, Azure Machine Learning ou Amazon Machine Learning.

A principal diferença de abordagem em termos de Core ML é que no item (a) o algoritmo de ML é totalmente embutido no sistema de produção e na abordagem (d) há uma estrutura auxiliar separada para realizar esse tipo de tarefa, que no caso é o Microserviço.

Mas a primeira pergunta que fica é: O que são os microserviços?

De acordo com o Sam Newton os microserviços é uma abordagem para sistemas distribuídos que promove o uso de serviços mais granulares com os seus próprios ciclos de vida.

Da perspectiva do Sam, esses microserviços são modelados ao redor de domínios de negócios para evitar os problemas das tradicionais arquiteturas monolíticas, isto é, arquiteturas que consideram um sistema único com todos os seus módulos em uma única aplicação.

[caption id=”” align=”alignnone” width=”640”] Então, sabe aquele mel gostoso que você consome? Ele é totalmente feito em uma estrutura de microserviços. Foto: My honey supers by Mandie[/caption]

Buscando uma outra definição, agora do lendário Martin Fowler e do James Lewis, traduzido do blog do Pedro Mendes temos uma ideia de como é o design dessa arquitetura:

[…] (O) microsserviço é uma abordagem [1] para desenvolver uma única aplicação como uma suíte de serviços, cada um rodando em seu próprio processo e se comunicando através de mecanismos leves, geralmente através de uma API HTTP. Estes serviços são construídos através de pequenas responsabilidades e publicados em produção de maneira independente através de processos de deploys automatizados. Existe um gerenciamento centralizado mínimo destes serviços, que podem serem escritos em diferentes linguagens e usarem diferentes tecnologias para armazenamento de dados.[…]

Vamos ver na prática como seria essa diferença em termos de arquitetura de uma estrutura monolítica seja para outra de microserviços na figura abaixo:

Referência: http://www.martinfowler.com/articles/microservices.html

Como podemos ver, cada elemento/funcionalidade da plataforma/sistema na estrutura monolítica é inserida dentro da aplicação como um todo; já nos microserviços esse funcionalidades são replicadas e isoladas ao longo dos servidores e usadas conforme a necessidade.

Em linhas gerais o que é definido nessa arquitetura é que esses sistemas distribuídos atuam de forma autônoma dentro de um determinado espectro de pequenas atividades específicas através de um serviço.

Extendendo um pouco mais esse conceito, vamos usar alguns dos pontos principais das definições do Sam Newton das características dos microserviços que são:

(a) são sistemas pequenos e focados em fazer bem uma única coisa, isto é, há uma coesão dentro do domínio do negócio no qual o serviço está atrelado; e

(b) baixo acoplamento, o que na prática significa que a manutenção nessa abordagem não afeta o sistema como um todo e sim somente um pequena parte;

Quando falamos de sistemas monolíticos distribuídos logo vem a mente o clássico livro do Michael Feathers chamado Working Effectively with Legacy Code (tradução livre: Trabalhando com código legado) que é uma bíblia para quem trabalha com código/arquiteturas não tão bem desenhadas que constantemente tem problemas de bugs, interdependências desnecessárias, complexidades escondidas o que deixa qualquer atividade de incorporação de novas features ou refactoring um verdadeiro pesadelo que se torna realidade.

E se pensarmos que na grande parte das vezes não estamos nem construindo software novo, mas sim colocando 90% do nosso esforço para manutenção de código antigo não soa tão mal assim pensarmos que faz sentido a adoção deste tipo de arquitetura de microserviços.

Uma das principais características no que se refere aos microserviços é que o isolamento do deployment (e por consequência a autonomia que o sistema tem por conta desse isolamento) é que se ao mesmo tempo o sistema/plataforma legada não é afetado por modificações, com os microserviços a manutenção tende a ganhar uma escala muito maior em termos de volume e administração (óbvio que se tratando de tecnologias de Continuous Integration há tecnologias como Chef e o Jenkins que fazem muito bem esse papel, mas prática é uma questão muito mais complexa de sincronização, orquestração e janelas de deployment; ou seja: não existe resposta fácil aqui).

Nem tudo são rosas quando falamos de microserviços. Se considerarmos alguns pontos do próprio Martin Fowler podemos ver que os microserviços ainda tem alguns calcanhares de Aquiles que são:

(a) aumento da complexidade de mecanismos de tolerância à falha (no caso o Netflix tem até uma aplicação para forçar isso de maneira arbitrária para aumentar a resiliência de suas plataformas);

(b) com maior volume de pequenos serviços distribuídos a parte de disponibilidade passa a ser muito mais crítica e difícil de lidar, o que coloca uma pressão altíssima nas questões de monitoramento e alarmística (o que no caso será um aumento violento da quantidade de alertas sobre jobs, fluxos de sincronização e orquestração em casos que se fosse em um sistema monolítico um time de Dev Ops poderia trabalhar com muito mais foco e minimizar o RTO e o RPO).

Na prática, assim como o número de serviços aumenta, os pontos de falha aumentam multiplicam-se na mesma velocidade;

(c) aumento da latência entre aplicações. Na prática funciona assim: uma coisa é um contexto de 200ms de tempo de resposta em uma arquitetura com um baixo grau de requisições com apenas um módulo de microserviço; outra completamente diferente é ter esses mesmos 200ms através de uma pilha de 6 aplicações interdependentes com mais de 120 milhões de requisições por dia;

(d) heterogeneidade do stack de tecnologia. Em alguns casos os sistemas monolíticos tem (ou ao menos deveriam ter) uma espécie de lingua franca para a construção da plataforma/sistema. Já com os microserviços, como vimos anteriormente eles tem um isolamento que restringe (minimiza) o impacto em plataformas adjacentes; mas que no entanto podem não obedecer algum tipo de padrão de tecnologia. Na prática, você pode ter um stack com um serviço escrito em Java, outro em Elixir, outro em Clojure, alguns até mesmo em Erlang.

Na prática isso é extremamente difícil de trabalhar, o que demanda um tempo maior de desenvolvedores full stack dado que essa abordagem pode em algum grau aumentar o número de redundâncias desnecessárias, limitar a produtividade e de quebra promover ainda mais a epidemia de desenvolvedores Resumé Driven que escolhem a melhor tecnologia para os seus respectivos CVs mas que deixam (muitas) pequenas bombas relógio nas aplicações/sistemas/plataformas mundo a fora.

Agora que temos a definição bem generalista do que é um microserviço, em um próximo post vamos explorar essa ideia para aplicações de Machine Learning dentro desse mesmo universo.

Palestra do Gilmar Souza no TDC 2016 Trilha Machine Learning

[slideshare id=64410358&doc=tdc2016-machinelearning-gilmar-160726194923]

Uma ótima referência sobre ML em produção

[vimeo 181931334 w=640 h=360]

Machine learning at NRK: From prototype to production: Øyvind Holmstad, Thomas Oldervoll from JavaZone on Vimeo.