Eu tenho uma caixa Ubuntu 10.04 executando várias dezenas de sites Python Django usando mod_wsgi (modo incorporado; omodo mais rápido, se configurado corretamente). O desempenho varia muito. Às vezes rápido, às vezes com atraso de vários segundos. Os gráficos sobre fumo estão por toda parte.
Recentemente, também adicionei um proxy nginx para o conteúdo estático, na esperança de que isso curasse o desempenho altamente flutuante. Mas, embora tenha reduzido significativamente o número de solicitações que o Apache precisa processar, não ajudou no problema principal.
Ao clicar em sites enquanto executa o htop, pode-se perceber que às vezes as solicitações são quase instantâneas, enquanto às vezes faz com que o Apache consuma 100% da CPU por alguns segundos. Eu realmente não entendo de onde vem essa flutuação.
Eu configurei o mpm_worker para Apache assim:
StartServers 1
MinSpareThreads 50
MaxSpareThreads 50
ThreadLimit 64
ThreadsPerChild 50
MaxClients 50
ServerLimit 1
MaxRequestsPerChild 0
MaxMemFree 2048
1 servidor com 50 threads, máximo de 50 clientes. Munin e apache2ctl -t
ambos mostram uma presença consistente de trabalhadores; eles não são destruídos e criados o tempo todo. No entanto, ele se comporta como tal.
Esseme diz que uma vez criado um subinterpretador, ele deve permanecer na memória, mas parece que os sites precisam ser recarregados o tempo todo.
Eu também tenho uma caixa nginx+gunicorn, que funciona muito bem. Eu realmente gostaria de saber por que o Apache é tão aleatório.
Esta é uma configuração de host virtual:
<VirtualHost *:81>
ServerAdmin [email protected]
ServerName example.com
DocumentRoot /srv/http/site/bla
Alias /static/ /srv/http/site/static
Alias /media/ /srv/http/site/media
WSGIScriptAlias / /srv/http/site/passenger_wsgi.py
<Directory />
AllowOverride None
</Directory>
<Directory /srv/http/site>
Options -Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
- Ubuntu 10.04
- Apache 2.2.14
- mod_wsgi 2.8
- nginx 0.7.65
Editar: coloquei um código no arquivo settings.py de um site que grava a data em um arquivo tmp sempre que ele é carregado. Agora posso ver que o site não é recarregado aleatoriamente o tempo todo, então o Apache deve mantê-lo na memória. Então, isso é bom, exceto que não me aproxima de uma resposta...
Editar: acabei de encontrar um erro que também pode estar relacionado a isso:
File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
errread, errwrite)
File "/usr/lib/python2.6/subprocess.py", line 1049, in _execute_child
self.pid = os.fork()
OSError: [Errno 12] Cannot allocate memory
O servidor tem 600 de 2.000 MB livres, o que deve ser suficiente. Existe um limite definido no Apache ou WSGI em algum lugar?
Responder1
Você já tentou usar o New Relic para tentar identificar se isso é um problema em seu aplicativo da web? Nível gratuito disponível e também uma avaliação inicial completa. Visão geral do que isso pode oferecer:
Se um problema específico com o aplicativo da web do serviço de back-end usado não se destacar como um problema, o relatório de análise de capacidade do servidor WSGI poderá mostrar algo, pois informará se você está esgotando a capacidade. Ele também pode dizer se você está superprovisionado e desperdiçando recursos, o que na verdade é o caso com bastante frequência.
Aliás, em geral eu não recomendaria o uso de 50 threads de solicitação em um único processo. É melhor usar cerca de 5 threads e vários processos. Exatamente o que é melhor realmente depende do aplicativo específico, se ele está executando muito trabalho vinculado à CPU e quanto tem para lidar com solicitações de longa execução. O fornecimento de muitos arquivos estáticos por meio do mesmo Apache também pode impactar isso, com o modo daemon do mod_wsgi possivelmente sendo uma solução geral melhor.
Você também está em uma versão mod_wsgi muito antiga, embora não acredite que isso possa causar problemas.
Finalmente, para evitar problemas com alguns módulos de extensão C de terceiros para Python, se este for o único aplicativo WSGI naquele servidor, defina:
WSGIApplicationGroup %{GLOBAL}
Responder2
Eu consertei isso. Converti todos os sites de produção para usarem seus próprios processos (e todos os sites de desenvolvimento juntos em um processo também), no modo daemon. Os gráficos do Smokeping estão muito melhores agora. O desempenho é estável.
Isso ainda me deixa sem saber por que o modo incorporado teve esses problemas, porque até onde sei, não tive criação/destruição de processos, mas pelo menos tenho um servidor em melhor execução.
Editar:
Como exemplo em uma configuração de site Apache:
WSGIDaemonProcess mysite12 processes=1 threads=10 display-name=%{GROUP}
WSGIProcessGroup mysite12
E então, para sites de baixa prioridade, coloquei isto wsgi.conf
:
WSGIDaemonProcess developmentsites processes=1 threads=15 display-name=%{GROUP}
E então em uma configuração do Apache:
WSGIProcessGroup developmentsites
Veja a diferença (também por causa do proxy nginx):