WebSphere MQやTibco Rendezvousなどのメッセージングソリューションの代わりにアクターを使用するのはいつですか?


106

JMSの代わりにScalaのアクターを支持する設計上の決定についての質問と回答をすでに読みました

通常、私たちは何年も前から存在しているメッセージングソリューションを使用します。WebSphereMQやApache ActiveMQなどのJMS実装がポイントツーポイント通信に使用されるか、Tibco Rendevousがマルチキャストメッセージングに使用されます。

それらは非常に安定しており、実績があり、高い可用性とパフォーマンスを提供します。それにもかかわらず、設定とセットアップはAkkaよりもはるかに複雑に見えます。

前述の製品(WebSphere MQまたはActiveMQ)がこれまで正常に使用されてきたいくつかのユースケースでAkkaを使用する必要があるのはなぜですか。今後のプロジェクトで、WebSphere MQまたはTibco RVの代わりにAkkaを使用することを検討する必要があるのはなぜですか?

そして、いつアッカを避けるべきですか?他のソリューションと同じ高可用性とパフォーマンスを提供していますか?それとも、Akkaを他のメッセージングミドルウェアと比較することさえ悪い考えですか?

たぶん、JVM(Point-to-Point)、TibcoRV(マルチキャスト)、Akka以外に検討する必要がある別のメッセージングソリューションもJVM環境にありますか?


回答:


92

まず、「古い」メッセージシステム(MQ)は実装が古いですが、エンジニアリングの考え方は新しいものです。つまり、トランザクション永続キューです。Scala ActorsとAkkaは新しい実装かもしれませんが、Actorの古い同時実行モデルに基づいて構築されています。

ただし、2つのモデルはどちらもイベントメッセージベースであるため、実際には非常に似ています。RabbitMQとAkkaに対する私の回答を参照してください。

JVM専用のコードを作成する場合は、おそらくAkkaが適切な選択です。それ以外の場合は、RabbitMQを使用します。

また、Scala開発者であれば、Akkaは非常に簡単です。ただし、AkkaのJavaバインディングはあまりJava風ではなく、Scalaの型システムによりキャストが必要です。

また、Javaでは通常、不変オブジェクトを作成しないため、メッセージングに推奨します。その結果、Javaでは、拡張できないAkkaを使用して誤って何かを実行するのが非常に簡単です(メッセージに可変オブジェクトを使用し、奇妙なクロージャーコールバック状態に依存しています)。MQでは、速度を犠牲にしてメッセージが常にシリアライズされるため、これは問題になりません。Akkaでは一般的にそうではありません。

また、Akkaは、大部分のMQよりも大量のコンシューマーに適しています。これは、ほとんどのMQ(JMS、AMQP)クライアントでは、すべてのキュー接続にスレッドが必要であるためです...したがって、多数のキュー==永続的に実行される多数のスレッド。これは主にクライアントの問題です。ActiveMQ Apolloには非ブロッキングディスパッチャーがあり、AMQPの問題を修正するとされています。RabbitMQクライアントには複数のコンシューマを組み合わせることができるチャネルがありますが、多数のコンシューマがデッドロックまたは接続の停止を引き起こす可能性があるという問題が依然としてあるため、通常、この問題を回避するためにスレッドを追加します。

そうは言っても、Akkaのリモート処理はかなり新しいものであり、おそらく従来のメッセージキューが提供する信頼できるメッセージ保証とQoSをまだすべて提供しているわけではありません(ただし、それは毎日変わります)。また、一般的にピアツーピアですが、ほとんどのMQシステムが行うサーバーツーピア(つまり、単一障害点)をサポートしていると思いますが、ピアツーピアのMQシステムがあります(RabbitMQはサーバーじっと見ます)。

最後に、RabbitMQとAkkaは実際に良いペアを作ります。特にRabbitMQはメッセージの消費の処理とローカルでのメッセージのルーティング(単一のJVM)を支援しないため、AkkaをRabbitMQのラッパーとして使用できます。

Akkaを選択するタイミング

  • たくさんの消費者がいる(数百万人と思う)。
  • 低レイテンシが必要
  • Actor同時実行モデルにオープン

システム例:インタラクティブなリアルタイムチャットシステム

MQを選択するタイミング

  • 多くの異なるシステム(つまり、JVM以外)と統合する必要がある
  • メッセージの信頼性は待ち時間よりも重要です
  • より多くのツールと管理UIが欲しい
  • 長期実行タスクには以前のポイントが優れているため
  • アクターとは異なる並行処理モデルを使用したい

システム例:スケジュールされたトランザクションバッチ処理システム

関連するコメントに基づいて編集

OPは、AkkaとMessage Queueの両方が処理できる分散処理に関係していると想定しました。それは私が彼が分散したアッカについて話していたと思います。ローカルの同時実行性にAkkaを使用することは、ほとんどのメッセージキューと比べるとかなり簡単です。あなたは両方の同時実行モデル(すなわち、トピック、キュー、取引所)としてローカルメッセージキューモデルを適用することができますので、私はほとんどの言う原子炉のライブラリとシンプルが反応しません。

適切な同時実行モデル/ライブラリを選択することは、低レイテンシアプリケーションにとって非常に重要です。メッセージキューなどの分散処理ソリューションは一般に理想的ではありません。ルーティングはほとんどの場合ネットワーク上で行われるため、アプリケーション内よりも明らかに低速であり、したがってAkkaが優れた選択肢となるからです。ただし、一部のプロプライエタリMQテクノロジではローカルルーティングが可能だと思います。また、前述したように、ほとんどのMQクライアントはスレッド化についてかなり愚かで、非ブロッキングIOに依存せず、接続/キュー/チャネルごとにスレッドを持っています...皮肉なことに、非ブロッキングIOは常に低遅延ではありませんが、一般により多くのリソースです効率的です。

ご覧のとおり、分散プログラミングと並行プログラミングのトピックはかなり大きく、毎日変化しているので、私の当初の意図は混乱せず、OPが関係していた分散メッセージ処理の特定の領域に焦点を当てていました。並行性の観点から、「新しい」が、アクターモデルやメッセージキューモデルと同様の「リアクティブ」プログラミング(RFP /ストリーム)に検索を集中したい場合があります。イベントベースです。


3
間違った質問への答えは正しくあり得ないと思います。メッセージキューと同時実行モデルを比較することはできません。それらは完全に異なるタスクを解決するために構築されており、共通して「メッセージ」という言葉しかありません。
Igor S.

2
はい、いいえ。Akkaは分散メッセージングをサポートしており、メッセージキューパラダイム(Google SpringのReactor)から並行性モデルを非常に簡単に構築できます。本当に今唯一の違いは、RabbitMQが永続的なメッセージを持っていることです。彼はタイトルで「俳優」と言うかもしれませんが、多くのメッセージベースのシステム(同時および分散の両方)と大幅に重複しているAkkaを明確に指摘しています。
アダム・ゲント

4
ところで@IgorS。メッセージキューで使用される通常の同時実行モデルは、SEDA(ステージイベント駆動型アーキテクチャ)と呼ばれます。Queues、Topics、およびExchangesは、それ自体が同時実行モデルです(たまたま、分散モデルでもあります。アクターモデルと同じです)。また、誰かが「間違った質問」と言ったとき、私は本当に軽蔑します。不適切な質問のほかに、いつ質問が間違っているのでしょうか。そのような何かを言うためにその卑劣でエリート主義者。
アダム・ゲント

1
それらが交換可能であると言ったことはありません。私は彼らが一緒に素晴らしい働きをするとさえ言っています。しかし、彼はここで分散akkaについて話しているのであって、俳優ライブラリーについてではありません。それは私がそれを読む方法です。あなたのポイントが有効であり、投稿でつまずく他の人を混乱させる可能性があるので、私の投稿を自由に編集してください。
アダム・ゲント

1
Akka Java APIの1つ-特にJDK 8ラムダを使用すると、非常にクリーンになりました。彼らがJDK 10で値オブジェクトを導入する場合、またはそれらが導入されると、より良くなると思います
Rob Crawford

4

私はメッセージングシステムの専門家ではありませんが、アプリでそれらをAkkaと組み合わせて、両方の長所を利用できます。Akkaとメッセージングシステム、この場合はZeroMQを試すのに役立つ例を次に示します。

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


6
ZeroMQは、正確にはメッセージングシステムではありません。それはむしろ改善されたソケットの一種です。本格的なメッセージングシステムは、ZeroMQよりもはるかに複雑です。リンク先のプロジェクトは、Akkaを使用したZeroMQの薄いラッパーのようです。
Vladimir Matveev

1

Akka-Camelは、ZeroMQよりも良い例です。ZeroMQはtcpからtcpへの直接通信です(したがって、ゼロ-メッセージキューはありません)。

AkkaCamelを使用すると、キューを抽象化し、メッセージキューメッセージのプッシュ/プルを処理するコードなしで、アクターから直接メッセージを生成/消費できます。

akka-zeromqを無視して、リモート処理でAkkaを直接使用できます。akka-zeromqはコアライブラリから削除されていると思いますが、scala-zeromq(https://github.com/mDialog/scala-zeromq)と呼ばれるakka用の優れたzeromqライブラリを構築しました

Akkaには2つの主要なコアユースケースがあります。

1)可変状態

共有された状態をアクタで非表示にすることで、より簡単に処理できます。アクターはメッセージを同期的に処理するため、アクターに状態を保持し、アクターAPIを介してそのフィールドを高い整合性で公開できます。

2)配布

並行性はakkaでは無料です。つまり、配布の問題を解決することだとあなたは言っています。マシンとコア全体に分散します。Akkaには、ネットワーク経由でメッセージを送信するための「ロケーション透過性」が組み込まれています。また、単一のサービスをスケールアップするためのクラスタリングとパターンも関連付けられています。これにより、ディストリビューション(マイクロサービスアーキテクチャなど)に最適なソリューションになります。

これは、ActiveMQでAkkaをAkka-Camelとともに使用する例です(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);

    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.