No hay bala de plata
En la práctica depende ...
tl; dr - solución fácil, usa nginx ...
Bloqueo
Por ejemplo, Apache por defecto usa un esquema de bloqueo donde el proceso se bifurca para cada conexión. Eso significa que cada conexión necesita su propio espacio de memoria y la gran cantidad de sobrecarga de cambio de contexto aumenta más a medida que aumenta el número de conexiones. Pero el beneficio es que, una vez que se cierra una conexión, el contexto se puede eliminar y cualquier / toda la memoria se puede recuperar fácilmente.
Un enfoque de subprocesos múltiples sería similar porque la sobrecarga de la conmutación de contexto aumenta con el número de conexiones, pero puede ser más eficiente en la memoria en un contexto compartido. El problema con este enfoque es que es difícil administrar la memoria compartida de manera segura. Los enfoques para superar los problemas de sincronización de memoria a menudo incluyen su propia sobrecarga, por ejemplo, el bloqueo puede congelar el hilo principal en cargas intensivas de CPU, y el uso de tipos inmutables agrega una gran cantidad de copias innecesarias de datos.
AFAIK, generalmente se prefiere usar un enfoque multiproceso en un servidor HTTP de bloqueo porque es más seguro / más simple administrar / recuperar la memoria de una manera segura. La recolección de basura se convierte en un problema cuando la recuperación de memoria es tan simple como detener un proceso. Para procesos de larga duración (es decir, un demonio), esa característica es especialmente importante.
Si bien la sobrecarga de cambio de contexto puede parecer insignificante con un pequeño número de trabajadores, las desventajas se vuelven más relevantes a medida que la carga aumenta de cientos a miles de conexiones concurrentes. En el mejor de los casos, el cambio de contexto escala O (n) a la cantidad de trabajadores presentes, pero en la práctica probablemente sea peor.
Donde los servidores que usan el bloqueo pueden no ser la opción ideal para cargas pesadas de E / S, son ideales para el trabajo intensivo de la CPU y el paso de mensajes se mantiene al mínimo.
Sin bloqueo:
Sin bloqueo sería algo como Node.js o nginx. Estos son especialmente conocidos por escalar a un número mucho mayor de conexiones por nodo bajo carga intensiva de IO. Básicamente, una vez que las personas alcanzan el límite superior de lo que los servidores basados en hilos / procesos pueden manejar, comienzan a explorar opciones alternativas. Esto también se conoce como el problema C10K (es decir, la capacidad de manejar 10,000 conexiones concurrentes).
Los servidores asíncronos sin bloqueo generalmente comparten muchas características con un enfoque de subprocesos múltiples con bloqueo en el sentido de que debe tener cuidado para evitar cargas intensivas de CPU porque no desea sobrecargar el subproceso principal. La ventaja es que la sobrecarga incurrida por el cambio de contexto se elimina esencialmente y con solo pasar un mensaje de contexto se convierte en un problema.
Si bien puede que no funcione para muchos protocolos de red, la naturaleza sin estado de HTTP funciona especialmente bien para arquitecturas sin bloqueo. Al usar la combinación de un proxy inverso y varios servidores HTTP sin bloqueo, es posible identificar y enrutar los nodos que experimentan una gran carga.
Incluso en un servidor que solo tiene un nodo, es muy común que la configuración incluya un servidor por núcleo de procesador para maximizar el rendimiento.
Ambos:
El caso de uso 'ideal' sería una combinación de ambos. Un proxy inverso en el frente dedicado a las solicitudes de enrutamiento en la parte superior, luego una mezcla de servidores bloqueantes y no bloqueantes. Sin bloqueo para tareas de E / S como servir contenido estático, contenido de caché, contenido html. Bloqueo para tareas pesadas de CPU como codificación de imágenes / video, transmisión de contenido, procesamiento de números, escritura de bases de datos, etc.
En tu caso:
Si solo está revisando los encabezados pero no está procesando las solicitudes, lo que esencialmente está describiendo es un proxy inverso. En tal caso, definitivamente iría con un enfoque asíncrono.
Sugeriría consultar la documentación del proxy inverso incorporado de nginx .
Aparte:
Leí la redacción del enlace que proporcionó y tiene sentido que async sea una mala elección para su implementación particular. El problema se puede resumir en una declaración.
Descubrí que al cambiar entre clientes, el código para guardar y restaurar valores / estado era difícil
Estaban construyendo una plataforma estatal. En tal caso, un enfoque asíncrono significaría que tendría que guardar / cargar constantemente el estado cada vez que cambia el contexto (es decir, cuando se dispara un evento). Además, en el lado de SMTP están haciendo mucho trabajo intensivo de CPU.
Parece que tenían una comprensión bastante pobre de asíncrono y, como resultado, hicieron muchas suposiciones malas.