2011-04-17 16 views
82

Ya leí la pregunta y las respuestas al What design decisions would favour Scala's Actors instead of JMS?.Cuándo utilizar actores en lugar de soluciones de mensajería como WebSphere MQ o Tibco Rendezvous?

Por lo general, utilizamos soluciones de mensajería que existen desde hace años: una implementación JMS como WebSphere MQ o Apache ActiveMQ se utiliza para la comunicación Punto a Punto o Tibco Rendevous para la mensajería Multicast.

Son muy estables, comprobados y ofrecen alta disponibilidad y rendimiento. Sin embargo, la configuración y la configuración parecen mucho más complejas que en Akka.

¿Cuándo y por qué debo usar Akka para algunos casos de uso en los que los productos antes mencionados, WebSphere MQ o ActiveMQ, se han utilizado con éxito hasta el momento? ¿Por qué debería considerar usar Akka en lugar de WebSphere MQ o Tibco RV en mi proyecto futuro?

¿Y cuándo debería evitar Akka? ¿Ofrece la misma alta disponibilidad y rendimiento que las otras soluciones? ¿O es una mala idea incluso comparar Akka con los otros middlewares de mensajería?

Quizás también haya otra solución de mensajería en el entorno JVM que debería considerar además de JMS (punto a punto), TibcoRV (multidifusión) y Akka?

+2

http://stackoverflow.com/questions/4648280/scala-actors-vs-jms/4648843 # 4648843 puede ser útil. – srnm

Respuesta

4

No soy un experto en sistemas de mensajería, pero puedes combinarlos con Akka en tus aplicaciones, obteniendo lo mejor de ambos mundos. He aquí un ejemplo que le puede resultar útil para experimentar con los sistemas de Akka y de mensajería, en este caso ZeroMQ:

https://github.com/zcox/akka-zeromq-java

+5

ZeroMQ no es exactamente un sistema de mensajería. Es más bien algún tipo de enchufes mejorados. Los sistemas de mensajería completos son mucho más complejos que ZeroMQ. El proyecto en su enlace parece ser solo una capa delgada alrededor de ZeroMQ con Akka. –

67

En primer lugar los sistemas "más viejos" mensaje (MQ) son mayores en la ejecución, sino que son una nueva en la idea de ingeniería de: colas transaccionales persistentes. Scala Actors y Akka tal vez una implementación más nueva, pero se basan en un modelo de concurrencia más antiguo de Actores.

Sin embargo, los dos modelos terminan siendo muy similares en la práctica porque ambos están basados ​​en mensajes de eventos: Consulte mi respuesta al RabbitMQ vs Akka.

Si va a codificar solo para la JVM, entonces Akka es probablemente una buena opción. De lo contrario, usaría RabbitMQ.

Además, si usted es un desarrollador de Scala, entonces Akka debería ser una obviedad. Sin embargo, las vinculaciones Java de Akka no son muy Java-ish y requieren conversión debido al sistema de tipos de Scala.

También en Java las personas no suelen hacer objetos inmutables que recomiendo que hagas para enviar mensajes. En consecuencia, es muy fácil en Java hacer algo accidentalmente usando Akka que no se escale (usando objetos mutables para mensajes, dependiendo del extraño estado de devolución de llamadas). Con MQ esto no es un problema porque los mensajes siempre se serializan a costa de la velocidad. Con Akka generalmente no lo son.

Akka también escala mejor con una gran cantidad de consumidores que la mayoría de MQ. Esto se debe a que para la mayoría de los clientes de MQ (JMS, AMQP) cada conexión de cola requiere un hilo ... por lo tanto, muchas colas == lotes de hilos que se ejecutan permanentemente. Sin embargo, esto es principalmente un problema del cliente. Creo que ActiveMQ Apollo tiene un despachador no bloqueador que supuestamente soluciona ese problema para AMQP. El cliente RabbitMQ tiene canales que le permiten combinar múltiples consumidores, pero todavía hay problemas con la gran cantidad de consumidores que pueden causar la muerte de interbloqueos o conexiones, por lo que generalmente se agregan más hilos para evitar este problema.

Dicho esto, Akka's remoting es bastante nuevo y probablemente todavía no ofrezca todas las garantías de mensajes confiables y QoS que proporcionan las colas de mensajes tradicionales (pero eso está cambiando todos los días). También es generalmente peer-to-peer pero creo que es compatible con servidor a peer, que generalmente es lo que hacen la mayoría de los sistemas MQ (es decir, punto único de falla) pero hay sistemas MQ que son peer-to-peer (RabbitMQ es server- a la par).

Finalmente, RabbitMQ y Akka hacen un buen par. Puede usar Akka como envoltorio para RabbitMQ, especialmente porque RabbitMQ no lo ayuda a manejar el consumo de mensajes y enrutar los mensajes localmente (en una sola JVM).

Al elegir Akka

  • tienen un montón de consumidores (piense millones).
  • Necesidad de baja latencia
  • abierta al modelo Actor concurrencia

sistema Ejemplo: Un sistema de chat interactivo en tiempo real

Cuándo elegir MQ

  • Necesidad de integrarse con muchos sistemas diferentes (es decir, sin JVM)
  • fiabilidad del mensaje es más importante que la latencia
  • gustaría recibir más herramientas y administrador de interfaz de usuario
  • Debido a los puntos anteriores mejores para las tareas de ejecución larga
  • le gustaría utilizar un modelo de concurrencia diferente de Actores

sistema Ejemplo: Un sistema de procesamiento por lotes transaccional programado

EDITAR basado en los comentarios en cuestión

Supuse que el OP estaba relacionado con el procesamiento distribuido que tanto Akka como Message Queues pueden manejar. Es decir, asumí que estaba hablando de distributed Akka. El uso de Akka para la concurrencia local es una comparación de manzanas a naranjas para la mayoría de las colas de mensajes. Lo digo más porque puede aplicar el modelo de cola de mensajes localmente como un modelo de concurrencia (es decir, tema, colas, intercambios) que hacen tanto la biblioteca Reactor como simple-react.

Elegir el modelo/biblioteca de concurrencia correcto es muy importante para aplicaciones de baja latencia. Una solución de procesamiento distribuido como una cola de mensajes generalmente no es ideal porque el enrutamiento casi siempre se realiza a través del cable, que obviamente es más lento que dentro de la aplicación y, por lo tanto, Akka sería una elección superior. Sin embargo, creo que algunas tecnologías patentadas de MQ permiten el enrutamiento local. Además, como mencioné anteriormente, la mayoría de los clientes de MQ son bastante estúpidos con el subprocesamiento y no dependen de E/S no bloqueantes y tienen un hilo por conexión/cola/canal ... irónicamente, el no bloqueo no siempre es de baja latencia, pero generalmente es más eficiente.

Como se puede ver el tema de la programación distribuida y programación concurrente es bastante grande y cambiando todos los días por lo que mi intención original no se confunda sino más bien centrarse en un área particular de procesamiento de mensajes distribuido que es lo que a pesar de la OP estaba preocupado con . En términos de concurrencia uno podría querer enfocar sus búsquedas en programación "reactiva" (RFP/streams) que es un modelo "más nuevo" pero similar al modelo de actor y modelo de cola de mensajes de los cuales todos estos modelos se pueden combinar generalmente porque están basados ​​en eventos.

+3

Creo que una respuesta a una pregunta incorrecta no puede ser correcta. No puede comparar una cola de mensajes y un modelo de concurrencia. Están diseñados para resolver tareas COMPLETAMENTE diferentes y tienen en común solo la palabra "mensaje". –

+1

Bueno, sí y no. Akka admite la mensajería distribuida y usted podría construir muy fácilmente un modelo de simultaneidad fuera del paradigma de cola de mensajes (Google Spring's Reactor). Realmente, la única distinción ahora es que RabbitMQ tiene mensajes duraderos ... oh, espera, Akka lo apoya también ahora. Puede decir "Actor" en el título pero señala explícitamente a Akka, que tiene una superposición masiva con muchos sistemas basados ​​en mensajes (tanto concurrentes como distribuidos). –

+3

BTW @IgorS. el modelo de concurrencia típico utilizado con las colas de mensajes se llama SEDA (arquitectura de eventos por etapas). Además de utilizar Colas, Temas e Intercambios, es un modelo de simultaneidad en sí mismo (que también pasa a ser modelo distribuido ... al igual que el modelo de actor). También desprecio cuando alguien dice "pregunta incorrecta" ... además de preguntas inapropiadas, ¿cuándo puede una pregunta estar equivocada? Es sarcástico y elitista decir algo así. –

0

Akka-Camel sería un mejor ejemplo que ZeroMQ - ZeroMQ es una comunicación directa de tcp a tcp (por lo tanto, cero - no hay cola de mensajes).

Con AkkaCamel puede abstraer la cola y producir/consumir mensajes directamente de un actor sin ningún código para tratar con el mensaje de la cola de mensajes empujando/tirando.

Puede renunciar a akka-zeromq y usar Akka directamente con la comunicación remota. creo akka-zeromq está siendo retirado de la biblioteca central, pero hemos construido una buena biblioteca zeromq para akka llamada Scala-zeromq (https://github.com/mDialog/scala-zeromq)

Akka tiene un par de casos de uso clave principal:

1) estado mutable

Es más fácil manejar el estado compartido escondiéndolo en un actor. Como actores manejan mensajes de forma sincrónica, puede mantener el estado de un actor y exponer ese campo con alta consistencia a través de la API de agente

2) Distribución

concurrencia es libre en akka por lo que dicen que es realmente acerca de la solución de los problemas de distribución. Distribución en máquinas y núcleos. Akka ha incorporado una "transparencia de ubicación" para enviar mensajes a través del cable. También tiene clústeres y patrones asociados para escalar un solo servicio. Esto hace que sea una solución muy buena para la distribución (por ejemplo la arquitectura micro-servicio)

Aquí es un ejemplo del uso Akka con ActiveMQ con Akka-Camel (usando Java8)

import akka.actor.Props; 
import akka.camel.Camel; 
import akka.camel.CamelExtension; 
import akka.testkit.TestActorRef; 
import akka.testkit.TestProbe; 
import org.junit.Ignore; 
import org.junit.Test; 
import akka.camel.javaapi.UntypedProducerActor; 
import akka.camel.javaapi.UntypedConsumerActor; 
import static com.rogers.totes.TotesTestFixtures.*; 
import org.apache.activemq.camel.component.*; 

public class MessagingTest { 
    @Test @Ignore 
    public void itShouldStoreAMessage() throws Exception{ 
     String amqUrl = "nio://localhost:61616"; 
     Camel camel = (Camel) CamelExtension.apply(system); 
     camel.context().addComponent("activemq", ActiveMQComponent.activeMQComponent(amqUrl)); 

     TestProbe probe = TestProbe.apply(system); 
     TestActorRef producer = TestActorRef.create(system, Props.create((Producer.class))); 
     TestActorRef consumer = TestActorRef.create(system, Props.create((Consumer.class))); 
     producer.tell("Produce", probe.ref()); 

     Thread.sleep(1000); 
    } 
} 

class Producer extends UntypedProducerActor{ 

    @Override 
    public String getEndpointUri() { 
     return "activemq:foo.bar"; 
    } 
} 

class Consumer extends UntypedConsumerActor{ 

    @Override 
    public String getEndpointUri() { 
     return "activemq:foo.bar"; 
    } 

    @Override 
    public void onReceive(Object message) throws Exception { 
     System.out.println("GOT A MESSAGE!" + message); 

    } 
} 
Cuestiones relacionadas