paint-brush
Por qué debería (casi) siempre elegir Sync Gunicorn Workerspor@shamik-ray
23,451 lecturas
23,451 lecturas

Por qué debería (casi) siempre elegir Sync Gunicorn Workers

por Shamik Ray5m2020/04/19
Read on Terminal Reader
Read this story w/o Javascript

Demasiado Largo; Para Leer

Gunicorn es un servidor WSGI muy popular y su popularidad se debe a que es liviano, rápido y simple, pero puede admitir la mayoría de los requisitos que tendría para alojar una aplicación en producción. El tipo de trabajador predeterminado es Sync y lo defenderé. Los trabajadores asincrónicos como Gevent crean nuevos greenlets (pseudo subprocesos ligeros) Cada vez que llega una nueva solicitud, los greenlets generados por los subprocesos de trabajo los manejan. Al mismo tiempo, los recursos necesarios para atender las solicitudes serán menores.

Company Mentioned

Mention Thumbnail
featured image - Por qué debería (casi) siempre elegir Sync Gunicorn Workers
Shamik Ray HackerNoon profile picture

Cualquiera que trabaje en marcos de aplicaciones web WSGI como Flask sabrá que, como práctica recomendada, es muy importante usar un servidor HTTP WSGI como Gunicorn para implementar la aplicación fuera de sus servidores de desarrollo.

Gunicorn es un servidor WSGI muy popular y su popularidad se debe a que es liviano, rápido y simple, pero puede admitir la mayoría de los requisitos que tendría para alojar una aplicación en producción. No entraría en detalles aquí sobre "Por qué Gunicorn/O por qué no". Lo que discutiré aquí es qué tipo de trabajador debe seleccionar y por qué.

Gunicorn se basa en el modelo de trabajador anterior a la bifurcación. Esto significa que hay un proceso maestro central que gestiona un conjunto de procesos de trabajo. El maestro nunca sabe nada acerca de los clientes individuales. Todas las solicitudes y respuestas son manejadas completamente por procesos de trabajo.

Tipos de trabajadores

El trabajador gunicorn puede ser de 2 tipos amplios: Sync y Async .

El tipo de trabajador predeterminado es Sync y lo defenderé. Como sugiere el nombre, los trabajadores de sincronización ejecutan una solicitud tras otra. Puede tener varios trabajadores de este tipo, y el número de solicitudes concurrentes atendidas es igual al número de dichos trabajadores.

En contraste con esto, Gunicorn ofrece un tipo de trabajador asíncrono. Hablaré del tipo de trabajador Gevent que es el más popular entre todos. Los trabajadores asincrónicos como Gevent crean nuevos greenlets (pseudo subprocesos ligeros). Cada vez que llega una nueva solicitud, los greenlets generados por los subprocesos de trabajo los manejan. La idea central es que cuando hay una acción vinculada a IO en su código, el greenlet cederá y le dará un identificador a otro greenlet para usar la CPU. Entonces, cuando llegan muchas solicitudes a su aplicación, puede manejarlas simultáneamente, las llamadas vinculadas a IO no bloquearán la CPU y el rendimiento mejorará. Al mismo tiempo, los recursos necesarios para atender las solicitudes serán menores.

¿Por qué no trabajadores asíncronos?

Si bien es tentador usar un tipo de trabajador asíncrono como Gevent y generar miles de greenlets, tiene un costo que debe conocer.

La documentación de Gunicorn define claramente cuándo debe usar un tipo de trabajador asíncrono

cualquier aplicación web que realice solicitudes salientes a las API que pueden tardar una cantidad de tiempo indefinida en regresar se beneficiará de un trabajador asíncrono

Podemos inferir de esto que cualquier operación vinculada a IO donde IO es relativamente más larga puede beneficiarse de los trabajadores asíncronos.

Los puntos a favor de usar async son los siguientes

  • Las operaciones vinculadas a IO no usarán recursos de CPU y los ciclos de CPU no se desperdiciarán cuando esté haciendo IO. Algunas otras solicitudes pueden usar la CPU.
  • Las redes modernas pueden realizar muchas operaciones de red al mismo tiempo, además, las memorias RAM son más baratas que nunca, por lo que, en teoría, todas las E/S se pueden realizar en paralelo si tiene muchas solicitudes vinculadas a E/S.
  • Si uno o más de los servicios backend a los que está llamando tardan en responder, solo se verán afectadas las solicitudes que los están llamando y no las otras, ya que su subproceso de trabajo continúa respondiendo a otras solicitudes creando greenlets más nuevos y su CPU no. obstruido.
  • Por último, esto le permite tener una huella de memoria de trabajadores pequeña ya que los pseudo subprocesos comparten la memoria y si está cargando modelos grandes, puede tener un trabajador y un servidor más solicitudes (teóricamente, si hace las cosas bien)

Advertencias que no se especifican en los ejemplos

Hay muchos recursos/ejemplos en Internet donde encontrará personas que defienden a Gevent. Pero la mayoría de estos ejemplos no hablan sobre los problemas que enfrentaría al usarlo en la aplicación de grado de producción real.

  • El uso de Gevent necesita que todo su código sea de naturaleza cooperativa o todas las bibliotecas que use deben ser parcheables por monos . Ahora bien, esta línea puede sonar simple, pero es una gran pregunta. Esto significa asegurarse de que todos los controladores de base de datos, clientes, bibliotecas de terceros utilizados sean Python puro, lo que garantizaría que se puedan parchear con monos O que estén escritos específicamente con soporte de Gevent. Si alguna parte de su biblioteca o parte del código no funciona mientras realiza IO, entonces todos sus greenlets en ese trabajador se bloquean y esto resultará en paradas prolongadas. Deberá encontrar dicho código y corregirlo.
  • Usando greenlets, sus conexiones a sus servicios back-end explotarán y deben manejarse. Debe tener grupos de conexiones que se puedan reutilizar y, al mismo tiempo, asegurarse de que su aplicación y el servicio de back-end puedan crear y mantener tantas conexiones de socket.
  • Las operaciones de bloqueo de la CPU detendrán todos sus greenlets, por lo que si sus solicitudes tienen alguna tarea vinculada a la CPU, no será de mucha ayuda. Por supuesto, puede ceder explícitamente entre estas tareas, pero deberá asegurarse de que parte del código sea seguro para greenlet.
  • Debe hacer todo esto cada vez que usted o su equipo escriban una nueva pieza de código.

Si todo esto suena como algo que puede pagar a largo plazo, hágalo.

La sincronización es simple

Los trabajadores de sincronización se simplifican en gran medida y funcionan bien en la mayoría de los casos. Mi consejo es que comience con los trabajadores de sincronización e intente arreglar el código de su aplicación tanto como sea posible si eso está bajo su control, en lugar de esperar que suceda magia cuando active 'Gevent'.

Si todos sus servicios de back-end están en la misma red, la latencia será muy baja y no debería preocuparse mucho por bloquear IO. Puedo decir por experiencia que con 3 o 4 trabajadores puede manejar miles de usuarios simultáneos fácilmente con un caché de aplicación adecuado. En caso de que necesite más rendimiento, puede tener más subprocesos por trabajador, lo que hará que el trabajador escriba gthread, pero aún así, un trabajador de sincronización y la huella de memoria por subproceso serán menores.

Si tiene una gran cantidad de memoria por trabajador, tal vez porque está cargando un modelo grande, intente usar preload True, lo que garantizaría que está cargando y luego bifurcando a los trabajadores. Hay otras opciones tambien. Me encantaría escribir algo sobre eso más tarde.

Si su aplicación tiene varias llamadas salientes a las API fuera de su red, debe proteger su aplicación estableciendo tiempos de espera razonables en su grupo de conexiones de urllib/requests. Además, asegúrese de que su aplicación tenga tiempos de espera de trabajo razonables que garanticen que una o más solicitudes incorrectas no bloqueen sus otras solicitudes durante mucho tiempo.

Finalmente, si todo esto falla y no puede escalar y usar sus recursos de manera eficiente, considere usar trabajadores asincrónicos.

NOTA: En algunos casos específicos, como la configuración de un socket web, las solicitudes de transmisión y las respuestas, siempre deberá usar trabajadores asincrónicos.

Referencias:

Comprender el bloqueo de llamadas

Búsqueda de llamadas bloqueadas

Registros de Gevent B