2011-11-28 15 views
8

Trabajo en una aplicación web que es una aplicación basada en la nube multi-tenant (muchos clientes, cada uno con su propio "entorno" separado, pero todo en conjuntos compartidos de hardware) y estamos presentando la capacidad de un usuario para trabajar por lotes para el procesamiento posterior. Los tipos de trabajo por lotes realmente no son importantes, es solo cantidad suficiente que hacerlo sin una cola de trabajo no es realmente práctico. Seleccionamos RabbitMQ como nuestro marco de cola subyacente.Grupos de trabajadores y colas de múltiples usuarios con RabbitMQ

Debido a que somos una aplicación multi-tenant, no necesariamente queremos que los clientes puedan causar largos tiempos de proceso de cola para otro cliente, así que una idea que hemos flotado es crear una cola en un base del cliente y tener un grupo de trabajadores compartidos apuntado en TODAS nuestras colas de clientes. El problema es que, al mejor que puedo imaginar, los trabajadores están directamente vinculados a una cola específica, no a un intercambio. En nuestro mundo ideal, nuestras colas de clientes se seguirán procesando, sin que un cliente bloquee a otra, de un grupo de trabajadores compartidos que podamos aumentar o reducir según sea necesario iniciando más trabajadores o cerrando los inactivos. Tener trabajadores atados a una cola específica nos impide esto en un sentido práctico, ya que con frecuencia tenemos muchos trabajadores que simplemente están inactivos en una cola sin actividad.

¿Es relativamente sencillo lograr esto? Soy bastante nuevo en RabbitMQ y realmente no he podido lograr lo que buscamos. Tampoco queremos tener que escribir una aplicación de consumidor de subprocesos múltiples muy compleja, es una pérdida de tiempo en desarrollo y tiempo de prueba que probablemente no podamos pagar. Nuestra pila está basada en Windows/.Net/C# si es germaine, pero no creo que deba tener una gran importancia en la cuestión que nos ocupa.

Respuesta

1

Puede hacer que su grupo de trabajadores consuma la misma cola única. Luego, el trabajo se distribuirá entre ellos y podrá aumentar/reducir su grupo para aumentar/disminuir su capacidad de procesamiento de trabajo.

+1

No estoy preguntando sobre la asignación de múltiples trabajadores a la misma cola, estoy preguntando sobre el reverso. Quiero que un grupo finito de trabajadores consuma desde un gran número (llamémoslo ~ 500) de colas. – bakasan

+1

He experimentado de primera mano con este tipo de enfoque y no es bonito: es difícil encontrar una heurística adecuada para procesar todas estas colas. ¿Procesa primero las colas más completas? ¿O los que tienen los mensajes más antiguos? En ambos casos, está fuera del protocolo AMQP y debe comenzar a tratar con la API de administración de Rabbit. Entonces, piense: tengamos el mismo número de colas que los trabajadores y agregue una asignación consistente de hash entre 500 Qs y las colas de trabajo. Entonces se da cuenta de que una sola cola yn trabajadores que compiten en ella es todo lo que necesita. –

+0

Tengo un requisito similar, sin embargo, quiero asegurarme de que los mensajes de un cliente en particular se procesen secuencialmente. Un contacto no se elimina antes de que se haya creado, etc. ¿Hay alguna configuración o configuración de RabbitMQ que pueda hacer esto y compartir la cola entre los trabajadores? (¿Es esta una nueva Q ...?) – Aaron

1

No entiendo por qué no utiliza los hostios de RabbitMQ y hace que su aplicación inicie sesión en RabbitMQ y se autentique en una conexión diferente para cada usuario.

Esto no significa que no pueda tener un supervisor de trabajadores que asigne trabajadores a un usuario u otro. Pero sí significa que todos los mensajes para cada usuario se procesan mediante intercambios y colas completamente independientes.

0

A los trabajadores se les asignan 0+ colas, no intercambios.

La lógica para la cual se tomarán las tareas de las que se implementan colas para cada trabajador en la clase indicada a través de CELERYD_CONSUMER, que es por defecto celery.worker.consumer.Consumer.

Puede crear una clase de consumidor personalizada ro implementa la lógica que desee. La parte difícil será decidir los detalles del algoritmo de "imparcialidad" que desea usar; pero una vez que haya decidido eso, puede implementarlo creando una clase de consumidor personalizada y asignándola a los trabajadores adecuados.

1

Se podría buscar en la aplicación de cola de prioridad (que no se implementa cuando esta pregunta se formuló originalmente): https://www.rabbitmq.com/priority.html

Si eso no funciona para usted, usted podría tratar de algunos otros trucos para lograr lo que want (que debería funcionar con versiones anteriores de RabbitMQ):

Puede tener 100 colas vinculadas a un intercambio de temas y establecer la clave de enrutamiento en un hash de la ID de usuario% 100, es decir, cada tarea tendrá una clave entre 1 y 100 y tareas para el mismo usuario tendrán la misma clave. Cada cola está vinculada con un patrón único entre 1 y 100.Ahora tiene una flota de trabajadores que comienza con un número de cola aleatorio y luego incrementa ese número de cola después de cada trabajo, de nuevo% 100 para volver a la cola 1 después de la cola 100.

Ahora su flota de trabajadores puede procesar hasta 100 usuarios únicos en paralelo, o todos los trabajadores pueden enfocarse en un solo usuario si no hay otro trabajo que hacer. Si los trabajadores necesitan desplazarse por las 100 colas entre cada trabajo, en el caso de que solo un usuario tenga muchos trabajos en una sola cola, naturalmente tendrá algunos gastos indirectos entre cada trabajo. Una menor cantidad de colas es una forma de lidiar con esto. También puede hacer que cada trabajador mantenga una conexión con cada una de las colas y consuma hasta un mensaje no reconocido de cada una. El trabajador puede recorrer los mensajes pendientes en la memoria mucho más rápido, siempre que el tiempo de espera del mensaje no reconocido sea suficientemente alto.

Alternativamente, podría crear dos intercambios, cada uno con una cola enlazada. Todo el trabajo va al primer intercambio y la cola, que consume un grupo de trabajadores. Si una unidad de trabajo lleva demasiado tiempo, el trabajador puede cancelarla y llevarla a la segunda fila. Los trabajadores solo procesan la segunda cola cuando no hay nada en la primera fila. También es posible que desee un par de trabajadores con la prioridad de colas opuesta para asegurarse de que las tareas que se ejecutan durante mucho tiempo aún se procesen cuando llegue un flujo interminable de tareas cortas, de modo que siempre se procesará un lote de usuarios. Esto no distribuirá verdaderamente su flota de trabajadores en todas las tareas, pero detendrá las tareas de ejecución prolongada de un usuario que impida que sus trabajadores ejecuten tareas de ejecución corta para ese mismo usuario u otro. También asume que puede cancelar un trabajo y volver a ejecutarlo más tarde sin ningún problema. También significa que habrá recursos desperdiciados de tareas que exceden el tiempo de espera y deben volver a ejecutarse como de baja prioridad. A menos que pueda identificar tareas rápidas y lentas por adelantado

La primera sugerencia con las 100 colas también podría tener un problema si hay 100 tareas lentas para un solo usuario, luego otro usuario publica un lote de tareas. Esas tareas no se verán hasta que se termine una de las tareas lentas. Si esto resulta ser un problema legítimo, podría combinar las dos soluciones.

Cuestiones relacionadas