Devs, hoje quero compartilhar um pouco sobre um approach que escolhemos pra ter nosso server disponível para alguns milhares de usuários numa boa.
De acordo com nosso analytics, tivemos em torno de 10k de acesso no dia em que precisávamos em uma t2.large e a CPU ficou em 6% … não fez muito estrago

A maioria de vocês já deve conhecer o Nginx, que nos ajuda bastante como http proxy server, mas hoje vou falar mais sobre o Varnish, que é um acelerador de aplicações web, segundo o próprio descritivo deles, que eu diria ser um cache pro http server.

Oi?
Oi, tudo bem? Então. Brevemente explicando, o Varnish vai armazenar o conteúdo das requisições HTTP em memória, e de acordo com a configuração que você fizer, quem acessar a mesma url durante um período de tempo vai receber a resposta que está em cache na memória, ou seja, sua aplicação (nodejs) não vai ser requisitada por algum tempo.

Importante: A equipe tem que chegar a uma definição pra ver se esta abordagem é válida. No nosso contexto, a maioria do conteúdo entregue pelo nosso server era sempre o mesmo, listagem de produtos, infos detalhes etc.

A nossa ideia inicial era deixar a arquitetura desta maneira:

Aws Load Balancer -> (Scaling Horizontal) EC2 t2.large -> nginx -> varnish -> (4 processos) nodejs

Mas quando nos falaram que não era algo tão brutal de users, e após realizarmos alguns testes de conexões (com node package loadtest) , acabamos ficando com a seguinte arquitetura:

EC2 t2.large -> nginx -> varnish -> (1 processo) nodejs

E não tivemos problemas :)

Configurando Varnish e Nginx no Ubuntu

Detalhe: estou levando em conta que você já tem o ambiente com nginx rodando e servindo a aplicação em Node, ok?

Instalando Varnish

apt-get install apt-transport-https
curl https://repo.varnish-cache.org/GPG-key.txt | apt-key add -
echo "deb https://repo.varnish-cache.org/ubuntu/ trusty varnish-4.1" \
>> /etc/apt/sources.list.d/varnish-cache.list
apt-get update
apt-get install varnish

Deixando o Varnish na porta 80

No seu editor de preferência, abra o arquivo /etc/default/varnish, ele terá um bloco com a porta para testes:

DAEMON_OPTS="-a :6081 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"

Vamos mudar para:

DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"

Ok, agora precisamos direcionar o request pro nosso Nginx que está a aplicação em node na porta:3000
Vamos abrir o arquivo /etc/varnish/default.vcl, e vou colocar aqui apenas os blocos que precisei alterar, comentando o porque.

.host e .port foram alterados para direcionar pro nginx

/etc/varnish/default.vcl
  • vim
1
2
3
4
5
6
7
8
backend default {
.host = "127.0.0.1";
.port = "3000";
.connect_timeout = 10s;
.first_byte_timeout = 15s;
.between_bytes_timeout = 60s;
.max_connections = 800;
}

Dependendo do seu contexto, voce precisara manualmente informar os arquivos/rotas que não quer que fiquem em cache. No nosso caso, /cms que é nosso gerenciador de conteúdo e /api/v1

/etc/varnish/default.vcl
  • vim
1
2
3
4
5
6
7
8
9
10
11
12
13
sub vcl_recv {
if (req.url ~ "^/cms/") {
return (pass);
}
if(req.url ~ "^/api/v1/") {
return (pass);
}
unset req.http.cookie;
# Happens before we check if we have this in cache already.
#
# Typically you clean up the request here, removing cookies you don't need,
# rewriting the request, etc.
}

E precisamos ajustar /etc/nginx/sites-enabled/default

/etc/nginx/sites-enabled/default
  • vim
1
2
3
4
5
6
7
8
9
10
11
12
upstream node_server {
server 127.0.0.1:80;
}
server {
# commented line below because we are using varnish as main cache,
# so port 80 is being used by varnish.
# listen 80;

location / {
proxy_pass http://node_server;
}
}

Por fim, falta ajustar os headers da sua aplicação node com max-age. No nosso caso, como utilizamos o express, vamos ao arquivo em que registramos as rotas:

/app/routes/index.js
  • js
1
2
3
4
app.all('/*', function(req, res, next) {
res.header('Cache-Control', 'public, max-age=120');
next();
});

Bom, agora você pode testar da seguinte maneira:

sudo service varnish restart
sudo service nginx restart

Confira se subiu tudo ok, e então você pode fazer uma request para o seu site e acompanhar os logs de requisição, utilizando
tail -f /path/to/logfile

A primeira vez que você fizer o acesso, verá os registros de log. Nas próximas requisições iguais, você não verá mais pois a request bateu primeiro no Varnish e foi entregue para o user o que estava em Cache.

Tem bastante coisa pra configurar com o Varnish, questão de tempo em que ele mantém cache e tudo mais. Eu abordei aqui o mais básico dele e acredito que já pode ser bem útil. Mas por favor, vá adiante e leia mais sobre o que pode ser feito.

See ya.