Kapan menggunakan aktor alih-alih solusi pengiriman pesan seperti WebSphere MQ atau Tibco Rendezvous?


106

Saya sudah membaca pertanyaan dan jawaban untuk Keputusan desain apa yang lebih mengutamakan Scala's Actors daripada JMS? .

Biasanya, kami menggunakan solusi perpesanan yang sudah ada selama bertahun-tahun: implementasi JMS seperti WebSphere MQ atau Apache ActiveMQ digunakan untuk komunikasi Point-To-Point, atau Tibco Rendevous untuk perpesanan Multicast.

Mereka sangat stabil, terbukti dan menawarkan ketersediaan dan kinerja yang tinggi. Namun demikian, konfigurasi dan penyiapannya tampak jauh lebih rumit daripada di Akka.

Kapan dan mengapa saya harus menggunakan Akka untuk beberapa kasus penggunaan di mana produk yang disebutkan di atas - WebSphere MQ atau ActiveMQ - telah berhasil digunakan sejauh ini? Mengapa saya harus mempertimbangkan untuk menggunakan Akka, bukan WebSphere MQ atau Tibco RV di proyek saya yang akan datang?

Dan kapan saya harus menghindari Akka? Apakah ini menawarkan ketersediaan dan kinerja tinggi yang sama dengan solusi lainnya? Atau apakah itu ide yang buruk untuk membandingkan Akka dengan middlewares perpesanan lainnya?

Mungkin juga ada solusi perpesanan lain di lingkungan JVM yang harus saya pertimbangkan selain JMS (Point-to-Point), TibcoRV (Multicast) dan Akka?


Jawaban:


92

Pertama, sistem pesan "lama" (MQ) lebih tua dalam implementasi tetapi mereka lebih baru dalam ide teknik: antrian persisten transaksional . Scala Actors dan Akka mungkin merupakan implementasi yang lebih baru tetapi dibangun di atas model Aktor konkurensi yang lebih lama.

Namun kedua model tersebut akhirnya menjadi sangat mirip dalam praktiknya karena keduanya berbasis pesan acara: Lihat jawaban saya untuk RabbitMQ vs Akka .

Jika Anda akan membuat kode hanya untuk JVM maka Akka mungkin adalah pilihan yang baik. Jika tidak, saya akan menggunakan RabbitMQ.

Juga jika Anda seorang pengembang Scala, maka Akka seharusnya tidak punya otak. Namun binding Java Akka tidak terlalu mirip dengan Java dan memerlukan casting karena sistem tipe Scala.

Juga di Java orang biasanya tidak membuat objek yang tidak berubah yang saya sarankan Anda lakukan untuk pengiriman pesan. Akibatnya sangat mudah di Java untuk secara tidak sengaja melakukan sesuatu menggunakan Akka yang tidak akan diskalakan (menggunakan objek yang bisa berubah untuk pesan, mengandalkan status panggilan balik penutupan yang aneh). Dengan MQ hal ini tidak menjadi masalah karena pesan selalu berseri dengan mengorbankan kecepatan. Dengan Akka mereka umumnya tidak.

Akka juga berskala lebih baik dengan jumlah konsumen yang besar daripada kebanyakan MQ. Ini karena untuk sebagian besar klien MQ (JMS, AMQP) setiap koneksi antrian memerlukan utas ... sehingga banyak antrian == banyak utas yang berjalan secara permanen. Ini terutama masalah klien. Saya pikir ActiveMQ Apollo memiliki dispatcher non-pemblokiran yang konon memperbaiki masalah itu untuk AMQP. Klien RabbitMQ memiliki saluran yang memungkinkan Anda menggabungkan banyak konsumen tetapi masih ada masalah dengan sejumlah besar konsumen yang berpotensi menyebabkan kebuntuan atau koneksi mati sehingga umumnya lebih banyak utas ditambahkan untuk menghindari masalah ini.

Yang sedang berkata remoting Akka agak baru dan mungkin masih tidak menawarkan semua jaminan pesan yang dapat diandalkan dan QoS yang disediakan antrian pesan tradisional (tapi itu berubah setiap hari). Ini juga umumnya peer-to-peer tetapi menurut saya mendukung server-to-peer yang umumnya dilakukan oleh kebanyakan sistem MQ (yaitu titik kegagalan tunggal) tetapi ada sistem MQ yang peer-to-peer (RabbitMQ adalah server- to-peer).

Akhirnya RabbitMQ dan Akka benar-benar pasangan yang bagus. Anda dapat menggunakan Akka sebagai pembungkus RabbitMQ terutama karena RabbitMQ tidak membantu Anda menangani konsumsi pesan dan merutekan pesan secara lokal (dalam satu JVM).

Kapan memilih Akka

  • Punya banyak konsumen (pikirkan jutaan).
  • Butuh latensi rendah
  • Terbuka untuk model konkurensi Aktor

Sistem contoh: Sistem obrolan waktu nyata interaktif

Kapan memilih MQ

  • Perlu berintegrasi dengan banyak sistem yang berbeda (yaitu non JVM)
  • Keandalan pesan lebih penting daripada latensi
  • Ingin lebih banyak alat dan UI admin
  • Karena poin sebelumnya lebih baik untuk tugas yang berjalan lama
  • Ingin menggunakan model konkurensi yang berbeda dari Aktor

Contoh sistem: Sistem pemrosesan batch transaksional terjadwal

EDIT berdasarkan komentar yang bersangkutan

Saya membuat asumsi bahwa OP terkait dengan pemrosesan terdistribusi yang dapat ditangani oleh Akka dan Antrean Pesan. Artinya saya berasumsi dia berbicara tentang didistribusikan Akka . Menggunakan Akka untuk konkurensi lokal adalah perbandingan apel dengan oranye untuk sebagian besar antrean pesan . Saya katakan paling karena Anda dapat menerapkan model antrian pesan secara lokal sebagai model konkurensi (yaitu topik, antrian, pertukaran) yang dilakukan oleh perpustakaan Reaktor dan simple-react .

Memilih model / library konkurensi yang tepat sangat penting untuk aplikasi berlatensi rendah. Solusi pemrosesan terdistribusi seperti antrian pesan umumnya tidak ideal karena perutean hampir selalu dilakukan melalui kabel yang jelas lebih lambat daripada dalam aplikasi dan dengan demikian Akka akan menjadi pilihan yang lebih baik. Namun saya yakin beberapa teknologi MQ berpemilik memungkinkan perutean lokal. Juga seperti yang saya sebutkan sebelumnya, sebagian besar klien MQ cukup bodoh tentang threading dan tidak bergantung pada IO non-pemblokiran dan memiliki utas per koneksi / antrian / saluran ... ironisnya io non-pemblokiran tidak selalu latensi rendah tetapi umumnya lebih banyak sumber daya efisien.

Seperti yang Anda lihat topik pemrograman terdistribusi dan pemrograman bersamaan agak besar dan berubah setiap hari sehingga niat awal saya tidak membingungkan tetapi lebih fokus pada satu area tertentu dari pemrosesan pesan terdistribusi yang saya pikirkan tentang OP. Dalam hal konkurensi, seseorang mungkin ingin memfokuskan pencarian mereka pada pemrograman "reaktif" (RFP / stream) yang merupakan model "lebih baru" tetapi serupa dengan model aktor dan model antrian pesan yang semua model ini dapat digabungkan secara umum karena keduanya berbasis acara.


3
Saya pikir jawaban untuk pertanyaan yang salah tidak mungkin benar. Anda tidak dapat membandingkan antrian pesan dan model konkurensi. Mereka dibangun untuk menyelesaikan tugas yang berbeda SEPENUHNYA dan memiliki kesamaan hanya kata "pesan".
Igor S.

2
Ya dan tidak. Akka mendukung perpesanan terdistribusi dan Anda dapat dengan mudah membangun model konkurensi dari paradigma antrian pesan (Reaktor Musim Semi Google). Sungguh satu-satunya perbedaan sekarang adalah bahwa RabbitMQ memiliki pesan yang tahan lama .. oh tunggu Akka mendukungnya sekarang juga. Dia mungkin mengatakan "Aktor" dalam judulnya tetapi secara eksplisit menunjukkan Akka yang memang memiliki banyak tumpang tindih dengan banyak sistem berbasis pesan (baik secara bersamaan maupun terdistribusi).
Adam Gent

4
BTW @IgorS. model konkurensi yang biasanya digunakan dengan antrian pesan disebut SEDA (arsitektur berbasis peristiwa yang dipentaskan). Selain menggunakan Queues, Topics, dan Exchanges adalah model konkurensi itu sendiri (yang kebetulan juga model terdistribusi .. sama seperti model aktor). Saya juga sangat membenci ketika seseorang mengatakan "pertanyaan yang salah" .. selain pertanyaan yang tidak pantas, kapan sebuah pertanyaan bisa salah? Ini snarky dan elitis untuk mengatakan sesuatu seperti itu.
Adam Gent

1
Saya tidak pernah mengatakan bahwa mereka dapat dipertukarkan. Saya bahkan mengatakan mereka bekerja sama dengan baik dan mengapa. Tapi dia jelas berbicara tentang akka yang didistribusikan di sini dan bukan akka perpustakaan aktor. Begitulah cara saya membacanya. Jangan ragu untuk mengedit postingan saya karena poin Anda valid dan dapat membingungkan orang lain yang menemukan postingan tersebut.
Adam Gent

1
Salah satunya adalah Akka Java API - sekarang sangat bersih, terutama dengan JDK 8 lambda. Saya menduga akan lebih baik jika / ketika mereka memperkenalkan objek nilai dengan JDK 10.
Rob Crawford

4

Saya bukan ahli dalam sistem perpesanan, tetapi Anda dapat menggabungkannya dengan Akka di aplikasi Anda, mendapatkan yang terbaik dari kedua dunia. Berikut adalah contoh yang mungkin berguna bagi Anda untuk bereksperimen dengan Akka dan sistem perpesanan, dalam hal ini ZeroMQ:

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


6
ZeroMQ sebenarnya bukan sistem pesan. Ini adalah semacam soket yang ditingkatkan. Sistem perpesanan yang lengkap jauh lebih kompleks daripada ZeroMQ. Proyek di tautan Anda tampaknya hanya pembungkus tipis di sekitar ZeroMQ dengan Akka.
Vladimir Matveev

1

Akka-Camel akan menjadi contoh yang lebih baik daripada ZeroMQ - ZeroMQ adalah komunikasi tcp langsung ke tcp (karenanya nol - tidak ada antrian pesan).

Dengan AkkaCamel Anda dapat mengabstraksi antrian dan menghasilkan / mengkonsumsi pesan langsung dari aktor tanpa kode apa pun untuk menangani pesan antrian pesan yang mendorong / menarik.

Anda dapat melepaskan akka-zeromq dan menggunakan Akka secara langsung dengan remote. Saya pikir akka-zeromq sedang dihapus dari pustaka inti tetapi kami membangun pustaka zeromq yang bagus untuk akka yang disebut scala-zeromq ( https://github.com/mDialog/scala-zeromq )

Akka memiliki beberapa kasus penggunaan inti utama:

1) Keadaan berubah

Lebih mudah menangani status bersama dengan menyembunyikannya di aktor. Saat aktor menangani pesan secara sinkron, Anda dapat menahan status di aktor dan mengekspos bidang itu dengan konsistensi tinggi melalui API aktor

2) Distribusi

Concurrency gratis di akka jadi Anda mengatakan ini benar-benar tentang menyelesaikan masalah distribusi. Distribusi di seluruh mesin dan inti. Akka telah membangun "transparansi lokasi" untuk mengirim pesan melalui kabel. Ini memiliki pengelompokan dan pola yang terkait untuk meningkatkan satu layanan juga. Ini menjadikannya solusi yang sangat baik untuk distribusi (misalnya arsitektur layanan mikro)

Berikut adalah contoh penggunaan Akka dengan ActiveMQ dengan Akka-Camel (menggunakan 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);

    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.