web-dev-qa-db-fra.com

Quand utiliser des acteurs au lieu de solutions de messagerie telles que WebSphere MQ ou Tibco Rendezvous?

J'ai déjà lu la question et les réponses à Quelles décisions de conception favoriseraient les acteurs de Scala au lieu de JMS? .

Habituellement, nous utilisons des solutions de messagerie qui existent déjà depuis des années: soit une implémentation JMS telle que WebSphere MQ ou Apache ActiveMQ est utilisée pour la communication point à point, soit Tibco Rendevous pour la messagerie multidiffusion.

Ils sont très stables, éprouvés et offrent une disponibilité et des performances élevées. Néanmoins, la configuration et l'installation semblent beaucoup plus complexes que dans Akka.

Quand et pourquoi devrais-je utiliser Akka pour certains cas d'utilisation où les produits susmentionnés - WebSphere MQ ou ActiveMQ - ont été utilisés avec succès jusqu'à présent? Pourquoi devrais-je envisager d'utiliser Akka au lieu de WebSphere MQ ou Tibco RV dans mon futur projet?

Et quand dois-je éviter Akka? Offre-t-il la même haute disponibilité et les mêmes performances que les autres solutions? Ou est-ce une mauvaise idée de comparer même Akka aux autres middlewares de messagerie?

Peut-être qu'il existe également une autre solution de messagerie dans l'environnement JVM que je devrais envisager en plus de JMS (Point-to-Point), TibcoRV (Multicast) et Akka?

104
Kai Wähner

Tout d'abord, les "anciens" systèmes de messages (MQ) sont plus anciens dans la mise en œuvre, mais ils sont une idée d'ingénierie plus récente: files d'attente persistantes transactionnelles. Scala Actors et Akka sont peut-être une implémentation plus récente mais sont construits sur un ancien modèle concurrent d'Actors.

Les deux modèles finissent cependant par être très similaires dans la pratique car ils sont tous deux basés sur un message d'événement: Voir ma réponse à RabbitMQ vs Akka .

Si vous allez coder uniquement pour la JVM, Akka est probablement un bon choix. Sinon, j'utiliserais RabbitMQ.

De plus, si vous êtes un développeur Scala, alors Akka devrait être une évidence. Cependant, les liaisons Java Java Akka ne sont pas très Java-ish et nécessitent un casting en raison au système de type de Scala.

Aussi en Java les gens ne font généralement pas d'objets immuables que je vous recommande de faire pour la messagerie. Par conséquent, il est très facile dans Java de faire accidentellement quelque chose en utilisant Akka qui ne sera pas mis à l'échelle (en utilisant des objets mutables pour les messages, en s'appuyant sur un état de rappel de fermeture étrange). Avec MQ, ce n'est pas un problème car les messages sont toujours sérialisés au prix de la vitesse. Avec Akka, ils ne le sont généralement pas.

Akka évolue également mieux avec une grande quantité de consommateurs que la plupart des MQ. En effet, pour la plupart des clients MQ (JMS, AMQP), chaque connexion de file d'attente nécessite un thread ... donc beaucoup de files d'attente == beaucoup de threads exécutés en permanence. C'est principalement un problème client. Je pense qu'ActiveMQ Apollo a un répartiteur non bloquant qui résout prétendument ce problème pour AMQP. Le client RabbitMQ dispose de canaux qui vous permettent de combiner plusieurs consommateurs, mais il y a toujours des problèmes avec un grand nombre de consommateurs pouvant entraîner la mort de blocages ou de connexions, donc généralement plus de threads sont ajoutés pour éviter ce problème.

Cela étant dit la communication à distance d'Akka est plutôt nouveau et n'offre probablement toujours pas toutes les garanties de message fiables et la QoS que les files d'attente de messages traditionnelles fournissent (mais cela change tous les jours). Il est également généralement peer-to-peer, mais je pense qu'il prend en charge le serveur-à-pair, ce qui est généralement ce que font la plupart des systèmes MQ (c'est-à-dire un point de défaillance unique), mais il existe des systèmes MQ qui sont peer-to-peer (RabbitMQ est serveur- à pair).

Enfin RabbitMQ et Akka forment une bonne paire. Vous pouvez utiliser Akka comme wrapper pour RabbitMQ, d'autant plus que RabbitMQ ne vous aide pas à gérer la consommation de messages et acheminer les messages localement (dans une seule machine virtuelle Java).

Quand choisir Akka

  • Avoir beaucoup de consommateurs (pensez à des millions).
  • Besoin d'une faible latence
  • Ouvert au modèle de simultanéité Acteur

Exemple de système: un système de chat interactif en temps réel

Quand choisir MQ

  • Besoin d'intégrer avec de nombreux systèmes différents (c'est-à-dire non JVM)
  • La fiabilité des messages est plus importante que la latence
  • Souhaite plus d'outils et d'interface utilisateur d'administration
  • En raison des points précédents, mieux pour les tâches de longue durée
  • Souhaiterait utiliser un modèle de concurrence différent de celui des acteurs

Exemple de système: un système de traitement par lots transactionnel planifié

EDIT en fonction des commentaires concernés

J'ai fait l'hypothèse que l'OP concernait le traitement distribué que Akka et Message Queues peuvent gérer. Je suppose qu'il parlait de distribué Akka . L'utilisation d'Akka pour la concurrence locale est une comparaison des pommes à l'orange avec la plupart des files d'attente de messages . Je dis le plus parce que vous pouvez appliquer le modèle de file d'attente de messages localement comme un modèle de concurrence (c'est-à-dire un sujet, des files d'attente, des échanges) que font à la fois la bibliothèque Reactor et simple-react .

Choisir le bon modèle/bibliothèque de concurrence est très important pour les applications à faible latence. Une solution de traitement distribué telle qu'une file d'attente de messages n'est généralement pas idéale car le routage est presque toujours effectué sur le câble, ce qui est évidemment plus lent que dans l'application et Akka serait donc un choix supérieur. Cependant, je crois que certaines technologies MQ propriétaires permettent un routage local. De plus, comme je l'ai mentionné plus tôt, la plupart des clients MQ sont assez stupides à propos du threading et ne comptent pas sur le non-blocage IO et ont un thread par connexion/file d'attente/canal ... ironiquement, le non-blocage io est pas toujours une faible latence mais est généralement plus économe en ressources.

Comme vous pouvez le voir, le sujet de la programmation distribuée et de la programmation simultanée est assez vaste et change tous les jours, donc mon intention initiale n'était pas confuse, mais plutôt de me concentrer sur un domaine particulier du traitement des messages distribués, ce qui m'intéressait, selon l'OP, En termes de simultanéité, on pourrait vouloir concentrer leurs recherches sur la programmation "réactive" (RFP/streams) qui est un modèle "plus récent" mais similaire au modèle d'acteur et au modèle de file d'attente de messages dont tous ces modèles peuvent généralement être combinés car ils sont basés sur des événements.

86
Adam Gent

Je ne suis pas un expert des systèmes de messagerie, mais vous pouvez les combiner avec Akka dans vos applications, en tirant le meilleur parti des deux mondes. Voici un exemple que vous pourriez trouver utile pour expérimenter avec Akka et les systèmes de messagerie, dans ce cas ZeroMQ:

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

4
Dean Wampler

Akka-Camel serait un meilleur exemple que ZeroMQ - ZeroMQ est une communication directe de TCP à TCP (d'où zéro - il n'y a pas de file d'attente de messages).

Avec AkkaCamel, vous pouvez résumer la file d'attente et produire/consommer des messages directement d'un acteur sans aucun code pour gérer le message poussé/tiré.

Vous pouvez renoncer à akka-zeromq et utiliser Akka directement avec la télécommande. Je pense que akka-zeromq est supprimé de la bibliothèque principale mais nous avons construit une bonne bibliothèque zeromq pour akka appelée scala-zeromq ( https://github.com/mDialog/scala-zeromq )

Akka a quelques cas d'utilisation clés:

1) État mutable

Il est plus facile de gérer l'état partagé en le cachant dans un acteur. Comme les acteurs traitent les messages de manière synchrone, vous pouvez conserver l'état d'un acteur et exposer ce champ avec une cohérence élevée via l'API d'acteur

2) Distribution

La concurrence est gratuite dans akka, vous dites donc qu'il s'agit vraiment de résoudre des problèmes de distribution. Distribution sur machines et cœurs. Akka a intégré une "transparence de localisation" pour l'envoi de messages via le fil. Il a également des clusters et des patters associés pour l'extension d'un service unique. Cela en fait une très bonne solution pour la distribution (par exemple l'architecture de micro-service)

Voici un exemple d'utilisation d'Akka avec ActiveMQ avec Akka-Camel (en utilisant 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);

    }
}
1
JasonG