O módulo prefork implementa um servidor HTTPD não-thread. Cada requisição HTTP é atendida por um processo individual criado a partir de um fork. Isso pode ser útil para aplicações WEB que não aceitam ou não sabem trabalhar com threads de modo seguro.
Outra razão é o melhor isolamento evitando que um processo errante contamine e derrube o servidor. Isso pode ser útil até que sua aplicação esteja em um estado maduro para trabalhar com threads.
Esse módulo se auto regula, dessa maneira, raramente, é preciso fazer ajustes no valor padrão de seus parâmetros. O principal parâmetro é MaxRequestWorks, que deve ser grande o suficiente para manipular o número de requisições que o servidor irá receber, mas pequeno o suficiente para não exaurir seus recursos de hardware. Vejamos como esse módulo funciona na prática.
Um processo pai (httpd ou apache2) mantém sempre um certo número de processos filhos ouvindo por requisições HTTP na porta TCP/80. Esses processos são chamados de spare (reserva) ou de processos idle (desocupados). Quando uma requisição HTTP chega pela rede, eles devem estar prontos para atender. Isso evita que as requisições precisem esperar que o servidor realize o fork para criar novos processos filhos, pois em termos de computação, esse é um tempo grande.
Um conjunto de diretivas configura como o processo pai cria seus processos filhos. Na maioria dos sites o valor padrão é suficiente para obter o equilíbrio entre demanda e disponibilidade de recursos de hardware. De acordo com o manual do Apache 2.4, se um site precisa atender mais de 256 requisições simultâneas é preciso fazer ajustes manuais nesses parâmetros até encontrar o equilíbrio desejado.
Enquanto o processo pai (daemon) necessita de privilégios de administrador (root), os processos filhos são lançados com os privilégios de um usuário comum (no Debian, esse usuário se chama www-data). As diretivas User e Group definem esse usuário comum. Isso é válido para
prefork,
worker e
event.
O privilégio de leitura (read) no sistema de arquivos, deve ser garantido ao conteúdo que esse usuário comum irá fornecer; os demais privilégios devem ser mantidos ao mínimo necessário. Vejamos como as principais diretivas de prefork devem ser configuradas.
MaxSpareServers - define o número máximo de processos spare. O valor padrão é 10. Se o número de processos spare exceder o valor definido para essa diretiva (após a liberação de um processo que estava ocupado) o servidor irá matar esses processos excedentes (isso tem um alto custo computacional, tenha cuidado!). O menor valor aceito para esse argumento é SEMPRE gerado por MinSpareServers + 1.
MinSpareServers - número mínimo de processos spare mantidos pelo servidor. O valor padrão é 5. Se o número de processos spare ficar abaixo do valor definido nesse parâmetro, o servidor lançará novos processos-filhos até atingir o valor informado nessa diretiva. Esse processo de lançar forks, ocorrerá de forma exponencial e com intervalos de um segundo, até atingir o valor de 32 processos lançados simultaneamente ou até atingir o valor mínimo definido na diretiva.
Assim, o servidor lança um processo, aguarda um segundo e lança dois processos. Aguarda outro segundo e lança quatro processos, sucessivamente até lançar 32 processos simultaneamente ou atingir o valor mínimo de spares definido na diretiva, o que acontecer primeiro.
StartServers - define o número de processos filhos lançados no momento da inicialização do servidor HTTPD. Essa diretiva é comum para os módulos
prefork,
worker ou
event. Esse parâmetro permite um balanceamento entre os valores mínimos e máximos.
O valor padrão irá variar entre os diferentes MPMs devido as diferenças de funcionamento entre eles. Para o método
prefork, esse valor é 5. Observe que esse valor deve estar entre os valores mínimo e máximo.
A inclusão dessas diretivas em um arquivo de configuração, ficaria do seguinte modo:
- StartServers 10
- MaxSpareServers 20
- MinSpareServers 5
Isso gera um conjunto de processos do seguinte modo:
Observe que o primeiro processo (PID 1796 em vermelho) tem privilégios de usuário administrativo (root), enquanto os demais (destacados em verde) são inicializados pelo usuário comum (www-data).