execstart - gunicorn time
Trabajadores de Gunicorn e hilos (1)
Déjame intentar una respuesta. Supongamos que al principio mi despliegue solo tiene un solo trabajador gunicornio. Esto me permite manejar solo una solicitud a la vez. El trabajo de mi trabajador es simplemente hacer una llamada a google.com y obtener los resultados de búsqueda para una consulta. Ahora quiero aumentar mi rendimiento. Tengo las siguientes opciones
Mantener un solo trabajador y aumentar el número de subprocesos en ese trabajador
Esto es lo más fácil. Dado que los subprocesos son más ligeros (menos consumo de memoria) que los procesos, mantengo solo un trabajador y agrego varios subprocesos a eso. Gunicorn se asegurará de que el maestro pueda enviar más de una solicitud al trabajador. Dado que el trabajador es multiproceso, es capaz de manejar 4 solicitudes. Fantástico. Ahora, ¿por qué necesitaría más trabajadores alguna vez?
Para responder a eso, asuma que necesito hacer algún trabajo en los resultados de búsqueda que Google devolvió. Por ejemplo, es posible que también desee calcular un número primo para cada consulta de resultados. Ahora estoy haciendo que mi carga de trabajo esté vinculada y tengo un problema con el bloqueo global del intérprete de python. Aunque tengo 4 hilos, solo un hilo puede procesar los resultados a la vez. Esto significa que para obtener un verdadero rendimiento paralelo necesito más de un trabajador.
Aumentar el número de trabajadores, pero todos los trabajadores son de un solo hilo
Entonces, ¿por qué necesito esto sería cuando necesito un verdadero procesamiento paralelo? Cada trabajador puede hacer una llamada paralela a google.com, obtener resultados y hacer cualquier procesamiento. Todo en paralelo. Fantástico. Pero el inconveniente es que los procesos son más pesados, y mi sistema podría no cumplir con las demandas de los trabajadores en aumento para lograr el paralelismo. Así que la mejor solución es aumentar los trabajadores y también agregar más hilos a cada trabajador.
Aumentar el número de trabajadores y cada trabajador es multiproceso.
Supongo que esto no necesita más explicación.
Cambiar el tipo de trabajador a Async
Ahora, ¿por qué querría hacer esto? Para responder, recuerda que incluso los hilos consumen memoria. Hay bibliotecas (una construcción radical que puedes buscar) implementadas por la biblioteca gevent que te permiten obtener hilos sin tener que crear hilos. Entonces, si creas tu gunicornio para usar gevent de tipo trabajador, obtienes el beneficio de NO tener que crear hilos en tus trabajadores. Suponga que está obteniendo hilos sin tener que crearlos explícitamente.
Por lo tanto, para responder a su pregunta, si está utilizando worker_type de algo que no sea Sync, no necesita aumentar el número de subprocesos en su configuración de Gunicorn. Puedes hacerlo, por todos los medios, pero un poco derrota el propósito.
Espero que esto haya ayudado.
También intentaré responder las preguntas específicas.
No, la opción de subproceso no está presente para la clase de trabajo Async. Esto realmente debe ser más claro a través de la documentación. Preguntándome por qué eso no ha sucedido.
Esta es una pregunta que necesita más conocimiento de su aplicación específica. Si el procesamiento de estos 100s de solicitudes paralelas solo involucra el tipo de operaciones de E / S, como buscar desde la base de datos, guardar y recopilar datos de alguna otra aplicación, entonces puede hacer uso del trabajador de subprocesos. Pero si ese no es el caso y desea ejecutarse en una CPU central porque las tareas están extremadamente ligadas a la computación, tal vez como el cálculo de números primos, debe usar el trabajador de sincronización. El razonamiento de Async es ligeramente diferente. Para usar Async, debe asegurarse de que su procesamiento no esté vinculado al proceso, esto significa que no podrá utilizar múltiples núcleos. La ventaja que obtienes es que la memoria que tendrían varios subprocesos no estaría allí. Pero tienes otros problemas como bibliotecas parcheadas que no son de mono. Mueva a Async solo si el trabajador de subprocesos no cumple con sus requisitos.
Sincronización, los trabajadores sin subprocesos son la mejor opción si desea una seguridad absoluta de subprocesos entre sus bibliotecas.
En términos de Gunicorn, soy consciente de que hay varias clases de trabajadores, pero para esta conversación solo estoy mirando los tipos de sincronización y asíncrono.
Desde mi entendimiento ...
sync
workers = (2 * cpu) + 1
worker_class = sync
async (gevent)
workers = 1
worker_class = gevent
worker_connections = a value (lets say 2000)
Entonces (basado en un sistema de 4 núcleos) usando trabajadores de sincronización, puedo tener un máximo de 9 conexiones procesando en paralelo. Con Async puedo tener hasta 2000, con las advertencias que vienen con async.
Preguntas
- Entonces, ¿dónde encajan los hilos? ¿Puedo agregar subprocesos a los tipos de trabajo de sincronización y asíncrono?
- ¿Cuál es la mejor opción entre los trabajadores de Gunicorn? ¿Debo colocar gunicorn delante de una API de Django, con el requisito de procesar cientos de solicitudes en paralelo?
- ¿Son seguras las hebras de clases de gevent y sync worker?