I have a design challenge in regards to a new akka application that I'm building.
The issue/challenge is:
On the client side I have made a simple actor which sends a request, and then using become() in order to wait for a proper server answer, of course also including a timeout message, in case I don't get an answer in proper time.
The interesting thing is however on the server side.
Here i have the following construction:
Actor A (Configured as a round robin router) this router is receiving all request from the client.
Actor A then forwards message to Actor A1, A2...Ax which all have been created in the context of actor A meaning it's the supervisor of them.
In the normal case the Actor Ax would be able to just reply to the sender, since the message is forwarded, however...
In case of an error I would like to besides log it on the server log, also to give the user som kind of information on the error that has happened.
In the perfect world I would prefer to be able to somehow in the supervisor strategy to just say something like getErrorActorsLastSender() and then get the ActorRef of the client which caused the issue. The reason why I prefer this, is that then I would have one place to have all the error handling, and all unforseen exceptions would always be handled at least in some generic way.
The alternative is to override the prerestart() method on each child actor, and then make the supervisor strategy to restart the actor when an exception is thrown. However this would require me to implement this method for x child actors.
Any good suggestions, if this is possible from supervisor strategy?
Thanks in advance.
Have you tried creating your own supervisor strategy, for example by extending OneForOneStrategy? There is a method called handleFailure which takes (among others) the child and the cause of the failure. Also you will get the ActorContext, which gives you the sender of the message that caused the error, I think you should be able to do what you want when you override this method.
One way to achieve your goals is to encapsulate the sender in the Exception. If you throw the Exception yourself, this should be straightforward.
Related
I am trying to configure an Akka Actor for Cluster Sharding, one thing that I am not quite sure, is it possible to configure several Stop Messages for an Entity for graceful Shutdown.
for ex, Entity configuration like following will trigger graceful shutdown for both 'onDelete' and 'onExit' or it will do it only for 'onExit'?
sharding
.init(
Entity(Actor1Key) {
context => ....
}
)
.withStopMessage(Actor1.onDelete)
.withStopMessage(Actor1.onExit)
if not do you have any idea how I can achieve this Behaviour?
Thx for answers
I think there may some confusion around what the purpose of the stopMessage is. There should not be a need for multiple stop messages.
The stopMessage sent by sharding after passivation has been requested by the actor, which is done by sending Passivate from the sharded actor itself.
You can let any of the messages that the actor accepts trigger passivation, the shard will send back the stopMessage when it is safe for the actor to actually stop.
The reason you should passivate rather than just Behaviors.stopped the actor is that there may be messages that was en route to the actor (mailbox and I think possibly a buffer in the shard in some circumstances) before the message causing it deciding to stop and you want to process those first. Passivation allows for that to happen by including a roundtrip to the shard actor which is charge of routing messages to the sharded actor.
A bit more details in the docs here: https://doc.akka.io/docs/akka/current/typed/cluster-sharding.html#passivation
What you have specified would only trigger the stop message for Actor1.onExit. The reason is how a stop message is defined for an Entity:
val stopMessage: Optional[M],
So you see that this is a plain optional thus no multiple elements are possible. You can also check how the withStopMessage is implemented here:
def withStopMessage(newStopMessage: M): Entity[M, E] =
copy(stopMessage = Optional.ofNullable(newStopMessage))
So you are basically going to "overwrite" the message any time you call withStopMessage. Unfortunately, I am not aware of any other way of specifying multiple stop messages (besides combining multiple messages in a common trait but I think this is not what you are looking for).
I have written some actor classes and I find that I have to get a handle into the lifecycle of these entities. For example whenever my actor is initialized I would like a method to be called so that I can setup some listeners on message queues (or open db connections etc).
Is there an equivalent of this? The equivalent I can think of is Spring's InitialisingBean and DisposableBean
This is a typical scenario where you would override methods like preStart(), postStop(), etc. I don't see anything wrong with this.
Of course you have to be aware of the details - for example postStop() is called asynchronously after actor.stop() is invoked while preStart() is called when an Actor is started. This means that potentially slow/blocking things like DB interaction should be kept to a minimum.
You can also use the Actor's constructor for initialization of data.
As Matthew mentioned, supervision plays a big part in Akka - so you can instruct the supervisor to perform specific stuff on events. For example the so-called DeathWatch - you can be notified if one of the actors "you are watching upon" dies:
context.watch(child)
...
def receive = {
case Terminated(`child`) => lastSender ! "finished"
}
An Actor is basically two methods -- a constructor, and onMessage(Object): void.
There's nothing in its lifecycle that naturally provides for "wiring" behavior, which leaves you with a few options.
Use a Supervisor actor to create your other actors. A Supervisor is responsible for watching, starting and restarting Actors on failure -- and therefore it is often valuable to have a Supervisor that understands the state of integrated systems to avoid continously restarting. This Supervisor would create and manage Service objects (possibly via Spring) and pass them to Actors.
Use your preferred Initialization technique at the time of Actor construction. It's tricky but you can certainly combine Spring with Actors. Just be aware that should a Supervisor restart your actor, you'll need to be able to resurrect its desired state from whatever content you placed in the Props object you used to start it in the first place.
Wire everything on-demand. Open connections on demand when an Actor starts (and cache them as necessary). I find I do this fairly often -- and I let the Actor fail when its connections no longer work. The supervisor will restart the Actor, which will recreate all connections.
Something important things to remember:
The intent of Actor model is that Actors don't run continuously -- they only run when there are messages provided to them. If you add a message listener to an Actor, you are essentially adding new threads that can access that actor. This can be a problem if you use supervision -- a restarted actor may leak that thread and this may in turn cause the actor not to be garbage collected. It can also be a problem because it introduces a race condition, and part of the value of actors is avoiding that.
An Actor that does I/O is, from the perspective of the actor system, blocking. If you have too many Actors doing I/O at the same time, you will exhaust your Dispatcher's thread pool and lock up the system.
A given Actor instance can operate on many different threads over its lifetime, but will only operate on one thread at a time. This can be confusing to some messaging systems -- for example, JMS' Spec asserts that a Session not be used on multiple threads, and many JMS interpret this as "can only run on the thread on which it was started." You may see warnings, or even exceptions, resulting from this.
For these reasons, I prefer to use non-actor code to do some of my I/O. For example, I'll have an incoming message listener object whose responsibility is to take JMS messages off a queue, use them to create POJO messages, and send tells to the Actor system. Alternately, I'll use an Actor, but place that actor on a custom Dispatcher that has thread pinning enabled. This assures that that Actor will only run on a specific thread and won't block up the system that other non-I/O actors are using.
Java/Akka (v2.3.9) here. Each of my Akka UntypedActor subclasses has the ability to respond to several "generic" messages, such as ExecuteOrder66:
// Groovy pseudo-code
class StormTrooper extends UntypedActor {
#Override
void onReceive(Object message) throws Exception {
if(message instanceof ExecuteOrder66) {
// Betray the Jedi, serve only the emperor.
}
}
}
Let's say I have 100 different actor subclasses that each support ExecuteOrder66. I need a way to broadcast instances of this message to every single one of my actors; so like a public broadcast announce which everybody gets.
I think that link to the Akka docs above gets me close, but I'm not seeing one that sends an ExecuteOrder66 to every single one of my actors. Any ideas?
The problem is that it is not quite clear who "everybody" is. What if some actor a gets a handshake message from some other actor b from remote actor system, stores b's reference, exchanges a few messages, then fails and restarts without the reference of b? Is b part of "everybody"? Who is responsible for finding the actor b again? How is one even supposed to know that b is still alive?
However, if you have a single specific actor system, a path selection with wildcards could do what you want. Something like this might do the job:
mySystem.actorSelection("akka://mySystemName/**")
This actor selection can then be used to tell (!) your broadcasted message to every actor on the system. You might also consider to be a little more restrictive, and select only the actors under /user, without touching the system actors.
Disclaimer: a little ad-hoc actor system I've just set up in the REPL doesn't complain about the path as indicated above, but I did not test it thoroughly. A runnable toy-example might be helpful.
I have a test for particular actor. This actor depends on some other actors, so I use TestProbe() to test in isolation.
My problem is, that I receive more messages then I am interested in testing at this very particular test. For example:
val a = TestProbe()
val b = TestProbe()
val actor = TestActorRef(new MyActor(a.ref, b.ref))
actor ! Message(1, 2)
b.expectMsg(3)
The test fails, because while creating MyActor it sends some kind of "registration" message to ones passed in constructor.
The message 3 arrives eventually, but assertion fails - this is not the first message to arrive.
I would like to avoid asserting more messages than I need for a test - those can change, etc, it is not the scope of a particular test anyway.
As the TestProbe does not contain such methods - I suspect there may be something wrong with my test setup (or rather my project architecture then). I see there are many methods like fishForMessage but all those require a explicit time parameters which seems like irrelevant as my whole test is purely synchronous.
Is there any way to accomplish such test is desired message is just among all the were received? If not, how can my setup can be improved to be easy testable?
The fishForMessage actually fits. All these assertions including expectMsg are asynchronous. expectMsg just uses the preconfigured timeFactor as timeout.
TestActorRef guarantees you only that CallingThreadDispatcher will be used to send messages and execute futures (if they use dispatcher from the test actor), so they will act sequentially til they're use context.dispatcher. Nothing stops some code inside your MyActor from using another dispatcher to send a response, so all checks still should be asynchronous - you just can't get rid of that.
Question from an akka newbie: let's say that at some point one of my actors wants to issue an HTTP request against an external REST API. What is the best way to do it? (note: I would ask the same question about an actor wishing to store data in a RDBMS).
Should I create another type of actor for that, and create a pool of such agents. Should I then create a message type that has the semantics of "please make an HTTP call to this endpoint", and should my first actor send this message to the pool to delegate the work?
Is that the recommended pattern (rather than doing the work in the initial actor)? And if so, would I then create a message type to communicate the outcome of the request to the initial actor when it is available?
Thank you for your feedback!
Olivier
This question is old now, but presumably one of your goals is to write reactive code that does not block threads, as sourcedelica mentioned. The Spray folks are best known for their async HTTP server and their awesome routing DSL (which you would use to create your own API), but they also offer a Spray-client package that allows your app to access other servers. It is based on Futures and thus allows you to get things done without blocking. Filip Andersson wrote an illustrative example; here are a few lines from it that will give you the idea:
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
// create a function to send a GET request and receive a string response
def get(url: String): Future[String] = {
val futureResponse = pipeline(Get(url))
futureResponse.map(_.entity.asString)
}
If you are familiar with futures, you know how you can further operate on Futures without blocking (like that map invocation). Spray's client library uses the same underlying data structures and concepts as their server side, which is handy if you are going to do both in one app.
Yes that sounds like a good approach.
If your HTTP client is blocking you will want to run the REST API calls in a different thread pool so you don't block your actors. You can use Future in actors to avoid blocking. Using a pool of actors is also possible though it's a little more work to set up.
For example, at the top level of your application create a ExecutionContext that is passed to actors that you create:
implicit val blockingEc =
ExecutionService.fromExecutorService(Executors.newFixedThreadPool(BlockingPoolSize))
class MyActor(implicit blockingEc: ExecutionContext) extends Actor {
def receive = {
case RestCall(arg) =>
val snd = sender()
Future { restApiCall(arg) } pipeTo snd
}
}
This will run the blocking call and send the result back to the requestor. Make sure to handle Status.Failure(ex) messages in the calling actor in case the restApiCall threw an exception.
The specific type and size of thread pool really depends on your application.