WebSphere MQ veya Tibco Rendezvous gibi mesajlaşma çözümleri yerine aktörler ne zaman kullanılmalı?


106

Hangi tasarım kararları JMS yerine Scala'nın Aktörlerini tercih eder? Sorusunu ve cevaplarını zaten okudum. .

Genellikle, yıllardır var olan mesajlaşma çözümlerini kullanırız: Noktadan Noktaya iletişim için WebSphere MQ veya Apache ActiveMQ gibi bir JMS uygulaması veya Çok Noktaya Yayın mesajlaşma için Tibco Rendevous kullanılır.

Oldukça kararlı, kanıtlanmış ve yüksek kullanılabilirlik ve performans sunuyorlar. Yine de yapılandırma ve kurulum Akka'dakinden çok daha karmaşık görünüyor.

Akka'yı yukarıda belirtilen ürünlerin - WebSphere MQ veya ActiveMQ - şimdiye kadar başarıyla kullanıldığı bazı kullanım durumları için ne zaman ve neden kullanmalıyım? Gelecekteki projemde neden WebSphere MQ veya Tibco RV yerine Akka kullanmayı düşünmeliyim?

Akka'dan ne zaman kaçınmalıyım? Diğer çözümlerle aynı yüksek kullanılabilirliği ve performansı sunuyor mu? Yoksa Akka'yı diğer mesajlaşma ara yazılımlarıyla karşılaştırmak bile kötü bir fikir mi?

Belki JVM ortamında JMS (Point-to-Point), TibcoRV (Multicast) ve Akka dışında göz önünde bulundurmam gereken başka bir mesajlaşma çözümü daha var mı?


Yanıtlar:


92

Öncelikle, "eski" mesaj sistemleri (MQ) uygulamada daha eskidir, ancak bunlar mühendislik fikrinde daha yenidir : işlemsel kalıcı kuyruklar . Scala Actors ve Akka daha yeni bir uygulama olabilir, ancak daha eski bir Actors eşzamanlılık modeli üzerine inşa edilmiştir.

Bununla birlikte, iki model pratikte birbirine çok benziyor çünkü ikisi de olay mesajına dayalı: RabbitMQ vs Akka'ya cevabımı görün .

Yalnızca JVM için kodlama yapacaksanız, Akka muhtemelen iyi bir seçimdir. Aksi takdirde RabbitMQ kullanırım.

Ayrıca bir Scala geliştiricisi iseniz, Akka hiç akıllıca olmamalıdır. Ancak Akka'nın Java bağlamaları çok Java'ya özgü değildir ve Scala'nın tip sistemi nedeniyle döküm gerektirir.

Ayrıca Java'da insanlar genellikle mesajlaşma için yapmanızı tavsiye ettiğim değişmez nesneler yapmazlar. Sonuç olarak, Java'da Akka'yı kullanarak ölçeklenmeyecek bir şeyi yanlışlıkla yapmak çok kolaydır (mesajlar için değişken nesneler kullanarak, garip kapatma geri arama durumuna dayanarak). MQ ile bu bir sorun değildir çünkü mesajlar her zaman hız pahasına serileştirilir. Akka ile genellikle değiller.

Akka, aynı zamanda çoğu MQ'dan çok sayıda tüketiciyle daha iyi ölçeklendiriyor. Bunun nedeni, çoğu MQ (JMS, AMQP) istemcisi için her kuyruk bağlantısının bir iş parçacığı gerektirmesidir ... bu nedenle çok sayıda kuyruk == kalıcı olarak çalışan çok sayıda iş parçacığı. Bu esasen bir müşteri sorunudur. ActiveMQ Apollo'nun, AMQP için bu sorunu düzelttiği iddia edilen, engellemeyen bir dağıtıcıya sahip olduğunu düşünüyorum. RabbitMQ istemcisi, birden fazla tüketiciyi birleştirmenize izin veren kanallara sahiptir, ancak yine de çok sayıda tüketiciyle ilgili sorunlar potansiyel olarak kilitlenmelere veya bağlantıların ölmesine neden olabilir, bu nedenle genellikle bu sorunu önlemek için daha fazla iş parçacığı eklenir.

Akka'nın uzaktan kumandasının oldukça yeni olduğu ve muhtemelen hala geleneksel mesaj kuyruklarının sağladığı tüm güvenilir mesaj garantilerini ve QoS'yi sunmadığı söyleniyor (ancak bu her gün değişiyor). Aynı zamanda genel olarak eşler arasıdır, ancak genellikle çoğu MQ sisteminin yaptığı şey olan (yani tek hata noktası) sunucudan eşe desteği desteklediğini mi düşünüyorum, ancak eşler arası MQ sistemleri var (RabbitMQ, eşler arası).

Sonunda RabbitMQ ve Akka gerçekten iyi bir çift oldu. Akka'yı özellikle RabbitMQ için bir sarmalayıcı olarak kullanabilirsiniz çünkü RabbitMQ, mesajların tüketimini yönetmenize ve mesajları yerel olarak (tek bir JVM'de) yönlendirmenize yardımcı olmaz.

Akka ne zaman seçilmeli

  • Çok sayıda tüketiciye sahip olun (milyonları düşünün).
  • Düşük gecikmeye ihtiyaç var
  • Aktör eşzamanlılık modeline açık

Örnek sistem: Etkileşimli gerçek zamanlı sohbet sistemi

MQ ne zaman seçilir?

  • Çok sayıda farklı sistemle (yani JVM olmayan) entegre edilmesi gerekiyor
  • Mesaj güvenilirliği gecikmeden daha önemlidir
  • Daha fazla araç ve yönetici kullanıcı arayüzü ister misiniz
  • Önceki noktalar nedeniyle uzun süren görevler için daha iyidir
  • Actors'dan farklı bir eşzamanlılık modeli kullanmak istiyor

Örnek sistem: Planlanmış bir işlemsel toplu işleme sistemi

İlgili yorumlara göre DÜZENLE

OP'nin hem Akka hem de Mesaj Kuyruklarının üstesinden gelebileceği dağıtılmış işlemeyle ilgilendiğini varsaydım. Yani dağıtılmış Akka'dan bahsettiğini sanıyordum . Yerel eşzamanlılık için Akka'yı kullanmak, çoğu ileti kuyruğuna kıyasla elma ile turuncudur . Çoğunu söylüyorum çünkü mesaj kuyruğu modelini hem Reactor kütüphanesinin hem de simple-react'in yaptığı bir eşzamanlılık modeli (yani konu, kuyruklar, değiş tokuşlar) olarak yerel olarak uygulayabilirsiniz .

Düşük gecikmeli uygulamalar için doğru eşzamanlılık modelini / kitaplığını seçmek çok önemlidir. İleti kuyruğu gibi dağıtılmış bir işleme çözümü genellikle ideal değildir çünkü yönlendirme neredeyse her zaman tel üzerinden yapılır ve bu uygulama içinde olduğundan açıkça daha yavaştır ve bu nedenle Akka daha iyi bir seçim olur. Ancak bazı tescilli MQ teknolojilerinin yerel yönlendirmeye izin verdiğine inanıyorum. Ayrıca daha önce bahsettiğim gibi, çoğu MQ istemcisi iş parçacığı oluşturma konusunda oldukça aptaldır ve engellemeyen GÇ'ye güvenmez ve bağlantı / kuyruk / kanal başına bir iş parçacığı vardır ... ironik olarak engellemeyen io her zaman düşük gecikme değildir, ancak genellikle daha fazla kaynaktır verimli.

Gördüğünüz gibi, dağıtılmış programlama ve eşzamanlı programlama konusu oldukça büyük ve her gün değişiyor, bu yüzden asıl amacım kafa karıştırmak değildi, daha ziyade OP'nin ilgilendiği şey olan dağıtılmış mesaj işlemenin belirli bir alanına odaklanmaktı. Eşzamanlılık açısından, aramalarını "daha yeni" ancak aktör modeline ve mesaj kuyruk modeline benzer bir model olan "reaktif" programlamaya (RFP / akışlar) odaklamak isteyebilir. olay tabanlıdır.


3
Bence yanlış bir sorunun cevabı doğru olamaz. Bir ileti kuyruğu ile bir eşzamanlılık modelini karşılaştıramazsınız. TAMAMEN farklı görevleri çözmek için inşa edilmişlerdir ve ortak noktaları yalnızca "mesaj" sözcüğüne sahiptir.
Igor S.

2
Peki evet ve hayır. Akka, dağıtılmış mesajlaşmayı destekler ve mesaj kuyruğu paradigması (google Spring'in Reaktörü) üzerinden çok kolay bir şekilde eşzamanlılık modeli oluşturabilirsiniz. Gerçekten artık tek fark, RabbitMQ'nun kalıcı mesajlara sahip olmasıdır .. oh bekle Akka bunu şimdi de destekliyor. Başlıkta "Aktör" diyebilir, ancak birçok mesaj tabanlı sistemle (hem eşzamanlı hem de dağıtılmış) büyük bir örtüşen Akka'ya açıkça işaret ediyor.
Adam Gent

4
BTW @IgorS. ileti kuyruklarıyla kullanılan tipik eşzamanlılık modeline SEDA (aşamalı olay güdümlü mimari) denir. Queues, Topics ve Exchange kullanmanın yanı sıra başlı başına bir eşzamanlılık modelidir (bu aynı zamanda dağıtılmış bir modeldir .. tıpkı aktör modeli gibi). Birisi "yanlış soru" dediğinde de gerçekten küçümsüyorum .. uygunsuz sorular dışında, bir soru ne zaman yanlış olabilir? Böyle bir şey söylemek, alaycı ve seçkinci.
Adam Gent

1
Değiştirilebilir olduklarını asla söylemedim. Hatta birlikte harika çalıştıklarını ve neden olduğunu söylüyorum. Ama açıkça aktör kütüphanesini akka değil, burada dağıtılan akka'dan bahsediyor. Ben böyle okudum. Konunuz geçerli olduğundan ve gönderi hakkında yanıltıcı olan diğerlerinin kafasını karıştırabileceğinden gönderimi düzenlemekten çekinmeyin.
Adam Gent

1
Biri Akka Java API - şimdi çok temiz, özellikle JDK 8 lambdas ile. JDK 10 ile değerli nesneler sunarlarsa daha iyi olacağından şüpheleniyorum.
Rob Crawford

4

Mesajlaşma sistemleri konusunda uzman değilim, ancak bunları uygulamalarınızda Akka ile birleştirerek her iki dünyanın da en iyisini elde edebilirsiniz. İşte Akka ve mesajlaşma sistemlerini denemek için yararlı bulabileceğiniz bir örnek, bu durumda ZeroMQ:

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


6
ZeroMQ tam olarak bir mesajlaşma sistemi değildir. Daha çok bir çeşit geliştirilmiş soket. Tam teşekküllü mesajlaşma sistemleri ZeroMQ'dan çok daha karmaşıktır. Bağlantınızdaki proje, Akka ile ZeroMQ'nun etrafındaki ince bir paket gibi görünüyor.
Vladimir Matveev

1

Akka-Camel, ZeroMQ'dan daha iyi bir örnek olacaktır - ZeroMQ, tcp'ye doğrudan bir iletişimdir (dolayısıyla sıfır - mesaj kuyruğu yoktur).

AkkaCamel ile sırayı soyutlayabilir ve mesaj kuyruğu mesajının itilmesi / çekilmesi ile başa çıkmak için herhangi bir kod olmadan doğrudan bir aktörden mesajlar üretebilir / tüketebilirsiniz.

Akka-zeromq'tan vazgeçebilir ve Akka'yı uzaktan kumanda ile doğrudan kullanabilirsiniz. Bence akka-zeromq çekirdek kitaplıktan kaldırılıyor, ancak akka için scala-zeromq adında iyi bir zeromq kitaplığı oluşturduk ( https://github.com/mDialog/scala-zeromq )

Akka'nın birkaç temel temel kullanım durumu vardır:

1) Değişken durum

Paylaşılan durumu bir aktörde saklayarak idare etmek daha kolaydır. Aktörler iletileri eşzamanlı olarak ele aldıkça, durumu bir aktörde tutabilir ve bu alanı aktör API'si aracılığıyla yüksek tutarlılıkla ortaya çıkarabilirsiniz.

2) Dağıtım

Eşzamanlılık akka'da ücretsizdir, bu yüzden gerçekten dağıtım problemlerini çözmekle ilgili olduğunu söylüyorsunuz. Makineler ve çekirdekler arasında dağıtım. Akka, kablo üzerinden mesaj göndermek için "konum şeffaflığı" oluşturmuştur. Tek bir hizmeti de ölçeklendirmek için ilişkilendirilmiş kümeleme ve kalıplara sahiptir. Bu, dağıtım için çok iyi bir çözüm olmasını sağlar (örn. Mikro hizmet mimarisi)

İşte Akka'yı ActiveMQ ile Akka-Camel ile kullanmanın bir örneği (Java8 kullanarak)

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);

    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.