Migrando do mod_python para o mod_wsgi
Já faz alguns meses que eu queria fazer alguns testes com o mod_wsgi, a alternativa ao mod_python que vem sendo cada vez mais comentada e sugerida na comunidade Django.
Ontem eu aproveitei o dia tranquilo pra unir o útil ao agradável e colocar isso em prática.
O que é WSGI?
Vamos "começar do começo": WSGI é mais simples do que parece, trata-se de uma interface definida pela PEP 333 [1] para intermediar a comunicação entre servidores web e frameworks Python. Ela surgiu pela necessidade qualquer um de nós nota com um pouco tempo: Python tem quilos de frameworksmuitas delas excelentes, e às vezes o mod_python parece ser um ornitorrinco em um ninho de coelhos quando implantamos alguns sites. É esquisito.
Mudando para o mod_wsgi
Para usar o WSGI puramente, é bastante simples, vamos fazer um pequeno script para ilustrar
def application(environ, start_response):
status_code = '200 OK'
headers = [('Content-Type', 'text/html')]
start_response(status_code, headers)
return ['So testando!']
from paste import httpserver
httpserver.serve(application, port='8000')Ao executar este script minúsculo e carregar em seu navegador a URL "http://localhost:8000", será exibido "So testando". Simples não? Veja
$ python my_app.py
serving on http://127.0.0.1:8000No Django, a coisa exige só um pouco mais de detalhes, mas nada complexo. Como já explanado há poucos dias pelo Eric, da Metaphormedia, em [2], é recomendável que se crie dentro de seu projeto uma pasta "apache" com um script dentro chamado "django.wsgi" - estes nomes são escolha sua, mas eles têm sido usados por mais de uma referência. Com o conteúdo abaixo (modificado segundo as suas necessidades)
#!/usr/bin/env python
import os, sys
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)+'/../'))
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()E configure seu apache, removendo o código que implementa o mod_python e adicionando o seguinte
WSGIScriptAlias / /caminho/do/seu/projeto/apache/django.wsgiAgora, para funcionar, é preciso que seu sistema operacional tenha o mod_wsgi instalado. No Ubuntu/Debian você instala com o seguinte comando
$ sudo apt-get install libapache2-mod-wsgiPronto, ao reiniciar o Apache, seu projeto estará lá, bonitão, rodando através do WSGI :)
Porque mod_wsgi?
Bom, essa deve ser a pergunta que você deve estar se fazendo. Se o mod_python sempre foi a alternativa recomendada e funciona bem, porque mudar para o mod_wsgi?
O mod_wsgi tem se comportado mais escalável que o mod_python. Por escalabilidade, entende-se a capacidade de um site de suportar o crescimento de uso sem perder a performance ou travar.
Ao ajustar um servidor para usar o mod_wsgi, pude notar essas diferenças. Elas não são tão grandes que se possa perceber com um simples teste com Apache Bench. É necessário forçar para notar a diferença, que tem sido até 10% superior.
Esse servidor que usei para fazer esses testes é uma VM (em Xen) com 512MB de RAM, rodando em um amd64, numa rede bastante estável, em Londres, enquanto que o Apache Bench foi executado em minha máquina.
Veja abaixo como os dois modos se comportaram:
Para compreender a legenda, o número após o "n" trata-se da quantidade de requisições enviadas e o número após o "c" trata-se da quantidade de requisições concorrentes, ou seja, "n1000c5" equivale a "1000 requisições enviadas de 5 em 5).
Tempo de resposta por requisição
Requisições por segundo
Load de 1 minuto
Load de 5 minutos
RSS / Memória real ocupada
Percentual da CPU
Conclusões
Todos os números apresentados acima não podem ser tomados como base exata para comparação, por alguns motivos, como a influência que o teste anterior efetua no subsequente, a oscilação da internet e a influência de outros processos.
Eu fiz questão de usar um servidor em produção onde está sendo servido um outro sistema da empresa, que mesmo que não estivesse em seu horário de pico, era usado normalmente por alguns usuários.
Há ainda toda a questão de controvérsias em torno do uso real da CPU e da memória.
Mas dá pra notar uma realidade clara: o mod_swgi se mostra mais vantajoso em memória e tempo de resposta. Não esqueçamos que 200 requisições concorrentes para um VPS com 512MB de RAM é uma senhora carga, equivalente a alguns milhões de pageviews por mês.
No teste de 2000 requisições a 200 concorrentes, ficou visível que a configuração de MaxRequestsPerChild (de 1000) entrou em cena e fez diferença no desempenho, tanto para segurar a carga quando para mudar um pouco a evolução do desempenho.
Por fim, devo avisar que no teste seguinte, de 5000 requisições a 200 concorrentes, o Apache caiu antes de completar 3000, em 3 tentativas.
Mais detalhes sobre o WSGI podem ser encontrados em [4], [5] e [6]
Links relacionados
| [1] | http://www.python.org/dev/peps/pep-0333/ |
| [2] | http://www.ericholscher.com/blog/2008/jul/8/setting-django-and-mod_wsgi/ |
| [3] | http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango |
| [4] | http://www.slideshare.net/hdiogenes/wsgi-a-resposta-para-a-questo-definitiva-sobre-python-a-web-e-tudo-mais-368429?src=embed |
| [5] | http://en.wikipedia.org/wiki/Wsgi |
| [6] | http://www.wsgi.org/wsgi/ |
| [7] | http://del.icio.us/marinho/wsgi |
Marinho Brandão
comentou há 1 mês, 2 semanas:
Marinho,
ótimo post, muito bom!