I'm looking for a framework/platform to (easily) support cross microservices communication. I was guided to look into Akka with Kafka. Unfortunately I was unable to find specifically this set-up and use case, but also didn't find any specific messages that can say it will not work.
Based on articles/messages here and on other sites I've compiled set of expectation from Akka + Kafka with a few open points.
Could you please review/correct the points below?
Platform for Microservices “cluster” implementation.
Microservices “cluster” is system implemented with set of
Microservices [application]
a. Microservices interact with each other by means of AKKA messaging API. (e.g. tell, ask)
b. There can be multiple instances of Microservice
i. Q: Is mailbox shared between instances (of one microservice=Actor)?
AKKA can be connected to Kafka and use it as transport (Message
Broker), i.e. Kafka API is encapsulated into AKKA API
a. Q: What are the values from Kafka? E.g. performance, throughput, reliability. Why Akka remoting is not enough?
Messaging
a. First, some initialization is needed:
i. e.g. create Actors System, supervisor
ii. There should be some shared pre-configuration between all Microservices (Actors in the cluster). E.g. IP/URI, message types/cases, etc.
b. Worker-Actors can be added/instantiated in run time:
i. Find supervisor by name/URI
ii. Add Work-Actor as child
c. There is ability to broadcast message to all children (e.g. specified by name and wildcards) and wait for responses from all children. Hower it seems it is not "native" for Akka API and code doesn't look as clear enough (samples at stackoverlow: 1, 2)
d. There is no ability to subscribe to certain type of events i.e. define filtering conditions during subscription, in case of filtering is needed – it can be done only inside each actor in onReceive method. So, in case of broadcasting each Actor will receive message and than need to decide whether it is applicable for him or not.
e. Q: what are message tracing/debugging tools/capabilities available in Akka?
Actors execution can be “chained”: E.g. A->B->C, in this case after processing C and B control will be passed back (in case of “ask” method)
AKKA Cluster
a. Provides APIs for app lifecycle mgmt.: start all/start one/stop/scale etc.
Q: how I can support/implement graceful shutdown?
b. It has built-in monitoring capabilities (check app availability,
health etc.)
c. Q: What about Infrastructure Monitoring? Do I need to care about it?
d. Q: Is ConductR is a must or just nice to have?
Service Discovery (e.g. Eureka) is not needed, since we use reactive communications (async. Messages via Message Broker)
a. Q: What about affinity/stickiness? Do I need to care about it? What Akka can offer in this area?
b. Q: How balancing is done?
In addition, if AKKA can really work on underlying Kafka - is there good example? I found only samples with data streaming, but I need just event/message processing.
Related
I want to know how can we send a message to a particular actor in cluster without knowing the actual path..
For Example...
I have 5 nodes all have same actorsytem and formed a cluster.
Each node will have 2 actors in it all actors across cluster have unique name.
I have an actor system outside the cluster.which not part of this cluster.
I have to send message from this actor system to cluster actors.
How can i map respective message to respective actor in cluster each time.Without knowing the actual path of the actor.
Without cluster sharding how actors inside cluster will accessed by outside cluster.
There is a direct answer to your question (at the end), but I think you need to go back to the docs and rethink your design. One of the primary reasons for this is that while what you are asking is possible, it goes against all of the best practices and many of the features involved are deprecated or not recommended. The best practice is that clusters should be self-contained and clusters should expose via well defined APIs and not actor internals. To quote from the remoting docs:
When building an Akka application, you would usually not use the Remoting concepts directly, but instead use the more high-level Akka Cluster utilities or technology-agnostic protocols such as HTTP, gRPC etc.
Essentially the docs are tell you that what you are trying to do is a bad idea. If two actors need to be able to discover each other, they should be in the same cluster. If for some reason you can't have them in the same cluster, for maintainability reasons you should expose the actor in the cluster via REST/gRPC or some other well defined API rather than trying to allow direct access to the actors.
Similarly, in the section about cluster client the docs say:
Cluster Client is deprecated in favor of using Akka gRPC. It is not advised to build new applications with Cluster Client, and existing users should migrate.
But, here's an attempt to answer the question directly. To quote the first sentence of the Actor discovery docs, "There are two general ways to obtain Actor references: by creating actors and by discovery using the Receptionist."
Unrelated side note: (That is a little misleading though, because there are some other ways in untyped Actors, and you also can obviously just be given a ActorRef. It's not the the docs are wrong, I'm just taking them a little out of context.).
Anyway, that leads to the direct answer to your question: ClientClusterReceptionist. You can find details on how to use it in the Classic Cluster Client docs. It's going to require some untyped actors, but since you are using deprecated approaches that probably isn't an issue.
But, moreso, you really should rethink this because based on your last question, it seems like you really aren't understanding how either clustering or sharding work.
As #david-ogren said, what you need is cluster client. You can read the documentation here. With cluster client, you still need to know at least one of the cluster node address and either:
The name of the actor you're trying to communicate with, if you're trying to communicate with the actor instance directly, or
A predefined topic to publish to. If you went for this route, you will need to make sure that all of the participating actors inside the cluster subscribes to the topic to receive them.
You can see a working example in this GitHub repository.
I have been learning Akka for few days and I have a simple questions to understand it well. How should be the application architecture created for REST service which using actors? Actors should be:
A simple component (for example Service layer, DAO, controllers, etc)?
An Actor should be a buisness logic element. For example I have a business logic which should be spearate into tasks which are actors?
An Actor = microservice. It is a high level layer. Every microservice in application should work as an separate actor?
I cannot understand it in this way - how should I use actors in correct way? If I create a REST service with layers (controllers, services, DAO and database), how should I separate it as actors in Akka application?
There was a blog (likely this) that reflects my take on Akka Actors pretty well. I don't really use them.
Depends on who you talk with, some people are really into it whereas others may see it as an underlying essential which maybe isn't that useful on an application level.
I use actors for handling state. That's all. Otherwise it's Futures or Akka Streams. I hope you like the blog. If you still have questions after it, please shoot. I have 5+ years of Akka behind me. Happy to help.
I wouldn't recommend building a REST service using raw Akka actors. Actors are better used for encapsulating state and behavior. For example, the loosely-coupled lightweight actors can be used for simulating individual IoT devices (e.g. thermostats), each of which maintains its own internal state (e.g. cool setting) and adjusts/reports its settings via non-blocking message passing.
For REST API/service, you might want to consider using Play which is built on top of Akka, supporting non-blocking I/O, JSON as first-class citizen, Websockets, etc. Here's a basic example of creating a REST service using Play.
On microservice, as noted in the above link:
Building a REST API in Play does not automatically make it a
"microservice" because it does not cover larger scale concerns about
microservices such as ensuring resiliency, consistency, or monitoring.
To incorporate microservice into your REST API, consider the Lagom framework which is built on top of Play/Akka along with the reactive qualities.
I'm struggling with proper design of communication between 2 separate akka microservices/bounded contexts in akka cluster.
Lets say we have 2 microservices in cluster per node.
Both microservices are based on akka.
It's clear for me that communication within particular bounded context will be handled by sending messages from actor to actor or from actor on node1 to actor on node2 (if necessary)
Q: but is it OK to use similar communication between separate akka application? e.g. boundedContext1.actor --message--> boundedContext2.actor
or it should be done via much clearer boundaries: In bc1 raise an event - publish to broker and read the event in bc2?
//Edit currently we've implemented a service registry an we're publishing events to service registry via Akka streams.
I think there is no universal answer here.
It is like if your BCs are simple enough you can hold the BCs in one application and even in one project/library with very weak boundaries i.e. just placing them into separate namespaces and providing an API for other BCs.
But if your BCs become more complex, more independent and require its own deployment cycle then it is definitely better to construct more strong boundaries and separate microservices that communicate through message broker.
So, my answer is you should just "feel" the right way according to your particular needs. If you don't "feel" it then follow KISS principle and start with an easier way i.e. using built-in akka communication system. And if in the future your BCs will become more complex then you will have to refactor them. But this decision will be justified and it will not be an unnecessary overhead.
I am looking to build a system that is able to process a stream of requests that needs a long processing time say 5 min each. My goal is to speed up request processing with minimal resource footprint which at times can be a burst of messages.
I can use something like a service bus to queue the request and have multiple process (a.k.a Actors in akka) that can subscribe for a message and start processing. Also can have a watchdog that looks at the queue length in the service bus and create more actors/ actor systems or stop a few.
if I want to do the same in the Actor system like Akka.net how can this be done. Say something like this:
I may want to spin up/stop new Remote Actor systems based on my request queue length
Send the message to any one of the available actor who can start processing without having to check who has the bandwidth to process on the sender side.
Messages should not be lost, and if the actor fails, it should be passed to next available actor.
can this be done with the Akka.net or this is not a valid use case for the actor system. Can some one please share some thoughts or point me to resources where I can get more details.
I may want to spin up/stop new Remote Actor systems based on my request queue length
This is not supported out of the box by Akka.Cluster. You would have to build something custom for it.
However Akka .NET has pool routers which are able to resize automatically according to configurable parameters. You may be able to build something around them.
Send the message to any one of the available actor who can start processing without having to check who has the bandwidth to process on the sender side.
If you look at Akka .NET Routers, there are various strategies that can be used to assign work. SmallestMailbox is probably the closest to what you're after.
Messages should not be lost, and if the actor fails, it should be passed to next available actor.
Akka .NET supports At Least Once Delivery. Read more about it in the docs or at the Petabridge blog.
While you may achieve some of your goals with Akka cluster, I wouldn't advise that. From your requirements it clearly states that your concerns are oriented about:
Reliable message delivery (where service buses and message queues are better option). There are a lot of solutions here, depending on your needs i.e. MassTransit, NServiceBus or queues (RabbitMQ).
Scaling workers (which is infrastructure problem and it's not solved by actor frameworks themselves). From what you've said, you don't even even need a cluster.
You could use akka for building a message processing logic, like workers. But as I said, you don't need it if your goal is to replace existing service bus.
The Akka doc talks about a variety of seemingly inter-related Akka technologies without distinguishing much between them:
Akka Networking
Akka Remoting
Akka Clustering
The Akka ZeroMQ module
My understanding is that "Akka Networking" is simply a module/lib that gives Akka the ability to speak to remote actor systems over TCP. Akka Remoting is another module/lib (not contained in the core Akka JAR) that gives Akka the use of Gossip protocols. And Akka Clustering is yet another module/lib that then uses these Gossip protocols to allow remote actor systems to cluster together and sharestate changes in a viral/"service discovery"-esque manner. And my understanding of Akka ZeroMQ is that it accomplishes the same thing as Akka Clustering, except using ZeroMQ as the basis of the network connections and protocols (instead of Gossip).
So first, if my understanding of these different modules/libs are incorrect, please begin by correcting me!
Assuming I'm more or less on target here, then my main concern is that I might have Remote Actor System 1 (RAS1) using Akka Clustering (and hence Gossip) trying to communicate with Remote Actor System 2 (RAS2) which uses Akka ZeroMQ. In this case, we're using two completely different clustering technologies and protocols, so does this mean these two remote systems can't speak to each other, or does special care need to be taken so that they are compatible with each other?
Akka Remoting is what allows for one actor to speak to another actor on a different machine. For Akka Remoting to work you need to know the specific IP address (or hostname), ActorSystem name, and Actor path of the actor you want to talk to. The ActorSystem name can be different in the 2 machines.
Akka Clustering takes away the problem of having to know the specific machine you are talking to (via Cluster-aware Routing or via a Receptionist that listens for machines joining or leaving the cluster). Cluster-aware Routing also allows for things like having a minimum of X instances of an actor running on any machine in the cluster. Akka Clustering uses the Gossip protocol to maintain the list of cluster members. A cluster-enabled application must know the address of at least one host which must always be running to be able to join the cluster. There might be 2, 3 or more, but the idea is that at least one of them must always be up. Akka Clustering is built on top of Akka Remoting.
Although I haven't worked with Akka ZeroMQ, I assume it works similarly to Akka AMQP. I see it more as an alternative to Remoting, in the sense that it enables actors on different machines to talk to each other, with the advantage that none of the actors need to know any specifics about any other machines where actors are running. However, as with Remoting, you need to manually create the actors that receive the messages, whereas with Clustering the cluster takes care of it (as long as you've configured your Routers correctly).
Regarding your last question. The easiest way I can think about for a Cluster to talk to Akka ZeroMQ would be to have one (or several?) actors in the Cluster that talk to ZeroMQ actors (i.e., you can actually mix and match). Have an actor inside the Cluster that listens on the queue, and have another one that publishes the message to the queue. Sort of an Adapter pattern.