How can we send a message from an actor system outside the Akka Cluster - akka

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.

Related

How can I create ActorSelection from ActorContext[T]

In the time since my last Akka project, Akka has moved on to a more cluster oriented approach.
I like the patterns that akka.actor.typed provide. But I am not building a clustered system. I looked at clustering, but I think my system is too fragmented and more static than a system that would make a reasonable cluster.
I have the bones of a system but I can't form bonds because I can't crate ActorSelections to connect my nodes. I have poked around in akka.actor.typed and don't see a path to creating an ActorSelection.
Is there a way to create an ActorSelection from anything I have access to in akka.actor.typed?
Is there another way to obtain an address to a remote actor system at a known port?
Thanks!
I see you figured out how to fall back to the classic APIs however I'd recommend that you read up on the typed receptionist for discovering actors instead of falling back to string lookups like that as they are more brittle and gives quite a tight coupling.
The receptionist works both in a single ActorSystem and in a cluster without changes. With the receptionist an actor that wants to provide a service registers itself using a typed key. Actors wanting to interact with it can subscribe or lookup available actors through the key (or use a group router which will keep track of available actors for a key and route to them).
See docs https://doc.akka.io/docs/akka/current/typed/actor-discovery.html#receptionist and https://doc.akka.io/docs/akka/current/typed/routers.html#group-router
After more digging I found the answer in the the Akka doc.
https://doc.akka.io/docs/akka/current/typed/coexisting.html
import akka.actor.typed.scaladsl.adapter._
val context: ActorContext[t]
context.toClassic.actorSelection("akka://actorSystemName#10.0.0.1:25520/user/actorName")

Communication between bounded contexts in akka cluster

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.

Q: Akka as cross microservice messaging toolkit?

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.

Cross-service calls with Akka

I'm playing with newly released Akka.Net 1.0 (congratulations on the release!) so it's all quite new to me, but I'm pretty sure anyone with JVM Akka experience could also chime in since there's nothing that's runtime-dependent in the question.
Let's consider several (for the sake of example, 2) separate services that are a part of a larger system/application. Those services usually do their own things, but cross-service calls are sometimes needed. Let's say that Service 2 can be standalone and has a GetStuff action. Service 1 has a DoSomething action, which has to get the result of GetStuff action first.
What is preferred way of handling that kind of situation when both services can be deployed separately and to different machines?
As I said, I don't know much about Akka, but digging through examples, docs and source I found two options:
Remoting. Separate actor systems in their own services using Remoting to get ActorSelection from remote host. It would be pretty much the same as Remoting docs example, just that two actor systems would be equal 'clients'.
Clustering. I'm trying to wrap my head around that and the most I can figure out right now would be to set up a separate cluster service that would just set up the cluster system, creating a simple listener actor so that the seed node could be properly initialized (?). Then each and every separate actor system created in their own services would join to said cluster system under different role.
Maybe there's yet another solution that I'm not aware of...?
Personally, clustering solution seems harder to grasp and set up at first glance, but maybe there are some significant advantages that I can't see right now.
To reiterate, what is the preferred way of handling such situation and what should I look out for?
Akka.Cluster depends on Akka.Remote - here's what's fundamentally different about them:
Akka.Remote - allows you to connect and communicate with actor systems running in remote processes. Can be totally separate code-bases running entirely different Akka.NET applications ("services", if you will.) All you need to communicate between the two systems is a shared set of message classes that's visible in both processes.
Akka.Cluster - an abstraction on top of Akka.Remote that eliminates the need for each of your service instances to have to know the explicit address of every other possible service instance you might need to connect to. These can be instances of the same services or instances of different services. Enables dynamic discovery of services via a really simple "seed node" strategy.
I recommend you take a look at the Akka.Cluster microservices example that I wrote - it shows how you can use the Akka.Cluster "roles" feature to dynamically make cross-service calls to nodes in a different service without having to explicitly define any of their network addresses. In particular, take a look at how I use "cluster-aware" routers to do this.

When to use Actors vs Futures?

I am currently working on a Play! project that has the following architecture:
Controllers -> Services (actors) -> Models (Regular case classes)
For each request that comes in, we will issue a call to the service layers like so:
Service ? DoSomething(request, context)
We have a set number of these service actors behind an akka router that are created during app initialization, and is expandable on demand.
And in the service we mostly do modest data manipulation or database calls:
receive = {
case DoSomething(x, y) => {
...
Model.doSometing(...)
sender ! result
}
}
I am having second thoughts on whether we should be using actors for our services or just use Futures only.
We do not have any internal state that needs to be modified in the service actors, whatever message comes in goes to a function and spits out the result. Isn't this the big strength of the actor model?
We are doing a lot of tasks which seem to take a lot away from the actor model
We aren't doing heavy computation and remoting doesn't make sense because most of the work is for the database and roundtriping to a remote actor to make some db call is unnecessary
We do use reactivemongo, so every db call is non blocking. We can make a lot of these calls
It seems to me that removing akka and just use Futures makes our life a lot easier, and we don't really lose anything.
There certainly is no shortage of opinion on the topic of what should and shouldn't be an actor. Like these two posts:
http://noelwelsh.com/programming/2013/03/04/why-i-dont-like-akka-actors/
http://www.chrisstucchio.com/blog/2013/actors_vs_futures.html
I don't think you're going to find an absolute answer to this question other then that it's situational and it's really up to your preferences and your problem. What I can do for you is to offer my opinion that is based on us implementing Akka for about 2 years now.
For me, I like to think of Akka really as a platform. We come for the Actor Model but we stay for all of the other goodness that the platform provides like Clustering/Remoting, FSM, Routing, Circuit Breaker, Throttling and the like. We are trying to build an SOA like architecture with our actors acting as services. We are deploying these services across a cluster, so we are taking advantage of things like Location Transparency and Routing to provide the ability for a service consumer (which itself could be another service) to find and use a service no matter where it is deployed, and in a highly available manner. Akka makes this whole process pretty simple based on the platform tools they offer.
Within our system, we have the concept of what I call Foundation Services. These are really simple services (like basic lookup/management services for a particular entity). These services generally don't call any other services, and in some cases, just perform DB lookups. These services are pooled (router) and don't usually have any state. They are pretty similar to what you are describing some of your services to be like. We then start to build more and more complex services on top of these foundation services. Most of these services are short lived (to avoid asking), sometimes FSM based, that collect data from the foundation services and then crunch and do something as a result. Even though these foundation services are themselves pretty simple, and some would say don't require an actor, I like the flexibility in that when I compose them into a higher level service, I can look them up and they can be anywhere (location transparent) in my cluster with any number of instances available (routing) for using.
So for us, it was really a design decision to baseline around an actor as a sort of micro-like service that is available within our cluster for consumption by any other service, no matter how simple that service is. I like communicating with these services, where ever they are, through a coarse grained interface in an async manner. A lot of those principles are aspects of building out a good SOA. If that's your goal, then I think Akka can be very helpful in achieving that goal. If you are not looking to do something like that, then maybe your are right in questioning your decision to use Akka for your services. Like I said earlier, it's really up to you to figure out what you are trying to do from an architecture perspective and then design your services layer to meet those goals.
I think you're on right tracks.
We do not have any internal state that needs to be modified in the service actors, whatever message comes in goes to a function and spits out the result. Isn't this the big strength of the actor model?
I found Chris Stucchio's blog (referred to by #cmbaxter above) instantly delightful. My case was so simple that architectural considerations were not a valid point. Just Spray routing and lots of database access, like you have. No state. Thus Future. So much simpler code.
Actor should be crated when you need some really long living stuff with modifying state. In other cases there are no any benefits from actors, especially from non-typed ones.
- do pattern matching every time
- control actor's lifecycle
- remember the things which should not be passed between threads
Why do all of this when you may have simple Future?
There are tasks where actors fit very well, but not everywhere
I was wondering the same and what we decide to do was to use Akka for our data access and it works very well, it's very testable (and tested), and very portable.
We created repositories, long living actors, that we bootstrapped in our App : (FYI, we are using slick for our DB Access, but also have a similar design for our MongoDB needs)
val subscriptionRepo = context.actorOf(Props(new SubscriptionRepository(appConfig.db)), "repository-subscription")
Now we are able to send a "Request" Message for data, ex:
case class SubscriptionsRequested(atDate: ZeroMillisDateTime)
that the actor will respond with
case class SubscriptionsFound(users: Seq[UserSubscription])
or Failure(exception)
In our situation (spray apps but also CLI), we wrapped those calls in a short living actor that take the context and complete on reception and closes itself. (You could handle domain specific logic in those actor, have it to extend another actor that manages its lifecycle and exception so you would only have to specify a partial function for your needs and leave the abstract actor to deal with timeouts, common exceptions etc.
We also have situations where we needed more work to be done in the initiating actor, and it very convenient to fire x messages to your repositories and have your actor storing those messages as they arrive, doing something once they are all there, firing back for completion to the sender( for instance) and close itself.
Thanks to this design, we have a very reactive repository living outside our app, completely tested with Akka TestKit and H2, completely DB agnostic, and it's dead easy, to access data from our DBs (and we never do any ASK, only Tell : Tell to repo, tell to sender, complete or x Tells to repos, pattern match on expected results until completion, tell to sender).