2011-04-15 22 views
6

Escribo una clase simple que usarán mis aplicaciones para enviar y recibir mensajes usando RabbitMQ. He leído tantos How-Tos, publicaciones en blogs, informes y me gusta sobre RabbitMQ como pude encontrar. la mayoría de los ejemplos muestran que se usa la conexión y el canal empaquetados en un bloque de uso, y lo contradicen al decir que probablemente debería implementarlos como un singleton. Específicamente con respecto al canal, he visto comentarios que dicen que no debes tener más de un hilo usando un solo canal al mismo tiempo.Pautas de creación de canales RabbitMQ

Escribo mi biblioteca en C#. es un singleton que tiene una conexión estática conectada en la primera instanciación.

Pensé en hacer lo mismo para el canal, pero tengo la intención de utilizar la misma biblioteca para permitir la publicación/suscripción a múltiples intercambios/colas. Tanto la publicación como la suscripción se pueden hacer desde múltiples hilos.

Y finalmente mi pregunta: ¿Cómo debo implementar la creación de canales? Por mensaje? ¿Cada consumidor tiene un canal privado único, el acceso de sincronización del editor a un solo canal único? Usted capta mi deriva. Tenga en cuenta que tengo la intención de utilizar un solo servidor, con varias docenas de consumidores/editores, no mucho más.

Gracias!

Respuesta

2

No puedo comentar los detalles de una implementación C#, pero puede ser útil saber que los canales Amqp están diseñados para compartir una única conexión TCP, es decir, para permitir la multiplexación. Un solo canal solo puede enviar uno o recibir un mensaje a la vez, pero una conexión puede recibir mensajes en diferentes canales simultáneamente. La imagen tiene 2 grandes archivos de 1GB que envía a través de Amqp a un solo consumidor, es posible que los mensajes se dividan en fragmentos de 10K y se envíen en forma intercalada. Puede manipular el tamaño predeterminado del mensaje Amqp cuando está configurando la conexión, esto influye en si se producirá el entrelazado y cuándo; AFAIK esta función está destinada a ayudar a evitar la inanición cuando varios consumidores comparten una conexión y un consumidor recibe mensajes grandes.

HTH.

3

Aclara las partes internas de aqmp. Actualmente, tengo entendido lo siguiente: A. Puedo mantener una única conexión de tcp compartida en el servidor desde cada aplicación (como un recurso compartido estático) B. Debería crear un canal para cada "tarea" (uno para escuchar la cola X y otra para publicar en Y, etc. asumiendo que estas "tareas" se pueden ejecutar en paralelo) C. O puedo usar un canal para todo dentro de una sola aplicación, mientras me aseguro de que el acceso esté sincronizado - utilizando algún mecanismo de bloqueo, suponiendo que el tiempo real que abarca el canal utilizado (bloqueado) es relativamente muy corto.

Gracias.

2

Tiene la razón de que el canal NO es threadsafe y no debe accederse por más de un hilo.

Si planea utilizar colas diferentes, puede tener varias colas con un solo canal. Pero si planifica en varios intercambios (no estoy seguro de por qué querría más de uno aquí), se vería obligado a realizar un seguimiento de múltiples intercambios y canales en su singleton, o descargar esa responsabilidad a las personas que llaman.

Construiría su singleton, ya que tiene un patrón de observador y contiene todas las cosas RabbitMQ allí con referencias a sus llamadores. También necesitaría ordenar llamadas a un solo hilo que trata con esto o podría correr el riesgo de tener problemas con los objetos del canal.

4

Editar (2016-1-26): Los canales NO son seguros para hilos. La documentación de que ha cambiado entre April y May 2015. El nuevo texto:

casos canal no deben ser compartidos entre los hilos. Las aplicaciones deberían preferir usar un canal por subproceso en lugar de compartir el mismo canal en varios subprocesos. Si bien algunas operaciones en canales son seguras para invocar concurrentemente, algunas no lo son y resultarán en un entrelazado incorrecto de tramas en el cable. Compartir canales entre hilos también interferirá con * Publisher Confirms.

Desde su pregunta suena como usted no tiene un número predefinido y fijo de las discusiones que en su mayoría publicación/suscriben a RabbitMQ (en cuyo caso se podría considerar la creación de un canal como parte de la inicialización de la rosca , o usando un ThreadLocal<IModel>).

Si las operaciones concurrentes de RabbitMQ son raras o el tamaño de los mensajes es siempre pequeño, puede salirse con la suya simplemente colocando un lock(channel) alrededor de todas sus operaciones de pub/sub RabbitMQ. Si necesita que varias solicitudes se transmitan de forma intercalada (eso es lo que los canales son en primer lugar) mediante el uso de subprocesos arbitrarios, es posible que desee crear un grupo de canales , p. a ConcurrentQueue<IModel> donde Encola los canales no utilizados y Dequeue durante el tiempo que los necesita. La creación de canales es muy baja-overhead, y tengo la sensación, a partir de pruebas de rendimiento, de que el proceso creación de canal no implica ninguna red io, es decir, parece que un canal se crea automáticamente en el servidor RabbitMQ en el primer uso por un cliente.


OLD (pre 01/26/2016): Los detalles ahora en su mayoría obsoletas del Java e implementaciones .net:

Re: canales y múltiples hilos, que es un poco confuso debido a su dependencia de la implementación.

implementación Java: Channels are thread safe:

casos de canal son seguros para su uso por varios subprocesos.

But:

confirma que no se manejan correctamente cuando un canal se comparte entre varios subprocesos

implementación de .NET: Channels are not thread safe:

Si hay más de un hilo necesita acceder a un particular I Instancias modelo, la aplicación debe imponer la exclusión mutua en sí misma.

Los síntomas de la serialización incorrecta de operaciones iModel incluyen, pero no se limitan a,

• secuencias de fotogramas no válidos que se envían en el cable

• NotSupportedExceptions que son lanzados ...

Así además de la útil respuesta de Robin, que se aplica independientemente de si es segura o no, en la implementación de .NET, no puede simplemente compartir una conexión.

+1

Puede compartir una conexión. Usted "no puede" compartir un IModel (Canal) en la parte superior de una Conexión. – user2864740

Cuestiones relacionadas