Quando utilizzare gli attori invece di soluzioni di messaggistica come WebSphere MQ o Tibco Rendezvous?


106

Ho già letto la domanda e le risposte a Quali decisioni di design favorirebbero gli attori di Scala invece di JMS? .

Di solito, utilizziamo soluzioni di messaggistica che esistono già da anni: o un'implementazione JMS come WebSphere MQ o Apache ActiveMQ viene utilizzata per la comunicazione Point-To-Point, o Tibco Rendevous per la messaggistica multicast.

Sono molto stabili, collaudati e offrono alta disponibilità e prestazioni. Tuttavia, la configurazione e l'installazione sembrano molto più complesse che in Akka.

Quando e perché dovrei usare Akka per alcuni casi d'uso in cui i suddetti prodotti - WebSphere MQ o ActiveMQ - sono stati utilizzati con successo finora? Perché dovrei considerare l'utilizzo di Akka invece di WebSphere MQ o Tibco RV nel mio progetto futuro?

E quando dovrei evitare Akka? Offre la stessa alta disponibilità e prestazioni delle altre soluzioni? O è una cattiva idea persino confrontare Akka con gli altri middleware di messaggistica?

Forse c'è anche un'altra soluzione di messaggistica nell'ambiente JVM che dovrei considerare oltre a JMS (Point-to-Point), TibcoRV (Multicast) e Akka?


Risposte:


92

Prima di tutto, i sistemi di messaggi "più vecchi" (MQ) sono più vecchi nell'implementazione ma sono un'idea più recente nell'ingegneria delle code persistenti transazionali . Scala Actors e Akka potrebbero essere un'implementazione più recente, ma si basano su un vecchio modello di concorrenza degli attori.

Tuttavia, i due modelli finiscono per essere molto simili nella pratica perché entrambi sono basati su messaggi di eventi: vedi la mia risposta a RabbitMQ vs Akka .

Se codifichi solo per JVM, Akka è probabilmente una buona scelta. Altrimenti userei RabbitMQ.

Inoltre, se sei uno sviluppatore Scala, Akka dovrebbe essere un gioco da ragazzi. Tuttavia, i collegamenti Java di Akka non sono molto Java e richiedono il cast a causa del sistema di tipi di Scala.

Anche in Java le persone in genere non creano oggetti immutabili, cosa che ti consiglio di fare per la messaggistica. Di conseguenza è molto facile in Java fare accidentalmente qualcosa usando Akka che non si ridimensionerà (usando oggetti mutabili per i messaggi, basandosi su uno strano stato di callback di chiusura). Con MQ questo non è un problema perché i messaggi vengono sempre serializzati a scapito della velocità. Con Akka generalmente non lo sono.

Akka si adatta anche meglio alla maggior parte dei consumatori rispetto alla maggior parte di MQ. Questo perché per la maggior parte dei client MQ (JMS, AMQP) ogni connessione di coda richiede un thread ... quindi molte code == molti thread in esecuzione permanente. Tuttavia, questo è principalmente un problema del cliente. Penso che ActiveMQ Apollo abbia un dispatcher non bloccante che presumibilmente risolve il problema per AMQP. Il client RabbitMQ ha canali che consentono di combinare più consumatori, ma ci sono ancora problemi con un gran numero di consumatori che potenzialmente causano deadlock o connessioni a morire, quindi generalmente vengono aggiunti più thread per evitare questo problema.

Detto questo, il remoting di Akka è piuttosto nuovo e probabilmente non offre ancora tutte le garanzie di messaggi affidabili e QoS fornite dalle code di messaggi tradizionali (ma questo cambia ogni giorno). È anche generalmente peer-to-peer, ma penso che supporti il ​​server-to-peer che è generalmente ciò che fa la maggior parte dei sistemi MQ (cioè single point of failure) ma ci sono sistemi MQ che sono peer-to-peer (RabbitMQ è server- to-peer).

Alla fine RabbitMQ e Akka fanno davvero una buona coppia. Puoi utilizzare Akka come wrapper per RabbitMQ in particolare poiché RabbitMQ non ti aiuta a gestire il consumo di messaggi e instradare i messaggi localmente (in una singola JVM).

Quando scegliere Akka

  • Avere molti consumatori (pensa milioni).
  • Serve una bassa latenza
  • Aperto al modello di concorrenza degli attori

Sistema di esempio: un sistema di chat interattivo in tempo reale

Quando scegliere MQ

  • Necessità di integrazione con molti sistemi diversi (es. Non JVM)
  • L'affidabilità dei messaggi è più importante della latenza
  • Vorrei più strumenti e interfaccia utente di amministrazione
  • A causa dei punti precedenti è migliore per le attività di lunga durata
  • Vorrebbe utilizzare un modello di concorrenza diverso rispetto agli attori

Sistema di esempio: un sistema di elaborazione batch transazionale pianificato

MODIFICA in base ai commenti interessati

Ho ipotizzato che l'OP fosse interessato all'elaborazione distribuita che sia Akka che le code di messaggi possono gestire. Questo è che presumo stesse parlando di Akka distribuito . L'uso di Akka per la concorrenza locale è un confronto tra mele e arancioni con la maggior parte delle code di messaggi . Dico di più perché puoi applicare il modello di coda dei messaggi localmente come un modello di concorrenza (cioè argomento, code, scambi) che sia la libreria Reactor che la semplice reazione .

La scelta del modello / libreria di concorrenza corretto è molto importante per le applicazioni a bassa latenza. Una soluzione di elaborazione distribuita come una coda di messaggi in genere non è l'ideale perché l'instradamento viene quasi sempre eseguito in rete, il che è ovviamente più lento rispetto all'applicazione e quindi Akka sarebbe una scelta migliore. Tuttavia credo che alcune tecnologie MQ proprietarie consentano il routing locale. Inoltre, come ho detto prima, la maggior parte dei client MQ sono piuttosto stupidi riguardo al threading e non si affidano a IO non bloccanti e hanno un thread per connessione / coda / canale ... ironicamente l'io non bloccante non è sempre a bassa latenza ma è generalmente più risorsa efficiente.

Come puoi vedere, l'argomento della programmazione distribuita e della programmazione concorrente è piuttosto ampio e cambia ogni giorno, quindi la mia intenzione originale non era confusa, ma piuttosto concentrarsi su una particolare area dell'elaborazione dei messaggi distribuiti che è ciò di cui pensavo fosse interessato l'OP. In termini di concorrenza, si potrebbe voler concentrare le proprie ricerche sulla programmazione "reattiva" (RFP / flussi) che è un modello "più recente" ma simile al modello attore e al modello coda messaggi di cui tutti questi modelli possono essere generalmente combinati perché sono basati sugli eventi.


3
Penso che una risposta a una domanda sbagliata non possa essere giusta. Non è possibile confrontare una coda di messaggi e un modello di concorrenza. Sono costruiti per risolvere COMPLETAMENTE compiti diversi e hanno in comune solo la parola "messaggio".
Igor S.

2
Ebbene sì e no. Akka supporta la messaggistica distribuita e potresti creare facilmente un modello di concorrenza basato sul paradigma della coda dei messaggi (Google Spring's Reactor). L'unica differenza ora è che RabbitMQ ha messaggi durevoli .. oh aspetta Akka lo supporta anche adesso. Potrebbe dire "Attore" nel titolo, ma sottolinea esplicitamente Akka che ha una massiccia sovrapposizione con molti sistemi basati su messaggi (sia concorrenti che distribuiti).
Adam Gent

4
BTW @IgorS. il tipico modello di concorrenza utilizzato con le code di messaggi è chiamato SEDA (architettura gestita da eventi a stadi). Oltre a usare Queues, Topics, and Exchanges è un modello di concorrenza in sé (che sembra essere anche un modello distribuito .. proprio come il modello attore). Disprezzo molto anche quando qualcuno dice "domanda sbagliata" .. oltre alle domande inappropriate, quando una domanda può essere sbagliata? È irriverente ed elitario dire qualcosa del genere.
Adam Gent

1
Non ho mai detto che fossero intercambiabili. Dico anche che lavorano alla grande insieme e perché. Ma sta chiaramente parlando dell'akka distribuito qui e non dell'akka della libreria degli attori. È così che l'ho letto. Sentiti libero di modificare il mio post poiché il tuo punto è valido e potrebbe confondere gli altri che inciampano sul post.
Adam Gent

1
Una delle API di Akka Java: ora è molto pulita, specialmente con JDK 8 lambda. Sospetto che migliorerà se / quando introdurranno oggetti di valore con JDK 10.
Rob Crawford

4

Non sono un esperto di sistemi di messaggistica, ma puoi combinarli con Akka nelle tue app, ottenendo il meglio da entrambi i mondi. Ecco un esempio che potresti trovare utile per sperimentare con Akka e sistemi di messaggistica, in questo caso ZeroMQ:

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


6
ZeroMQ non è esattamente un sistema di messaggistica. È piuttosto una sorta di prese migliorate. I sistemi di messaggistica a tutti gli effetti sono molto più complessi di ZeroMQ. Il progetto al tuo collegamento sembra essere solo un sottile involucro attorno a ZeroMQ con Akka.
Vladimir Matveev

1

Akka-Camel sarebbe un esempio migliore di ZeroMQ: ZeroMQ è una comunicazione diretta da tcp a tcp (quindi zero - non c'è coda di messaggi).

Con AkkaCamel puoi astrarre la coda e produrre / consumare messaggi direttamente da un attore senza alcun codice per gestire il push / pull dei messaggi nella coda dei messaggi.

Puoi rinunciare a akka-zeromq e utilizzare Akka direttamente con il telecomando. Penso che akka-zeromq sia stato rimosso dalla libreria principale ma abbiamo costruito una buona libreria zeromq per akka chiamata scala-zeromq ( https://github.com/mDialog/scala-zeromq )

Akka ha un paio di casi d'uso principali:

1) Stato mutevole

È più facile gestire lo stato condiviso nascondendolo in un attore. Poiché gli attori gestiscono i messaggi in modo sincrono, puoi mantenere lo stato in un attore ed esporre quel campo con elevata coerenza tramite l'API dell'attore

2) Distribuzione

La concorrenza è gratuita in Akka, quindi dici che si tratta davvero di risolvere i problemi di distribuzione. Distribuzione tra macchine e core. Akka ha incorporato la "trasparenza della posizione" per l'invio di messaggi in rete. Ha clustering e schemi associati per ampliare anche un singolo servizio. Questo lo rende un'ottima soluzione per la distribuzione (es. Architettura di micro-servizi)

Ecco un esempio di utilizzo di Akka con ActiveMQ con Akka-Camel (utilizzando 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);

    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.