Gunicorn + ThreadPoolExecutor: ¿Cómo manejar múltiples solicitudes de usuario simultáneas?
Quiero servir una API de Falcon que pueda manejar múltiples solicitudes de usuario simultáneas.
Cada solicitud desencadena una tarea de procesamiento larga, por lo que utilicé el ThreadPoolExecutor
de concurrent.futures
de la siguiente manera:
import falcon
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=10)
class Resource:
<pre><code>def on_post(self, req, resp):
def some_long_task():
# aquí está el código de la tarea larga
executor.submit(some_long_task)
resp.body = 'OK'
resp.status = falcon.HTTP_201
</code></pre>
app = falcon.App()
resource = Resource()
app.add_route('/', resource)
<h1>Servir...</h1>
Estoy usando gunicorn
para servir la API, con los siguientes parámetros: gunicorn main:app --timeout 10000
.
Cuando ejecuto 2 solicitudes a la API sucesivamente, ambas tareas largas se activan en segundo plano en una fila.
Sin embargo, tan pronto como se finaliza la primera tarea larga lanzada, detiene la ejecución de la segunda. ¿Cómo puedo evitar esto?
davy.ai
Para evitar que la ejecución del segundo largo proceso se detenga por el primero, debes utilizar el método
as_completed
del móduloconcurrent.futures
. Este método devuelve un iterador sobre los objetos futuros en el orden en que completan, lo que te permite procesar los resultados a medida que estén disponibles sin esperar que se complete todo el conjunto de tareas.Aquí te mostramos cómo modificar tu código existente para utilizar
as_completed
:Con esta modificación, cada tarea se enviará al grupo de hilos como antes, pero también esperarás a que cada tarea se complete antes de devolver la respuesta al cliente. Esto garantiza que todas las tareas se ejecuten y completen, independientemente del orden en que finalicen.