Minimizando a necessidade do deploy em aplicações web monolíticas

Minimizando a necessidade do deploy em aplicações web monolíticas 1

O fato de termos uma aplicação monolítica não implica na necessidade de executarmos o procedimento de deploy (implantação) a cada pequena alteração. Neste post vou expor algumas técnicas simples e complexas que poderão lhe ajudar a atingir este objetivo.

Como exemplo vou usar o Grails Brasil, pois a esmagadora maioria das técnicas que aqui serão expostas são aplicadas neste projeto, que recentemente tem passado por importantes mudanças conforme evoluímos sua arquitetura.

HTML que pode ser externalizado deve ser externalizado

Em portais como o Grails Brasil é comum termos elementos da página que precisamos alterar com frequência, tal como exposto na imagem abaixo (me desculpem pela grosseria gráfica):

areas_html

Além de áreas como estas, é também necessário incluir trechos que sempre são alterados como, por exemplo, scripts de acompanhamento de tráfego como Google Analytics, propagandas, códigos de identificação do site ou mesmo trechos JavaScript que precisamos alterar com frequência.

São pequenos conteúdos que tornam o procedimento de implantação (por mais automatizado e lindo que seja) demasiadamente caro quando precisamos alterar apenas aqueles pontos.

A solução que adotamos consiste em externalizar estes conteúdos em um repositório centralizado que pode ser desde uma pasta no servidor, um bucket no serviço S3 da AWS, uma tabela em um banco de dados ou qualquer outra tecnologia de armazenamento que nos permita alterar este conteúdo de forma rápida e cômoda sem a necessidade de acionarmos o procedimento de implantação.

Claro que a solução não termina aí. Há casos nos quais o acesso a este repositório é lento, comprometendo o desempenho do site. Como resolver esta situação? Simples: cacheamos este conteúdo. Como mantemos o cache atualizado? Definindo uma data de expiração ou uma URL de limpeza que é acionada por usuários autorizados quando este conteúdo é alterado.

(o mesmo princípio pode ser aplicado a imagens, arquivos CSS e código JavaScript)

Links expostos no menu de navegação

É comum termos em nossos menus de navegação links que apontem para outros sites. No caso do Grails Brasil ocasionalmente precisamos incluir ou remover estes links, tal como ocorre quando, por exemplo, a itexto lança algum treinamento.

Novamente a mesma técnica se aplica: os menus são mais um item de configuração em nosso banco de dados. Conforme incluímos ou removemos registros neste repositório, menus surgem ou desaparecem do site.

Atualmente o link que leva ao blog do Grails Brasil é exposto usando exatamente esta funcionalidade, tal como pode ser visto na imagem abaixo:

menu_grails_brasil

Scripts (linguagens embarcadas)

Se sua arquitetura for bem definida, conforme o tempo passa o núcleo do sistema vai se tornando cada vez mais estável e, com isto, a necessidade de alteração do mesmo diminui significativamente. É o que ocorreu com o Grails Brasil: hoje todo o núcleo do sistema, que é essencialmente o seu mecanismo de processamento de postagens (cases, perguntas e notícias) não requer mais modificações (a última foi feita uns dois anos atrás).

No entanto ocasionalmente ocorre a necessidade de adicionar comportamentos ao redor deste núcleo. Por exemplo: ao finalizar a postagem de uma notícia publicar o evento em alguma rede social. Ao invés de modificar o código fonte do sistema hoje, o que fazemos é disparar eventos específicos para eventos bem definidos no sistema.

Com isto, o evento “postar notícia” dispara o script “disparo_noticia”, que publica algo em uma rede social ou envia um e-mail para alguém. É necessário desativar o envio deste e-mail? Fácil: trocamos o script com a aplicação executando e não precisamos nos preocupar com uma nova implantação.

Este é apenas um exemplo do uso de scripts. Já falei bastante a respeito deste assunto no meu canal do YouTube conforme você pode ver nesta playlist do meu canal.

Plug-ins

Scripts são uma solução excelente quando queremos lidar com eventos, mas e quando precisamos trocar uma regra de negócio ou mesmo adicionar novos módulos ao sistema com ele em execução?

Uma alternativa fascinante e que estamos explorando para uma futura versão do Grails Brasil é a adoção de plug-ins. A ideia é relativamente simples mas muito difícil de ser implementada: novas funcionalidades para o seu sistema são encapsuladas em módulos carregados em tempo de execução pelo seu programa, tal como ocorre o tempo inteiro com sua IDE favorita.

Imagine que em um futuro próximo seja de nosso interesse adicionar um módulo de cadastro de vagas no Grails Brasil (está planejado). Há dois caminhos: podemos incorporar este novo código à base já existente ou implementar um plug-in que seria instalado no servidor. No momento em que este fosse ativado um novo link seria exposto na barra de navegação do site e os usuários teriam acesso a esta nova funcionalidade.

Deu algum problema neste novo módulo (algo extremamente comum em novas funcionalidades)? Fácil: trocamos o plug-in em tempo de execução. É um dos principais ganhos que tanto se fala por aí em arquiteturas baseadas em micro-serviços. A diferença é que você pode ter isto hoje sem eles.

Hoje vejo dois caminhos nesta direção:

  • OSGi – te permite construir estes módulos no formato de bundles, que são carregados dinamicamente pela sua aplicação sem a necessidade desta ser reiniciada. É uma tecnologia maravilhosa e muito madura (existe desde 1999) mas que infelizmente não vemos ser muito divulgada ultimamente.
  • Implementar a sua própria plataforma de plug-ins. É um procedimento extremamente trabalhoso, sendo assim requer uma analise muito bem feita a respeito do custo de construção e implementação.

(há um terceiro caminho também que seria o projeto Jigsaw, mas não tenho o acompanhado já faz algum tempo)

Data sources configurados via JNDI

Outro recurso importante e muitas vezes negligenciado. Se você disponibilizar à sua aplicação a fonte de dados via JNDI, não é necessário (dependendo do seu servidor de aplicação) reiniciar sua aplicação caso, por exemplo, você precise alterar a configuração do pool de conexões ou mesmo trocar completamente de banco de dados.

JNDI não é apenas para data sources

É importante lembrar que JNDI não é usado apenas para se obter um data source. Na realidade, qualquer tipo de objeto pode ser disponibilizado via JNDI. Sendo assim não é difícil imaginar uma arquitetura na qual plug-ins que representem regras de negócio ou mesmo módulos sejam disponibilizados pelo servidor de aplicação através desta interface.

Nunca fiz isto, mas já ouvi algumas experiências positivas nesta direção. É um procedimento raro mas não inviável.

Conclusões

Mostrei neste post algumas técnicas interessantes que possibilitam ao arquiteto projetar soluções nas quais a necessidade de executarmos o procedimento de implantação pode ser extremamente reduzida. Vão desde soluções simples como a externalização de recursos estáticos (HTML, JavaScript, imagens, CSS), passando pela adoção de scripts usando linguagens embarcáveis como Groovy, chegando a soluções mais complexas como a implementação de uma arquitetura de plug-ins e, finalmente, expondo um uso pouco conhecido do JNDI.

Em todas as soluções o problema a ser solucionado é o mesmo: componentização. Se você quer minimizar a necessidade de uma implantação, o foco deve ser no projeto de soluções que tenham um modelo de componente bem definido. Tendo isto, a implantação se torna um evento raro.

(lembrando que componente pode não ser código executável, tal como exemplificado no caso dos recursos estáticos externalizáveis exposto neste post)

Nosso foco atual no projeto “Grails Brasil” é chegar ao momento em que a implantação se torne algo extremamente raro. Ironicamente para chegar a este resultado temos executado implantações diárias nas quais pouco a pouco vamos incorporando nossa própria arquitetura de plug-ins que queremos tornar pública em breve. :)

 

1 comment on “Minimizando a necessidade do deploy em aplicações web monolíticas

  1. Pingback: Semana Groovy 36 em casa nova! | Groovy & Grails Brasil

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.