Não há bala de prata
Na prática, depende ...
tl; dr - solução fácil, use nginx ...
Bloqueio:
Por exemplo, o Apache, por padrão, usa um esquema de bloqueio no qual o processo é bifurcado para todas as conexões. Isso significa que toda conexão precisa de seu próprio espaço de memória e a enorme quantidade de sobrecarga de alternância de contexto aumenta mais à medida que o número de conexões aumenta. Mas o benefício é que, quando uma conexão é fechada, o contexto pode ser descartado e toda e qualquer memória pode ser facilmente recuperada.
Uma abordagem multithread seria semelhante, pois a sobrecarga da alternância de contexto aumenta com o número de conexões, mas pode ser mais eficiente em termos de memória em um contexto compartilhado. O problema dessa abordagem é que é difícil gerenciar a memória compartilhada de maneira segura. As abordagens para superar os problemas de sincronização de memória geralmente incluem sua própria sobrecarga; por exemplo, o bloqueio pode congelar o encadeamento principal em cargas intensivas da CPU, e o uso de tipos imutáveis adiciona muitas cópias desnecessárias de dados.
AFAIK, geralmente é preferível o uso de uma abordagem de vários processos em um servidor HTTP de bloqueio, porque é mais seguro / mais simples gerenciar / recuperar a memória de uma maneira segura. A coleta de lixo se torna um problema quando a recuperação de memória é tão simples quanto interromper um processo. Para processos de longa execução (por exemplo, um daemon), essa característica é especialmente importante.
Embora a sobrecarga de alternância de contexto possa parecer insignificante para um pequeno número de trabalhadores, as desvantagens se tornam mais relevantes à medida que a carga aumenta para centenas de milhares de conexões simultâneas. Na melhor das hipóteses, a alternância de contexto escala O (n) para o número de trabalhadores presentes, mas na prática é provavelmente pior.
Onde os servidores que usam bloqueio podem não ser a escolha ideal para cargas pesadas de E / S, eles são ideais para trabalhos intensivos em CPU e a passagem de mensagens é reduzida ao mínimo.
Sem bloqueio:
Não bloquear seria algo como Node.js ou nginx. Eles são especialmente conhecidos por dimensionar para um número muito maior de conexões por nó, sob carga intensiva de IO. Basicamente, uma vez que as pessoas atingem o limite superior do que os servidores baseados em processos / encadeamentos podem lidar, eles começam a explorar opções alternativas. Isso também é conhecido como o problema C10K (ou seja, a capacidade de lidar com 10.000 conexões simultâneas).
Os servidores assíncronos sem bloqueio geralmente compartilham muitas características com uma abordagem de multiencadeamento com bloqueio, pois você deve ter cuidado para evitar cargas intensivas da CPU, porque não deseja sobrecarregar o encadeamento principal. A vantagem é que a sobrecarga incorrida pela alternância de contexto é essencialmente eliminada e com apenas uma passagem de mensagem de contexto se torna um problema.
Embora possa não funcionar para muitos protocolos de rede, a natureza sem estado de HTTPs funciona especialmente bem para arquiteturas sem bloqueio. Ao usar a combinação de um proxy reverso e vários servidores HTTP sem bloqueio, é possível identificar e rotear os nós com carga pesada.
Mesmo em um servidor que possui apenas um nó, é muito comum a instalação incluir um servidor por núcleo de processador para maximizar a taxa de transferência.
Ambos:
O caso de uso 'ideal' seria uma combinação de ambos. Um proxy reverso na frente dedicado a rotear solicitações na parte superior, depois uma mistura de servidores de bloqueio e sem bloqueio. Sem bloqueio para tarefas de E / S, como veiculação de conteúdo estático, conteúdo de cache e conteúdo html. Bloqueio para tarefas pesadas da CPU, como codificação de imagens / vídeo, conteúdo de streaming, processamento de números, gravação de banco de dados, etc.
No seu caso:
Se você está apenas verificando os cabeçalhos, mas não processando as solicitações, o que está descrevendo é essencialmente um proxy reverso. Nesse caso, eu definitivamente adotaria uma abordagem assíncrona.
Eu sugiro verificar a documentação do proxy reverso interno do nginx .
A parte, de lado:
Li o artigo a partir do link que você forneceu e faz sentido que o assíncrono tenha sido uma má escolha para sua implementação específica. O problema pode ser resumido em uma declaração.
Verificou-se que, ao alternar entre clientes, o código para salvar e restaurar valores / estado era difícil
Eles estavam construindo uma plataforma estatal. Nesse caso, uma abordagem assíncrona significaria que você precisaria salvar / carregar constantemente o estado toda vez que o contexto alternar (ou seja, quando um evento for disparado). Além disso, no lado SMTP, eles estão fazendo muito trabalho intensivo da CPU.
Parece que eles tinham uma compreensão muito pobre de assíncrono e, como resultado, fizeram muitas suposições ruins.