Khi nào sử dụng các diễn viên thay vì các giải pháp nhắn tin như WebSphere MQ hoặc Tibco Rendezvous?


106

Tôi đã đọc câu hỏi và câu trả lời cho Những quyết định thiết kế nào sẽ ủng hộ Scala's Actors thay vì JMS? .

Thông thường, chúng tôi sử dụng các giải pháp nhắn tin đã tồn tại trong nhiều năm: hoặc triển khai JMS như WebSphere MQ hoặc Apache ActiveMQ được sử dụng cho giao tiếp Point-To-Point hoặc Tibco Rendevous cho nhắn tin Multicast.

Chúng rất ổn định, đã được chứng minh và cung cấp tính khả dụng và hiệu suất cao. Tuy nhiên, cấu hình và thiết lập có vẻ phức tạp hơn nhiều so với Akka.

Khi nào và tại sao tôi nên sử dụng Akka cho một số trường hợp sử dụng trong đó các sản phẩm nói trên - WebSphere MQ hoặc ActiveMQ - đã được sử dụng thành công cho đến nay? Tại sao tôi nên cân nhắc sử dụng Akka thay vì WebSphere MQ hoặc Tibco RV trong dự án tương lai của mình?

Và khi nào tôi nên tránh Akka? Nó có cung cấp tính khả dụng và hiệu suất cao như các giải pháp khác không? Hay thậm chí là một ý tưởng tồi nếu so sánh Akka với các phần mềm trung gian nhắn tin khác?

Có lẽ cũng có một giải pháp nhắn tin khác trong môi trường JVM mà tôi nên xem xét ngoài JMS (Point-to-Point), TibcoRV (Multicast) và Akka?


Câu trả lời:


92

Trước hết, hệ thống thông báo "cũ" (MQ) đã cũ hơn trong việc triển khai nhưng chúng là một ý tưởng kỹ thuật mới hơn về: hàng đợi liên tục giao dịch . Scala Actors và Akka có thể là một triển khai mới hơn nhưng được xây dựng trên một mô hình đồng thời cũ hơn của Actors.

Tuy nhiên, hai mô hình cuối cùng rất giống nhau trong thực tế vì cả hai đều dựa trên thông điệp sự kiện: Hãy xem câu trả lời của tôi cho RabbitMQ vs Akka .

Nếu bạn chỉ viết mã cho JVM thì Akka có lẽ là một lựa chọn tốt. Nếu không, tôi sẽ sử dụng RabbitMQ.

Ngoài ra, nếu bạn là một nhà phát triển Scala, thì Akka hẳn là một người không có trí tuệ. Tuy nhiên, các liên kết Java của Akka không phải là Java-ish và yêu cầu ép kiểu do hệ thống kiểu của Scala.

Ngoài ra, trong Java, mọi người thường không tạo các đối tượng bất biến mà tôi khuyên bạn nên làm để nhắn tin. Do đó, trong Java rất dễ vô tình làm điều gì đó bằng cách sử dụng Akka sẽ không mở rộng quy mô (sử dụng các đối tượng có thể thay đổi cho các thông báo, dựa vào trạng thái gọi lại đóng cửa kỳ lạ). Với MQ, đây không phải là vấn đề vì các tin nhắn luôn được nối tiếp với chi phí tốc độ. Với Akka, họ thường không như vậy.

Akka cũng mở rộng quy mô tốt hơn với lượng người tiêu dùng lớn hơn hầu hết MQ. Điều này là do đối với hầu hết các máy khách MQ (JMS, AMQP) mọi kết nối hàng đợi đều yêu cầu một luồng ... do đó rất nhiều hàng đợi == rất nhiều luồng chạy vĩnh viễn. Đây chủ yếu là một vấn đề của khách hàng. Tôi nghĩ ActiveMQ Apollo có một bộ điều phối không chặn có mục đích khắc phục sự cố đó cho AMQP. Ứng dụng khách RabbitMQ có các kênh cho phép bạn kết hợp nhiều người tiêu dùng nhưng vẫn có vấn đề với số lượng lớn người tiêu dùng có khả năng gây ra bế tắc hoặc kết nối chết vì vậy thường nhiều chủ đề hơn được thêm vào để tránh vấn đề này.

Điều đó được cho là sự hối hận của Akka là khá mới và có lẽ vẫn chưa cung cấp tất cả các đảm bảo tin nhắn và QoS đáng tin cậy mà hàng đợi tin nhắn truyền thống cung cấp (nhưng điều đó đang thay đổi hàng ngày). Nó cũng thường là ngang hàng nhưng tôi có nghĩ rằng hỗ trợ máy chủ-để-ngang hàng thường là những gì hầu hết các hệ thống MQ làm (tức là một điểm lỗi) nhưng có các hệ thống MQ là ngang hàng (RabbitMQ là máy chủ- ngang hàng).

Cuối cùng thì RabbitMQ và Akka thực sự là một cặp ăn ý. Bạn có thể sử dụng Akka làm trình bao bọc đặc biệt cho RabbitMQ vì RabbitMQ không giúp bạn xử lý việc tiêu thụ tin nhắn và định tuyến tin nhắn cục bộ (trong một JVM duy nhất).

Khi nào chọn Akka

  • Có nhiều người tiêu dùng (nghĩ đến hàng triệu).
  • Cần độ trễ thấp
  • Mở cho mô hình đồng thời Actor

Hệ thống ví dụ: Hệ thống trò chuyện thời gian thực tương tác

Khi nào chọn MQ

  • Cần tích hợp với nhiều hệ thống khác nhau (tức là không phải JVM)
  • Độ tin cậy của tin nhắn quan trọng hơn độ trễ
  • Muốn có thêm công cụ và giao diện người dùng quản trị
  • Vì những điểm trước đó tốt hơn cho các tác vụ chạy lâu
  • Muốn sử dụng một mô hình đồng thời khác với Actors

Hệ thống ví dụ: Hệ thống xử lý hàng loạt giao dịch theo lịch trình

CHỈNH SỬA dựa trên các nhận xét có liên quan

Tôi đã giả định rằng OP quan tâm đến việc xử lý phân tán mà cả Akka và Hàng đợi Thư đều có thể xử lý. Đó là tôi cho rằng anh ta đang nói về Akka phân tán . Sử dụng Akka cho đồng thời cục bộ là một so sánh táo với cam đối với hầu hết các hàng đợi tin nhắn . Tôi nói hầu hết vì bạn có thể áp dụng cục bộ mô hình hàng đợi tin nhắn như một mô hình đồng thời (tức là chủ đề, hàng đợi, trao đổi) mà cả thư viện Reactorsimple-react đều làm.

Chọn đúng mô hình / thư viện đồng thời là rất quan trọng đối với các ứng dụng có độ trễ thấp. Một giải pháp xử lý phân tán như hàng đợi tin nhắn thường không lý tưởng vì việc định tuyến hầu như luôn được thực hiện qua dây, rõ ràng là chậm hơn so với trong ứng dụng và do đó Akka sẽ là một lựa chọn tốt hơn. Tuy nhiên, tôi tin rằng một số công nghệ MQ độc quyền cho phép định tuyến cục bộ. Cũng như tôi đã đề cập trước đó, hầu hết các máy khách MQ khá ngu ngốc về phân luồng và không dựa vào IO không chặn và có một luồng cho mỗi kết nối / hàng đợi / kênh ... trớ trêu thay, io không chặn không phải lúc nào cũng có độ trễ thấp mà nói chung là nhiều tài nguyên hơn Có hiệu quả.

Như bạn có thể thấy chủ đề của lập trình phân tán và lập trình đồng thời là khá lớn và thay đổi hàng ngày nên ý định ban đầu của tôi không gây nhầm lẫn mà là tập trung vào một lĩnh vực cụ thể của xử lý thông điệp phân tán, đó là điều tôi mặc dù OP đã quan tâm. Về mặt đồng thời, người ta có thể muốn tập trung tìm kiếm của họ vào lập trình "phản ứng" (RFP / luồng) là một mô hình "mới hơn" nhưng tương tự với mô hình tác nhân và mô hình hàng đợi tin nhắn mà tất cả các mô hình này nói chung có thể được kết hợp vì chúng dựa trên sự kiện.


3
Tôi nghĩ rằng một câu trả lời cho một câu hỏi sai không thể đúng. Bạn không thể so sánh hàng đợi tin nhắn và mô hình đồng thời. Chúng được xây dựng để giải quyết HOÀN TOÀN các nhiệm vụ khác nhau và chỉ có điểm chung là từ "message".
Igor S.

2
Vâng có và không. Akka hỗ trợ nhắn tin phân tán và bạn có thể rất dễ dàng xây dựng mô hình đồng thời ngoài mô hình hàng đợi tin nhắn (Lò phản ứng của google Spring). Thực sự sự khác biệt duy nhất bây giờ là RabbitMQ có tin nhắn lâu dài .. oh chờ Akka cũng hỗ trợ điều đó. Anh ta có thể nói "Actor" trong tiêu đề nhưng chỉ ra rõ ràng Akka có sự chồng chéo lớn với nhiều hệ thống dựa trên thông điệp (cả đồng thời và phân tán).
Adam Gent

4
BTW @IgorS. mô hình đồng thời thường được sử dụng với hàng đợi thông báo được gọi là SEDA (kiến trúc hướng sự kiện theo giai đoạn). Bên cạnh việc sử dụng Hàng đợi, Chủ đề và Trao đổi là một mô hình đồng thời tự nó (điều đó chỉ xảy ra với mô hình phân tán cũng .. giống như mô hình diễn viên). Tôi cũng thực sự khinh thường khi ai đó nói "câu hỏi sai" .. ngoài những câu hỏi không phù hợp, một câu hỏi có thể sai khi nào? Nó khó nói và elitist để nói điều gì đó như thế.
Adam Gent

1
Tôi chưa bao giờ nói chúng có thể hoán đổi cho nhau. Tôi thậm chí nói rằng họ làm việc tuyệt vời cùng nhau và tại sao. Nhưng rõ ràng anh ấy đang nói về akka được phân phát ở đây chứ không phải akka ở thư viện diễn viên. Đó là cách tôi đọc nó. Vui lòng chỉnh sửa bài đăng của tôi vì quan điểm của bạn là hợp lệ và có thể gây nhầm lẫn cho những người khác vấp phải bài đăng.
Adam Gent

1
Một là API Akka Java - hiện tại nó rất sạch, đặc biệt là với lambdas JDK 8. Tôi nghi ngờ nó sẽ trở nên tốt hơn nếu / khi họ giới thiệu đối tượng giá trị với JDK 10
Rob Crawford

4

Tôi không phải là chuyên gia về hệ thống nhắn tin, nhưng bạn có thể kết hợp chúng với Akka trong ứng dụng của mình, tận dụng tối đa cả hai thế giới. Đây là một ví dụ mà bạn có thể thấy hữu ích khi thử nghiệm với Akka và các hệ thống nhắn tin, trong trường hợp này là ZeroMQ:

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


6
ZeroMQ không hẳn là một hệ thống nhắn tin. Nó đúng hơn là một số loại ổ cắm được cải tiến. Các hệ thống nhắn tin chính thức phức tạp hơn nhiều so với ZeroMQ. Dự án tại liên kết của bạn dường như chỉ là một lớp bọc mỏng xung quanh ZeroMQ với Akka.
Vladimir Matveev

1

Akka-Camel sẽ là một ví dụ tốt hơn ZeroMQ - ZeroMQ là một giao tiếp tcp trực tiếp với tcp (do đó không có - không có hàng đợi tin nhắn).

Với AkkaCamel, bạn có thể trừu tượng hóa hàng đợi và sản xuất / tiêu thụ thông điệp trực tiếp từ một tác nhân mà không cần bất kỳ mã nào để đối phó với việc đẩy / kéo thông điệp hàng đợi.

Bạn có thể bỏ qua akka-zeromq và sử dụng Akka trực tiếp với sự hối hận. Tôi nghĩ rằng akka-zeromq đang bị xóa khỏi thư viện lõi nhưng chúng tôi đã xây dựng một thư viện zeromq tốt cho akka có tên là scala-zeromq ( https://github.com/mDialog/scala-zeromq )

Akka có một số trường hợp sử dụng cốt lõi chính:

1) Trạng thái có thể thay đổi

Xử lý trạng thái được chia sẻ dễ dàng hơn bằng cách ẩn nó trong một diễn viên. Khi các tác nhân xử lý thông báo một cách đồng bộ, bạn có thể giữ trạng thái trong một tác nhân và hiển thị trường đó với tính nhất quán cao thông qua API tác nhân

2) Phân phối

Đồng thời là miễn phí trong akka, vì vậy bạn nói rằng nó thực sự là để giải quyết các vấn đề phân phối. Phân phối trên các máy và lõi. Akka đã xây dựng tính năng "minh bạch vị trí" để gửi tin nhắn qua dây. Nó cũng có tính năng phân cụm và người bảo trợ được liên kết để mở rộng quy mô một dịch vụ. Điều này làm cho nó trở thành một giải pháp rất tốt để phân phối (ví dụ: kiến ​​trúc dịch vụ vi mô)

Đây là một ví dụ về việc sử dụng Akka với ActiveMQ với Akka-Camel (sử dụng 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);

    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.