<div dir="ltr"><div>Buenas,</div><div><br></div><div>Te contesto entre lineas y perdona si me pongo un poco pedante o chapas. Pero creo que es mejor no dar nada por hecho cuando hay más de un sistema corriendo a la vez.<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">El lun, 5 jul 2021 a las 21:31, Felipe Maza (<<a href="mailto:felipe@felipem.com">felipe@felipem.com</a>>) escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hola,</div><div><br></div><div>Llevo unos días viendo diferentes programas para gestionar sistemas de colas y, en principio, creo que casi todos parecen complejos para lo que necesito.</div><div><br></div><div>Mi problema a resolver es el siguiente, tenemos un modelo de predicción que se ejecuta periódicamente y también bajo demanda del usuario. Ese modelo se ejecuta en un solo hilo y tarda bastantes minutos en completar la tarea. Por tanto, puedo tener varias ejecuciones simultáneas siempre que no excedamos el número de cores disponibles, ya que en ese caso se vuelve el sistema excesivamente lento. Al modelo se le invoca a través de una pequeña api hecha con <span style="font-family:monospace">flask</span>. En el futuro puede que haya otros modelos en la misma máquina.</div><div><br></div><div>Hace un par de años para un problema similar ya me programé mi propio gestor de colas rudimentario,pero ahora busco algo que sea estable, con pocos bugs, mantenible, etc.</div><div><br></div><div>Las características que (creo que) necesito son:</div><div>- Encolar tareas (logicamente)</div></div></blockquote><div><br></div><div>Qué garantías de entrega quieres. Idealmente 1 vez y sólo una vez, pero en el mundo real debes elegir entre al menos una vez y como máximo una vez. Si tu tarea no es idempotente ese al menos una vez te puede generar problemas. Pero, ¿es correcto perder algún trabajo para asegurar que no llegan duplicados?<br></div><div><br></div><div><a href="https://docs.celeryproject.org/en/stable/userguide/calling.html#message-sending-retry">https://docs.celeryproject.org/en/stable/userguide/calling.html#message-sending-retry</a> <br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>- Tener colas con diferente prioridad (manuales, periódicas).</div></div></blockquote><div><br></div><div>Colas con prioridad o diferentes rutas de mensajes para dimensionar de una forma u otra los workers?</div><div><br></div><div><a href="https://docs.celeryproject.org/en/master/faq.html#does-celery-support-task-priorities">https://docs.celeryproject.org/en/master/faq.html#does-celery-support-task-priorities</a></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>- Registrar la salida, tanto si ha tenido éxito como si ha tenido errores.</div></div></blockquote><div><br></div><div>Qué ocurre si no llega a haber resultado? Imagina que tu tarea consume mucha memoria y es matada por el OOM killer de linux (si es que usas linux, si no imagina otro percance similar). O qué pasa si se apaga la máquina? Quieres que se considere que la tarea no ha sido procesada y se reintente si no has hecho ack de la tarea? Qué pasa si cada vez que reintentas la tarea se genera un problema de memoria y nunca se hace ack de ella? <br></div><div><br></div><div><a href="https://docs.celeryproject.org/en/stable/faq.html#why-do-workers-delete-tasks-from-the-queue-if-they-re-unable-to-process-them">https://docs.celeryproject.org/en/stable/faq.html#why-do-workers-delete-tasks-from-the-queue-if-they-re-unable-to-process-them</a></div><div><a href="https://docs.celeryproject.org/en/stable/faq.html#should-i-use-retry-or-acks-late">https://docs.celeryproject.org/en/stable/faq.html#should-i-use-retry-or-acks-late</a></div><div><a href="https://medium.com/@hengfeng/how-to-create-a-dead-letter-queue-in-celery-rabbitmq-401b17c72cd3">https://medium.com/@hengfeng/how-to-create-a-dead-letter-queue-in-celery-rabbitmq-401b17c72cd3</a></div><div><br></div><div>Qué ocurre si guardas los resultados de las tareas en un redis y este se cae? Lo configuras con persistencia a disco? Cuánto tiempo te puedes permitir perder resultados (que todavía persisten solo en memoria) ante una caida del Redis?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>- (opcional) En un futuro ejecutar otras apis con modelo en la misma máquina.<br></div></div></blockquote><div><br></div><div>En la misma máquina o en otra no es problema. Y separar los workers o no hacerlo tampoco lo sería. Este es el único requisito que me ha parecido simple.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div><br></div><div>Lo primero que he explorado ha sido <span style="font-family:monospace">Celery</span>, y es impresionante el montón de posibilidades que ofrece, tantas que ir poco más de los ejemplos iniciales me parece muy complejo para solucionar el problema anterior. Me da la sensación que hay que controlar un montón de aspectos para montarlo y mantenerlo correctamente; y que cuando aparezca algún error no va a ser rápido dar con la solución.</div></div></blockquote><div><br></div><div>Es muy complejo, posiblemente demasiado complejo. Pero son complejidades que hacen que se adapte a muchos tipos de problemas diferentes. Algunos ejemplos:</div><div>- Cuando tienes tareas livianas ir haciendo prefetch de varios mensajes y guardarlos en una cola junto al worker te quita tiempos de latencias. Cuando tienes tareas pesadas (tu caso) ese prefetch puede hacer que un worker acapare tareas mientras otros están ociosos <a href="https://docs.celeryproject.org/en/stable/userguide/optimizing.html#prefetch-limits">https://docs.celeryproject.org/en/stable/userguide/optimizing.html#prefetch-limits</a></div><div>- Si tu worker usa librerías con memory leaks, refrescar el worker después de algunas tareas puede darte la estabilidad que no tienen tus dependencias. Si no puedes configurar esto (en celery es configurable) te tocará a ti reiniciar los workers de vez en cuando o meter un monitor que los levante cuando mueran.</div><div>- Hay quien necesita y quien no montar workflows sobre las tareas <a href="https://docs.celeryproject.org/en/stable/userguide/canvas.html">https://docs.celeryproject.org/en/stable/userguide/canvas.html</a></div><div>- Si tienes tareas programadas o recurrentes con celery puedes usar celery beat y no depender del cron de tu sistema.</div><div>- ...<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div>Después de mirar otras alternativas, con la que parece que he montado una primera versión que parece que me lo soluciona, es <span style="font-family:monospace">Redis Queue </span>(<a href="https://python-rq.org/" target="_blank">https://python-</a><a href="https://python-rq.org/" target="_blank">rq</a><a href="https://python-rq.org/" target="_blank">.org/</a>). La forma en la que utiliza <span style="font-family:monospace">Redis</span> es relativamente simple, y más o menos ofrece lo que necesito.</div><div>En el tema de los <span style="font-family:monospace">worker</span> creo que ahí flojea un poco, pues parece que tendré que gestionar manualmente cuántos hay arrancados y si no se han muerto.</div><div><br></div></div></blockquote><div><br></div><div>Si hay una opción más simple que celery y que resuelve tus requisitos (presentes y futuros) tírate de cabeza a ella. Si no sabes cuáles son tus requisitos celery es una opción conservadora: cuando sepas que requisitos tienes posiblemente solo tengas que cambiar la config y en algún caso raro y marciano (posiblemente nunca) hacer cosas con los blueprints para extenderlo.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div>¿Tenéis experiencia resolviendo algún problema similar? ¿Creéis que merece la pena el esfuerzo para aprender <span style="font-family:monospace">celery</span> (u otra solución) para algo que no debería ser muy complejo? ¿<span style="font-family:monospace">Redis</span> os parece buen motor o debería ir a <span style="font-family:monospace">Rabbitmq</span>? Nunca había usado ninguno de ellos. ¿Cómo gestionais el tema de los <span style="font-family:monospace">worker</span>? Seguro que es más sencillo de lo que creo.<br></div><div>Cualquier comentario que queráis hacer será bienvenido.</div><div><br></div></div></blockquote><div><br></div>Celery es muy complejo. Estas son sus partes y como extenderlo <a href="https://docs.celeryproject.org/en/latest/userguide/extending.html">https://docs.celeryproject.org/en/latest/userguide/extending.html</a></div><div class="gmail_quote"><br></div><div class="gmail_quote">Pero aparte de complejo tiene cosas que no aprovechan esa complejidad y resultan complejas de usar correctamente, por ejemplo configurar celerybeat en alta disponibilidad <a href="https://github.com/celery/celery/issues/251">https://github.com/celery/celery/issues/251</a></div><div class="gmail_quote"><br></div><div class="gmail_quote">Es por eso que odio con todas mis fuerzas celery. Por un lado tiene un nivel de robustez y adaptabilidad a distintos tipos de trabajo que es digno de admirar. Por otro es fácil, muy fácil, pegarse un tiro en un pié si lo usas mal. Si no fuese porque todavía no he encontrado una alternativa mejor (aunque tengo algún candidato para ser probado) dejaría de usarlo ya, pero por el momento es lo menos malo que conozco.</div><div class="gmail_quote"><br></div><div class="gmail_quote">Así que por ahora, y con la boca pequeña, recomiendo celery.</div><div class="gmail_quote"><br></div><div class="gmail_quote">Un saludo,</div><div class="gmail_quote"><br></div><div class="gmail_quote">Javi<br></div><div class="gmail_quote"> <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div>Gracias,<br></div><div><br></div><div>Un saludo.<br></div><div><br>-- <br><div dir="ltr">Felipe Maza Fernández<br><a href="mailto:felipe@felipem.com" target="_blank">felipe@felipem.com</a><br>622 338 121<br></div></div></div>
_______________________________________________<br>
Python-es mailing list<br>
<a href="mailto:Python-es@python.org" target="_blank">Python-es@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-es" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-es</a><br>
</blockquote></div></div>