Esta respuesta es complementaria a las otras y explica por qué Unicornio necesita nginx frente a ella .
TL; DR La razón por la que Unicorn generalmente se implementa junto con un proxy inverso como nginx es porque sus creadores lo diseñaron deliberadamente, haciendo una compensación por la simplicidad.
En primer lugar, no hay nada que te impida implementar Unicorn sin un proxy inverso. Sin embargo, esa no sería una muy buena idea; A ver por qué.
Unicorn sigue la filosofía de Unix que consiste en hacer una cosa y hacerlo bien , y es servir a clientes rápidos y de baja latencia (veremos lo que esto significa más adelante). El hecho de que Unicorn esté diseñado para clientes rápidos de baja latencia también implica que no es muy bueno con clientes lentos y de alta latencia , lo cual es cierto. Este es uno de los puntos débiles de Unicorn y es donde entra en juego un proxy inverso: se sienta frente a Unicorn y se ocupa de esos clientes lentos (veremos cómo más adelante).
Afortunadamente, dicho proxy inverso ya existe y se llama nginx .
La decisión de manejar solo clientes rápidos simplifica enormemente el diseño de Unicorn y permite una base de código mucho más simple y más pequeña, a costa de cierta complejidad adicional en el departamento de implementación (es decir, también debe implementar nginx además de Unicorn).
Una decisión alternativa podría ser diseñar Unicornio de tal manera que no necesite un proxy inverso. Sin embargo, esto significa que tendría que implementar una funcionalidad adicional para hacer todas las cosas que ahora hace nginx, lo que resulta en una base de código más compleja y más esfuerzos de ingeniería.
En cambio, sus creadores tomaron la decisión de aprovechar el software existente que está probado en batalla y muy bien diseñado, y evitar perder tiempo y energía en problemas ya resueltos por otro software.
Pero pongámonos técnicos y respondamos su pregunta:
¿Por qué se necesita implementar Unicorn junto con nginx?
Estas son algunas de las razones clave:
Unicorn utiliza bloqueo de E / S para clientes
Confiar en un proxy inverso significa que Unicorn no necesita usar E / S sin bloqueo. En cambio, puede usar el bloqueo de E / S, que es inherentemente más simple y fácil de seguir para el programador.
También como dice el documento DISEÑO :
[El uso de E / S de bloqueo] permite seguir una ruta de código más simple dentro del intérprete de Ruby y menos llamadas al sistema.
Sin embargo, esto también tiene algunas consecuencias:
Punto clave # 1: Unicorn no es eficiente con clientes lentos
(Por simplicidad, asumimos una configuración con 1 trabajador Unicornio)
Dado que se usa el bloqueo de E / S, un trabajador de Unicorn solo puede atender a un cliente a la vez , por lo que un cliente lento (es decir, uno con una conexión lenta) mantendría al trabajador ocupado por más tiempo (de lo que lo haría un cliente rápido) ) Mientras tanto, los otros clientes solo esperarían hasta que el trabajador vuelva a estar libre (es decir, las solicitudes se acumularían en la cola).
Para solucionar este problema, se implementa un proxy inverso frente a Unicorn, que amortigua completamente las solicitudes entrantes y las respuestas de la aplicación, y luego envía cada una de ellas a la vez (es decir, las alimenta con cuchara) a Unicorn y a los clientes, respectivamente. En ese sentido, se podría decir que el proxy inverso "protege" a Unicorn de los clientes de red lentos.
Afortunadamente, Nginx es un gran candidato para este rol, ya que está diseñado para manejar de manera eficiente miles de cientos de clientes concurrentes.
Es de vital importancia que el proxy inverso esté dentro de la misma red local que Unicorn (típicamente en la misma máquina física que se comunica con Unicorn a través de un socket de dominio Unix), para que la latencia de la red se mantenga al mínimo.
Por lo tanto, tal proxy desempeña efectivamente el papel de un cliente rápido para el que Unicorn está diseñado para servir en primer lugar, ya que envía solicitudes a Unicorn rápido y mantiene a los trabajadores ocupados durante el menor tiempo posible (en comparación con la cantidad de tiempo que un cliente con una conexión lenta lo haría).
Punto clave # 2: Unicorn no es compatible con HTTP / 1.1 keep-alive
Dado que Unicorn utiliza el bloqueo de E / S, también significa que no puede admitir la función de mantenimiento de HTTP / 1.1, ya que las conexiones persistentes de clientes lentos ocuparían rápidamente a todos los trabajadores de Unicorn disponibles.
Por lo tanto, para aprovechar HTTP keep-alive, adivina qué: se usa un proxy inverso.
nginx, por otro lado, puede manejar miles de conexiones concurrentes usando solo unos pocos hilos. Por lo tanto, no tiene los límites de concurrencia que tiene un servidor como Unicorn (que esencialmente se limita a la cantidad de procesos de trabajo), lo que significa que puede manejar conexiones persistentes perfectamente. Más de cómo funciona esto realmente se puede encontrar aquí .
Es por eso que nginx acepta conexiones de mantenimiento de los clientes y las envía a Unicorn a través de conexiones simples a través de un socket Unix.
Punto # 3: Unicornio no es muy bueno para servir archivos estáticos
Nuevamente, servir archivos estáticos es algo que Unicorn puede hacer, pero no está diseñado para hacerlo de manera eficiente.
Por otro lado, los proxys inversos como nginx son mucho mejores (es decir, sendfile(2)
y el almacenamiento en caché).
Más
Hay otros puntos que se describen en el documento de FILOSOFÍA (ver "Rendimiento mejorado a través de proxy inverso" ).
Vea también algunas de las características básicas de nginx .
Vemos que al aprovechar el software existente (es decir, nginx) y siguiendo la filosofía de Unix de "hacer una cosa y hacerlo bien", Unicorn puede seguir un diseño e implementación más simples mientras se mantiene eficiente para servir aplicaciones Rack (por ejemplo. su aplicación Rails).
Para obtener más información, consulte la filosofía y los documentos de diseño de Unicorn que explican con más detalle las opciones detrás del diseño de Unicorn y por qué nginx se considera un buen proxy inverso para Unicorn.