Quantos processos devo especificar em um WSGIDaemonProcess enquanto estiver executando o Django através do mod_wsgi?

23

Digamos que eu tenha 2 sites (Superusuário e Serverfault) sendo executados em seu próprio host virtual Apache em uma caixa. Os 2 sites são alimentados pelo Django e estão rodando no Apache com mod-wsgi. Um arquivo de configuração típico para um dos sites terá a seguinte aparência:

WSGIDaemonProcess serverfault.com user=www-data group=www-data processes=5

O host é uma máquina Linux com 4 GB de RAM executando o Ubuntu. Alguém pode sugerir o número de processos que devo especificar acima para meus 2 sites? Vamos supor que eles tenham o mesmo tráfego que os sites reais de Superusuário e Serverfault.

Thierry Lam
fonte

Respostas:

22

Bem, a quantidade de tráfego que os atuais sites de superusuário e Serverfault tem? As hipotéticas não são muito úteis se não tiverem informações suficientes para facilitar a resposta ...

Sua contagem de processos na pior das hipóteses deve ser o número máximo de solicitações por segundo que você deseja que o site possa manipular, dividido pelo número de solicitações por segundo que um processo pode manipular se todas essas solicitações forem feitas com a ação mais lenta (portanto, recíproco do tempo de processamento dessa ação). Adicione o fator de falsificação que achar adequado, com base no intervalo de confiança de suas medidas de req / s e tempo.

A contagem média de casos é a mesma, mas você divide o req / s pela média ponderada de suas solicitações por segundo para cada ação (o peso é a porcentagem de solicitações que você espera que atinjam essa ação específica). Novamente, os fatores de correção são úteis.

O limite superior real de quantos processos você pode executar na máquina é determinado pela quantidade superior de memória que cada processo leva; coloque um processo em spool e execute uma variedade de ações que exigem muita memória (aquelas que recuperam e processam muitos dados, normalmente) com um conjunto de dados realista (se você usar apenas um conjunto de dados de brinquedo para teste, digamos 50 ou 100 linhas, se uma de suas ações recuperar e manipular todas as linhas da tabela, não será uma boa medida para quando essa tabela aumentar para 10.000 linhas) para ver para que serve o uso da memória. Você pode restringir artificialmente o uso de memória por processo com um script que colha trabalhadores que atingem um determinado limite de uso de memória, correndo o risco de causar problemas desagradáveis ​​se você definir esse limite muito baixo.

Depois de obter o número de uso de memória, você deduz uma certa quantidade de memória para sobrecarga do sistema (eu gosto de 512 MB), deduz um monte mais se tiver outros processos em execução na mesma máquina (como um banco de dados) e, em seguida, um pouco mais para garantir que você não fique sem espaço em cache do disco (depende do tamanho do conjunto de trabalho do disco, mas novamente eu usaria nada menos que 512 MB). Essa é a quantidade de memória que você divide pelo uso da memória por processo para obter o limite máximo.

Se o número de processos necessários para atender ao seu pico de carga for maior que o número de processos que você pode ajustar na caixa, precisará de mais máquinas (ou para mover o banco de dados para outra máquina, no caso mais simples).

Lá está você, vários anos de experiência escalando sites destilados em um pequeno e simples post de SF.

mulher
fonte
Outro fator importante para o número de processos / encadeamentos é o tempo que as solicitações individuais podem levar para serem tratadas e a disseminação geral por todos os períodos de tempo possíveis. Em outras palavras, quantas solicitações ao mesmo tempo precisam ser tratadas, o que leva mais que o tempo médio de resposta. Portanto, não é tão simples quanto as solicitações teóricas / s, já que o impacto dessas solicitações em execução mais longa pode ser significativo e exigir indevidamente os parâmetros gerais de configuração. O FWIW mod_wsgi 3.0 incluirá algumas coleções internas de estatísticas para tentar capturar dados sobre isso para ajudar na configuração.
Graham Dumpleton 03/11/2009
@ Graham: Releia minha resposta, cobri isso em detalhes. Pedidos / s é apenas o inverso do tempo de resposta e é mais fácil dividir por um número inteiro req / s do que multiplicar por um decimal.
Womble
Você não pode se concentrar apenas na resposta do pior caso, nem apenas na média dessa questão. Ele precisa ser ponderado de maneiras com base na porcentagem de solicitações que se enquadram em períodos de tempo, ou seja, a distribuição entre todos os tempos possíveis. Se você realmente tivesse o pior tempo possível de resposta, apresentaria requisitos irreais. O problema é realmente difícil saber qual fórmula usar. É por isso que, no mod_wsgi 3.0, haverá coleta de estatísticas embutidas que analisa a utilização do encadeamento e para qual porcentagem, por contagem e tempo, que qualquer número de encadeamentos está sendo usado a qualquer momento.
Graham Dumpleton 4/11/2009
3
O problema talvez seja que você esteja analisando os processos apenas onde eu estou preocupado com a forma como os segmentos em que cada processo usa o fator, e isso não é tão simples. Em outras palavras, essa diretiva WSGIDaemonProcess indica 5 processos em que cada processo é por padrão usando 15 threads. Por mais que eu li na sua descrição, ele está assumindo processos de thread único. Caso contrário, aponte para mim como o seu modelo atende a threads, além de problemas de contenção / dimensionamento no GIL. Portanto, qualifique-se de que sua descrição seja válida apenas para processos de encadeamento único e não discutirei.
Graham Dumpleton 4/11/2009
2
O "multithread-Apache + multiprocess-wsgi" não é a melhor opção até que você tenha 99% de certeza de que seu código Python e todas as dependências são seguras para threads?
Tomasz Zieliński
9

A resposta de womble é incrível, embora um pouco difícil de entender e solicitar os inexperientes. Gostaria de fornecer alguns números empíricos e comparação de aplicativos "conteúdo simples" versus "comércio eletrônico".

Não há muito material para definir casos de uso diferentes em relação à configuração apropriada de mod_wsgi, portanto, espero que esteja tudo bem em usar uma pequena prosa aqui.

A) Sites e Microsites CMS

Executamos vários sites de clientes, a maioria deles sites de conteúdo ou micro sites que hospedam o django CMS, alguns formulários personalizados e, às vezes, o Aipo para tarefas em segundo plano agendadas. Esses sites não têm fome de recursos, vários deles rodam alegremente em paralelo em um único Intel Xeon de 4 núcleos com 32 GB de RAM. Aqui está a configuração que usamos para cada um desses tipos de sites:

WSGIDaemonProcess example.com user=www-data processes=2 maximum-requests=100

Estou falando de aproximadamente 40 sites em um único servidor, a maioria deles com o site de teste em execução no modo de espera. Com 2 processos (com 15 threads cada, por padrão), os sites estão bem, embora limitados em sua capacidade de alocar recursos do servidor. O motivo pelo qual essa configuração é suficiente pode ser justificado com a natureza simples do aplicativo (CMS): Não se espera que nenhuma solicitação demore mais do que alguns milissegundos para concluir. O Apache sempre permanecerá relaxado, assim como a carga da CPU.

B) Sites de comércio eletrônico

Os sites mais complexos que fazemos são caracterizados por operações locais ainda computacionalmente baratas, mas dependências externas (por exemplo, serviços web que fornecem dados de reserva) que são caros em termos de tempo de transação. As operações com solicitações externas ocupam threads por muito mais tempo, portanto, você precisa de mais threads para atender o mesmo número de usuários (em comparação com um site simples do CMS acima). Pior ainda, os encadeamentos são ocasionalmente bloqueados quando um serviço externo não pode responder a uma solicitação imediatamente, às vezes por alguns segundos. Isso pode levar ao efeito colateral desagradável de que os threads que colocam solicitações na mesma fila de serviço subam até que todos os threads mod_wsgi disponíveis sejam usados ​​e bloqueados a espera.

Para esses cenários, tentamos usar 6processos sem ver muita diferença e acabamos 12vendo um aumento incomparável no desempenho e na estabilidade operacional:

WSGIDaemonProcess example.com user=www-data processes=12 maximum-requests=100

Alguns testes simples de carga com 150 e 250 usuários paralelos são facilmente manipulados pelo site, mantendo uma boa resposta (enquanto nos 2processos, o site é inutilizável, atendendo 50 usuários em paralelo). O Intel Xeon de 2 CPUs e 6 núcleos com 32 GB de RAM funciona bem abaixo de 25% do uso da CPU sob essa carga, o uso da RAM também permanece constante em menos de 25%. Observe que usamos aqui uma máquina dedicada apenas para um único site, para não roubar recursos que outros sites possam precisar.

Conclusão

Usar um número maior de processos é uma troca entre permitir que o Apache faça uso dos recursos disponíveis do sistema ou não. Se você deseja manter um sistema de servidor estável (não o site!) Em condições de "ataque", mantenha o número baixo. Se você deseja que o Apache o ajude a usar os recursos do sistema (CPU, RAM), quando necessário, escolha um número maior. O quão alto você pode ir calcula um pouco como descrito na resposta aceita acima e, em última análise, é limitado pela energia da CPU e RAM disponíveis.

(PS: Eu mantenho a seção ConfigurationDirectives do wiki do projeto modwsgi debaixo do meu travesseiro para leitura em segundo plano semelhante ao Apache. Também não deixe de entender e monitorar as conexões abertas do servidor Apache .)

Peterino
fonte
Ótimo post, mas por que você não define a contagem de threads? Como o GIL do Python nega muitas vantagens dos threads, eu presumo que você desejaria ter mais processos do que threads, mas há alguma vantagem em especificar a contagem de threads?
Cerin
O número padrão threadsé 15, de acordo com a documentação . Não acho que exista uma vantagem em especificar isso explicitamente. Na verdade, lembro-me de ter deixado de fora por um motivo: houve alguma postagem no SO ou parte de alguma documentação que recomendava omitir o valor para evitar efeitos colaterais (eu sei, isso soa estranho). Infelizmente, não encontro essa fonte agora. Pelo resto da sua pergunta (GIL), você provavelmente é mais especialista do que eu, desculpe.
Peterino 3/11
Obrigado por esta configuração empírica. No entanto, lembre-se de que, de acordo com este post You should never use maximum-requests in a production system unless you understand the implications and have a specific temporary need.
raratiru 17/0318