A stack BrazilJS

Em:

Começar algo do zero é tão divertido quanto é complicado, e foi bem assim que montamos o ambiente para rodar as aplicações que hoje formam uma pseudo-plataforma BrazilJS. Neste post vou tentar listar tudo o que foi feito e como foi feito para subir o CMS BrazilJS, o Blog BrazilJS e mais umas pequenas ferramentas.

Hosting

Depois de pesquisar as variadas soluções de mercado, optamos por usar a Digital Ocean. O principal fator decisório foi o fato do serviço da Digital Ocean ser realmente muito simples de usar. Além disso, a documentação é fantástica e na grande maioria dos casos o problema com a solução já está documentado. Isso facilita e muito a vida de quem não tem tanta experiência com essa parte de infra-estrutura e servidores. O preço também é bem acessível, estamos pagando cerca de $10 (dólar) mensais com o sistema de backup ativado, o que é bem interessante, pois não precisamos nos preocupar em instalar ferramentas de backup, agendar scripts, etc.

Servidor

Nossas aplicações foram desenvolvidas com Node.js, então obviamente o Node.js precisa estar rodando no servidor. Usamos uma solução for dummies, as chamadas “One-click apps” que a Digital Ocean oferece. Nesse caso a imagem utilizada foi a node v4.2.4 on 14.04, que vem com o Ubuntu server 14.04. One-click apps Digital Ocean Com isso, o primeiro passo foi dado. Um servidor Ubuntu + Node.js rodando em poucos minutos.

Gerenciamento e Deploy

Mesmo não tendo muita experiência com o deploy de aplicações Node.js, queríamos ter ao menos o básico. Em outras palavras, uma solução simples para colocar novas versões das aplicações no ar. Atualmente muito se fala do Docker, e com razão. É uma solução incrível que em breve devemos adotar na nossa stack. A solução atual foi um pouco mais simples, optamos por usar o pm2. O pm2 nada tem a ver com o Docker, mas ele possui uma opção de deploy bem simples que nos agradou bastante. A principal função do pm2 é gerenciar aplicações Node.js. Vejam na imagem abaixo um exemplo em produção do pm2 gerenciando nossas aplicações. pm2 BrazilJS O pm2 nos dá uma série de recursos interessantes, como por exemplo levantar e monitorar aplicações Node.js. Veja como o nosso blog é iniciado com o pm2: shell
NODE_ENV=production pm2 start /path/to/app/index --name braziljs-blog
Ao executar esta linha, o pm2 passará a gerenciar essa aplicação, de forma que conseguimos executar ações bem úteis, como reiniciar a aplicação, parar, matar, monitorar, ver os logs, e muito mais.

Com o pm2, o deploy se torna uma tarefa trivial. Bastou criar um arquivo chamado ecosystem.json na raíz do projeto ( é possível executar pm2 ecosystem para gerar automaticamente), configurar algumas coisas e pronto. Existem alguns outros passos de configuração que podem ser vistos na documentação sobre deploy do pm2, mas o que importa é que no final basta rodar o comando: pm2 deploy ecosystem.json production. Deploy feito. Um ponto que vale mencionar aqui é a configuração das chaves SSH. Estamos utilizando o Bitbucket, e para fazer o deploy funcionar corretamente foi preciso criar uma chave pública no servidor onde as aplicações estão rodando e adiciona-la no Bitbucket. A chave pública local (desenvolvimento) precisa ser adicionada na lista de hosts conhecidos no servidor.

Nginx

Uma boa prática para aplicações desenvolvidas com Node.js é usar o Nginx como ponto de entrada. Isso é bom por vários motivos, um deles é o fato de poder delegar menos tarefas ao próprio Node.js. Por exemplo, a entrega de arquivos estáticos pode ser feita sempre pelo Nginx, dando um bypass total na aplicação Node.js.

Usando um proxy-reverso do Nginx conseguimos definir rotas para cada aplicação Node.js. Isso também nos da a possibilidade de escalar as aplicações, fazendo o Nginx funcionar como um load-balancer no futuro.

Nosso arquivo (/etc/nginx/sites-available/default) de configuração ficou mais ou menos assim: `\ server { listen 80;

server_name braziljs.org;

location / {
    proxy_pass [URL PRIVADA NODE APP];
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

} Para servir arquivos estáticos sem passar pelo Node.js, bastou adicionar mais um `location`: location /public { root /path/to/public; } `\ Desta maneira, sempre que o path path/to/public for requisitado, o Nginx será o responsável pela entrega dos arquivos.

Memcached

Mais uma boa prática quase que obrigatória em qualquer aplicação Web é o uso de alguma solução de cache. O Memcached é uma solução free e open-source, de alta performance, de um sistema distribuído de cache em memória. Tanto a instalação/configuração e uso nas nossas aplicações Node.js foram bem tranquilas. Utilizamos o módulo memcached que parece ser a solução mais eficaz no mundo Node.js. Abaixo segue um exemplo de como fizemos cache em uma das seções do CMS BrazilJS: `\js var Memcached = require(‘memcached’); var mc = new Memcached(‘URL DO MEMCACHED:PORTA’, { maxExpiration: 60, timeout: 2500 });

mc.get(‘eventsList’, function(err, data) { // Sem cache, vai ir na aplicação Node.js if (!data) { // … // Adiciona no Memcached mc.set(‘eventsList’, locals.events, 60, function(err) { if(err){ console.error(‘Failed setting memcached [EVENTS]’, err); } else { console.log(‘Stored in memcached [EVENTS]’); } });

// Dados no Memcached } else { // Usa o valor da variável data } }); `\ Com poucas linhas de código em pontos estratégicos de cada aplicação, conseguimos ter um ganho de performance expressivo. Obviamente ainda temos muito a melhorar nessa questão, mas estamos no caminho 🙂

Ghost

Ghost Escolhemos o Ghost como plataforma para os nossos artigos. Alguns fatores influenciaram a escolha. Um deles é o fato do Ghost ser uma solução Node.js. Já que o nosso stack estava pronto e configurado, nada melhor do que usar uma ferramenta fácil de plugar. Além disso, a interface do Ghost para os autores é muito boa, e essa era uma premissa. Obviamente o Ghost têm algumas falhas, uma delas sendo a falta de uma API para interagir com a plataforma. Por esse motivo acabamos criando uma ferramenta bem simples de scraping, para poder ter a liberdade de listar os artigos em nossas páginas do CMS. Tivemos também problemas com o envio de emails através do Ghost. Depois de dias perdidos, acabamos encontrando a solução, que basicamente era alterar a porta.

KeystoneJS

KeystoneJS Como solução para o nosso CMS acabamos escolhendo o KeystoneJS. Existem diversas soluções e frameworks legais para Node.js, mas o Keystone foi o favorito por alguns motivos:

  • É um projeto open-source e bem ativo
  • Fácil e rápido de aprender, além de ser bem flexível
  • Database-driven
  • Fácil de criar APIs
  • Admin gerado baseado nos models da aplicação

Swap

Uma pequena dor de cabeça que tivemos, devido a falta de conhecimento, foi com o nosso CMS baseado no KeystoneJS. Ao dar o start em uma aplicação KeystoneJS, o processamento e o uso de memória é bastante elevado. O problema que enfrentamos foi o constante uso do processador, chegando a 90% em cada hit da aplicação. Depois de muita pesquisa e estudo, chegamos a solução: Swap. Swap é um espaço em disco dedicado a memória virtual, e por padrão a máquina Ubuntu da Digital Ocean não cria esse espaço. Depois de descobrir que o problema era esse (pedimos ajuda no Gitter do KeystoneJS), o problema foi facilmente resolvido.

Open-source

Ainda não liberamos nenhuma das soluções devido a falta de documentação, testes e uma série de fatores que julgamos necessários para abrir um projeto. Com o tempo vamos melhorar isso e cada parte desse pequeno mundo que criamos será aberto para a comunidade. Outro fator é que até agora pouca coisa de fato foi desenvolvida que mereça se tornar um projeto Open-source. Nada demais têm em um CMS, em um tema para um blog, etc. Mas claro, esse é apenas o primeiro passo. Com a evolução novos projetos virão e o processo natural é que tudo seja aberto. A exceção aqui é o pequeno serviço de scraping que desenvolvemos, que sim, pode ser útil para a comunidade. Em breve ele estará disponível.

Conclusão

Esse foi um resumo do que fizemos até aqui, em breve farei mais alguns posts relacionados a stack e aos projetos em si, com mais detalhes técnicos, etc. A ideia desse post foi compartilhar o que está por trás dos nossos projetos, como fizemos e quais foram os problemas encontrados durante o desenvolvimento.

Referências

Deploy PM2: http://pm2.keymetrics.io/docs/usage/deployment/

Node.js, PM2, Digital Ocean: https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps

SSH keys Digital Ocean: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-droplets

SSH issues Bitbucket: https://confluence.atlassian.com/bitbucket/troubleshoot-ssh-issues-271943403.html

Node.js em produção na Digital Ocean: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-14-04

Ghost na Digital Ocean: https://www.howtoinstallghost.com/how-to-install-ghost-on-digital-ocean-vps-old/

Swap na Digital Ocean: https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04

Performance Node.js: https://www.nginx.com/blog/5-performance-tips-for-node-js-applications/

Ghost timeout error: http://onemobdev.com/blog/2015/08/14/ghost-etimedout-error-digitalocean/

Foto no topo da página por coniferconifer

  • Weekly #182 – V8 e o WebAssembly, DevTools e mais sobre performance e PWAs

    A BrazilJS Weekly é a seleção semanal que reúne as novidades sobre o desenvolvimento Web no Brasil e no mundo. Ainda não é inscrito? Faça o seu cadastro e receba nossa Newsletter semanal 😎👊🙂👌👍 Sugira conteúdo para a Weekly usando o nosso canal de issues no Github. Um agradecimento especial aos 15 colaboradores da edição […]

  • HyperTerm agora é Hyper.app

    O time da Zeit anunciou na última semana uma mudança no terminal JS/HTML/CSS desenvolvido pela empresa. O HyperTerm agora é Hyper.app. Guillermo Rauch, um dos fundadores da empresa, comentou que o projeto iniciou apenas como um experimento e se tornou um dos projetos mais populares no GitHub neste ano, com mais de 9.000 estrelas. O […]

  • Weekly #179 – Novo logo da Mozilla, JavaScript rising stars e React 15.5 e 16

    A BrazilJS Weekly é a seleção semanal que reúne as novidades sobre o desenvolvimento Web no Brasil e no mundo. Ainda não é inscrito? Faça o seu cadastro e receba nossa Newsletter semanal 😎👊🙂👌👍 Sugira conteúdo para a Weekly usando o nosso canal de issues no Github. Um agradecimento especial aos 9 colaboradores da edição […]

Patrocinadores BrazilJS

Gold

Silver

Bronze

Apoio

BrazilJS® é uma iniciativa NASC.     Hosted by Getup