Estoy tratando de construir un servidor web Python usando Django y Waitress, pero me gustaría saber cómo Waitress maneja las solicitudes concurrentes y cuándo puede ocurrir el bloqueo .
Si bien la documentación de Waitress menciona que hay varios subprocesos de trabajo disponibles, no proporciona mucha información sobre cómo se implementan y cómo los afecta Python GIL (énfasis mío):
Cuando un canal determina que el cliente ha enviado al menos una solicitud HTTP válida completa, programa una "tarea" con un "despachador de subprocesos". El despachador de subprocesos mantiene un grupo fijo de subprocesos de trabajo disponibles para hacer el trabajo del cliente (de manera predeterminada, 4 subprocesos). Si un subproceso de trabajo está disponible cuando se programa una tarea, el subproceso de trabajo ejecuta la tarea. La tarea tiene acceso al canal y puede volver a escribir en el búfer de salida del canal. Cuando todos los hilos de trabajo están en uso , las tareas programadas esperarán en una cola para que un hilo de trabajo esté disponible.
Tampoco parece haber mucha información sobre Stackoverflow. De la pregunta "¿El trabajador asincrónico de greadread de Gunicorn es análogo a la camarera?" :
La camarera tiene un subproceso maestro asíncrono que almacena las solicitudes y almacena cada solicitud en uno de sus subprocesos de trabajo de sincronización cuando finaliza la E / S de la solicitud.
Estas declaraciones no abordan el GIL (al menos desde mi entendimiento) y sería genial si alguien pudiera dar más detalles sobre cómo funcionan los hilos de trabajo para Waitress. ¡Gracias!
Respuestas:
Así es como funcionan generalmente los servidores asincrónicos controlados por eventos:
Casi de la misma manera que acabo de describir arriba. Y para los trabajadores crea hilos, no procesos.
La camarera usa hilos para los trabajadores. Entonces, sí, se ven afectados por GIL en el sentido de que no son realmente concurrentes, aunque parecen serlo. "Asíncrono" es el término correcto.
Los subprocesos en Python se ejecutan dentro de un solo proceso, en un solo núcleo de CPU, y no se ejecutan en paralelo. Un hilo adquiere el GIL por un período de tiempo muy pequeño y ejecuta su código y luego el GIL es adquirido por otro hilo.
Pero dado que el GIL se libera en la E / S de la red, el proceso padre siempre adquirirá el GIL siempre que haya un evento de red (como una solicitud entrante) y de esta manera puede estar seguro de que el GIL no afectará las operaciones vinculadas a la red ( como recibir solicitudes o enviar respuestas).
Por otro lado, los procesos de Python son realmente concurrentes: pueden ejecutarse en paralelo en múltiples núcleos. Pero Waitress no usa procesos.
¿Deberías estar preocupado?
Si solo está realizando pequeñas tareas de bloqueo como lectura / escritura de bases de datos y solo atiende a unos pocos cientos de usuarios por segundo, entonces el uso de hilos no es realmente tan malo.
Para servir a un gran volumen de usuarios o realizar tareas de bloqueo de larga duración, puede buscar colas de tareas externas como Celery . Esto será mucho mejor que generar y gestionar procesos usted mismo.
fuente