java jms activemq failovercluster

java - ActiveMQ: cómo manejar failovers de intermediarios al usar colas temporales



jms failovercluster (2)

En mis aplicaciones JMS utilizamos colas temporales en los productores para poder recibir respuestas de las aplicaciones del consumidor.

Estoy enfrentando exactamente el mismo problema en mi parte final como se menciona en este hilo: http://activemq.2283324.n4.nabble.com/jira-Created-AMQ-3336-Temporary-Destination-errors-on-H-A-failover-in-broker-network-with-Failover-tt-td3551034.html#a3612738

Cada vez que reiniciaba un intermediario arbitrario en mi red, recibía muchos errores como este en el registro de mi aplicación para el consumidor al intentar enviar una respuesta a una cola temporal:

javax.jms.InvalidDestinationException: Cannot publish to a deleted Destination: temp-queue://ID:...

Entonces vi que la respuesta de Gary sugería usar

jms.watchTopicAdvisories=false

como un brokerURL URL en el cliente brokerURL . Inmediatamente cambié las URL de mi agente de cliente con este parámetro adicional. Sin embargo, ahora veo errores como este cuando reinicio mis intermediarios en la red para esta prueba de conmutación por error:

javax.jms.JMSException: The destination temp-queue: //ID:client.host-65070-1308610734958-2:1:1 does not exist.

Estoy usando la versión ActiveMQ 5.5. Y mi URL de corredor de cliente se ve así:

failover:(tcp://amq-host1:61616,tcp://amq-host2.tred.aol.com:61616,tcp://amq-host3:61616,tcp://amq-host4:61616)?jms.useAsyncSend=true&timeout=5000&jms.watchTopicAdvisories=false

Además, aquí está mi XML de configuración de activemq para uno de los 4 intermediarios: amq1.xml

¿Puede alguien aquí ver este problema y sugerirme qué error estoy cometiendo en esta configuración?

Actualizar:

Para aclarar más sobre cómo estoy haciendo solicitud-respuesta en mi código:

  1. Ya uso un destino por productor (es decir, cola temporal) y configuré esto en el encabezado de respuesta de cada mensaje.
  2. Ya estoy enviando un identificador de correlación único por mensaje en el encabezado JMSCorrelationID.
  3. Por lo que sé, incluso Camel y Spring también están utilizando la cola temporal para el mecanismo de solicitud y respuesta. La única diferencia es que la implementación de Spring JMS crea y destruye la cola temporal para cada mensaje, mientras que yo creo la cola temporal para toda la vida del productor. Esta cola temporal se destruye cuando se cierra la aplicación del cliente (productor) o por el agente de AMQ cuando se da cuenta de que no hay un productor activo conectado con esta cola temporal.
  4. Ya estoy configurando la caducidad de un mensaje en cada mensaje en el lado Productor para que el mensaje no se mantenga en una cola demasiado tiempo (60 segundos).

Existe un atributo de intermediario, org.apache.activemq.broker.BrokerService # cacheTempDestinations que debería ayudar en la conmutación por error: case. Establezca eso en true en la configuración xml, y un destino temporal no se eliminará inmediatamente cuando un cliente se desconecte. Una conmutación por error rápida: la reconexión podrá volver a producir y / o consumir desde la cola temporal.

Hay una tarea de temporizador basada en timeBeforePurgeTempDestinations (predeterminado 5 segundos) que maneja la eliminación de caché.

Una advertencia, sin embargo, no veo ninguna prueba en activemq-core que haga uso de ese atributo, así que no puedo darte ninguna garantía en este caso.


Las colas temporales se crean en el intermediario al que se conecta el solicitante (productor) en su escenario de respuesta de solicitud. Se crean a partir de una javax.jms.Session , por lo que en esa sesión desconectada, ya sea debido a la desconexión del cliente o la falla / failover del intermediario, esas colas se han ido de forma permanente. Ninguno de los otros intermediarios entenderá lo que significa cuando uno de sus consumidores intente responder a esas colas; de ahí tu excepción.

Esto requiere un cambio arquitectónico en la mentalidad, suponiendo que desea hacer frente a la conmutación por error y persistir todos sus mensajes. Aquí hay una manera general de atacar el problema:

  1. Sus encabezados de respuesta deben referirse a una cola específica para el proceso del solicitante: por ejemplo, queue:response.<client id> . El ID del cliente puede ser un nombre estándar si tiene un número limitado de clientes, o un UUID si tiene un gran número de ellos.
  2. El mensaje de salida debe establecer un identificador de correlación (simplemente un identificador que le permite asociar una solicitud con una respuesta, los solicitantes después de que todos puedan hacer más de una solicitud al mismo tiempo). Esto se establece en el encabezado JMSCorrelationID , y debe copiarse de la solicitud al mensaje de respuesta.
  3. El solicitante debe configurar un oyente en esa cola que devolverá el cuerpo del mensaje al hilo solicitante en función de esa identificación de correlación. Hay que escribir un código de subprocesamiento múltiple para esto, ya que necesitará administrar manualmente algo así como un mapa de id. De correlación a subprocesos de origen (quizás a través de Futures).

Este es un enfoque similar al de Apache Camel para solicitud-respuesta sobre mensajes .

Una cosa a tener en cuenta es que la cola no desaparecerá cuando el cliente lo haga, por lo que debe establecer un tiempo para vivir en el mensaje de respuesta de manera que se elimine del intermediario si no se ha consumido; de lo contrario, obtendrá una acumulación de mensajes no consumidos. También deberá configurar una estrategia de cola de mensajes no entregados para descartar automáticamente los mensajes caducados .