terça-feira, 12 de fevereiro de 2013

Unicorn e Thin no Heroku

Depois de ver este post http://michaelvanrooijen.com/articles/2011/06/01-more-concurrency-on-a-single-heroku-dyno-with-the-new-celadon-cedar-stack/ decidi configurar uma aplicação no Heroku para utilizar o Unicorn ao invés do Thin.

Se você observar no post acima, existe um benchmark em relação ao tempo que levou os testes e a quantidade de requisições por segundo. Fiquei realmente animado com esta possibilidade para escalar aplicações, visto que cada dyno do heroku atende a uma requisição e a única possibilidade de antender mais requisições com o servidor Thin é aumentar o número de dynos.

O Unicorn foi desenvolvido para trabalhar com vários processos, fazendo fork de instâncias, deste modo em um único dyno é possível ter aproximadamente 3 processos, isso devido a limitação de memória oferecida por cada dyno que é de 512mb, porém se você adicionar mais um dyno você tem 6 processos rodando. Legal, não acha?

Com estas possibilidades animadoras resolvi fazer alguns testes para ver se utilizá-lo é realmente uma vantagem para deixar a resposta da aplicação mais rápida. Meu arquivo de configuração do Unicorn ficou exatamente como o deste post: http://stackoverflow.com/questions/9344788/am-i-preloading-the-app-in-heroku-unicorn-correctly

Para coletar os dados utilizei o comando httperf da seguinte maneira: httperf --hog --server meuservidor.com.br --ssl --ssl-no-reuse --num-conn=500 --ra=10 --timeout 30

Este comando irá fazer 500 conexões SSL com a página raiz do meu site (que não faz acesso a banco de dados), forçando handshake através da opção --ssl-no-reuse a uma taxa (--ra=10) de 10 conexões por segundo. Rodei o comando 3 vezes e fiz a média dos resultados obtidos para os seguintes valores de --ra: 10, 40, 80, 160, 320 e 500.

Então vamos aos dados obtidos:

Confesso que esperava mais do Unicorn, já que temos 3 processos atendendo requisições. A partir de 80 conexões ele estabeleceu em média 5 conexões a mais por segundo, sendo que em um dos testes o Thin conseguiu um desempenho um pouco melhor.
O tempo de resposta foi outra surpresa para mim, sendo que o Thin conseguiu ser mais rápido quando muitas conexões estão sendo estabelecidas por segundo.

Não vejo nenhuma vantagem clara de usar o Unicorn por enquanto, além de algumas vezes (raras) ter me deparado com o erro: httperf: failed to connect to SSL server (err=-1, reason=5).

Depois destes dados compilados, achei que fui muito suave e decidi ser mais agressivo em relação ao número de requisições. Requisitei 1500 conexões a uma taxa de 100 conexões por segundo (um site bem movimentado, não acha?). Nesta configuração ambos os servidores não conseguiram antender a todas as requisições (timeout), porém a performance de ambos os servidor foi semelhante, com o Unicorn atendendo um pouco mais de requisições (1233 x 1249), a taxa de conexão praticamente igual (20,8 x 21,6) assim como o tempo de resposta (3371ms x 3025ms).

Estes últimos testes atenderam mais de 1000 conexões concorrentes. Isso na versão para desenvolvedor do Heroku. Muito bom!

Ainda pretendo fazer testes em páginas que realizem consultas não triviais ao banco de dados para ver se os servidor apresentam tempos diferentes, mas isso fica para um próximo post...