Portabilidade - MPMs (multi-processing
modules)
Essa talvez tenha sido uma das grandes mudanças nessa
versão, não desconsiderando as outras nem querendo
ser simplista. Basicamente, o servidor 1.3 trabalhava com o
modelo de pré-fork, o que seria isso? É
inicializado um processo pai que da fork criando n processos
filhos. Esses processos filhos são os responsáveis
por cuidar e responder as requisições vinda dos
clientes. Dependendo do número de requisições,
mais cópias de filhos são criadas. O processo pai
fica supervisionando o funcionamento dos seus filhos e vendo
se tudo corre bem. Ele controla a quantidade de filhos que
estão a disposição de forma a regular o
número de filhos / requisições, para que na
maior quantidade de tempo possível, se tenha filhos
disponíveis para atender as requisições.
Através de diretivas o administrador configura tais
parâmetros, que é proporcional com a quantidade de
memória disponível na máquina. Atividades de
servir Web é gastadora intensiva de memória, e
atividades de swap são onerosas demais e praticamente
inviabilizam o funcionamento do servidor de forma
desejável. O Apache sempre tenta deixar alguns processos
ociosos, esperando por conexões, além dos que
estão servindo as requisições atuais. Isso
garante que ele tenha sempre uma sobra de processos caso
aumente o número de requisições por intervalo
de tempo, e não faz com que ele tenha que criar (fork)
de outro processo naquele instante, fazendo com que o
usuário espere a criação do processo.
Esse modelo trabalho bem na maioria dos Unix,
principalmente no Linux. O Linux é o sistema conhecido
como o sistema com mais rápidas chamadas de sistemas
existentes, criar processos para ele é bastante natural
e quase instantâneo. Ele foi desenhado para isso.
Já no Windows não, e para sua versão foi
utilizado da idéia de através do primeiro processo
criado, criar vários threads. O Windows é baseado
em threads, que tem compartilhamento de memória, entre
outras características.
Junta-se a essa variação, múltiplas
plataformas com diferenciações de código
até para otimização (o Apache é conhecido
como sendo o mais otimizado dos servidores, seus
desenvolvedores tiram da última gota de suor, lugar para
melhorar e aumentar sua velocidade), obtêm-se um
código bastante alargado e poluído, com milhares de
#ifdefs espalhados (diretivas de compilação para
variação de código na hora da
compilação, para o não-programador). Com essas
tantas condicionais de compilação, fazer a
manutenção no código ficou bastante
difícil e mesmo adicionar novas plataformas ou mesmo
diferenciação entre versões da mesma
plataforma, fica lento e a longo prazo inviável (mais
embaixo apr).
Com a evolução das discussões sobre a
versão 2.0, um ponto ficou bastante claro: a
decisão de rodar o Apache em todas as plataformas com
igualdade de preferência e possibilidades. No Windows
ele teria que funcionar bem, tão bem quanto nos Unix e
adicionar uma nova plataforma teria que ser mais simples,
principalmente para o desenvolvedor da plataforma. Como se
pode notar pelo relato, o código no mesmo lugar seria
inviável e difícil de manter, decidiu-se criar uma
nova camada de abstração. O MPM (Multi-Processing
Modules). O MPM teria que mapear requisições dentro
de primitivas básicas. Atrás destas teria-se o modo
como ela seria tratada, se com processo, thread, ou seja
lá o que queiram inventar. Ficaria a cargo de cada
desenvolvedor decidir como fazer isso na sua plataforma.
Essa abstração dos MPMs criou uma nova
possibilidade: a adaptação do servidor a
necessidade do Administrador. Temos MPMs conhecidos nos Unix:
pré-fork, pthread e dexter. O prefork é exatamente
o que acontece com a versão 1.3 e é bastante
adequado para sistemas como Linux, como já disse
(rápidos com processos). O Pthread é um
híbrido entre threads e processos. Ele primeiro cria
(fork) vários processos filhos e depois para cada filho
cria um certo número de threads por filhos. O
número de threads por processos é fixo, ou seja, o
número de requisições também é fixo.
É ajustável pelo número de filhos. Tal
módulo é indicado para plataformas que tem suporte
a threads e tem problemas de memória em sua
implementação. Já o Dexter cria vários
processos (fixos) e um conjunto de threads por processo, mas
dependendo da quantidade de requisições que vem por
servidor, ele acomoda os números e cria ou destrói
threads. É indicado para plataformas mais modernas com
bom suporte a threads. Temos também para o Windows NT da
Microsoft o WINNT_MPM. Ele é a padrão para o NT e
trabalha com um processo pai e vários threads. É
muitíssimo melhor que o suporte atual (1.3) para tal
plataforma.