Are non-serialisable `Props` an anti-pattern? - akka

Example:
Suppose I have an actor that is managing communication with some external service, so it has a Client object within it for making requests to the external service. In order to avoid this actor becoming monolithic, I might want to create child actors for handling different pieces of interaction: maintaining a heartbeat to the service, making and coordinating complicated requests, etc. These child actors will need a reference to a Client of the service.
Given that these client objects are unlikely to be serialisable and may be stateful e.g. contain connection state, is it an anti pattern to pass them to child actors via Props? The Akka documentation seems to strongly encourage maintaining serialisable props, but this seems to be extremely limiting in this case.

The Akka documentation seems to strongly encourage maintaining serialisable props
I am not aware of this suggestion, do you mind sharing the link in the question?
From my experience, it is pretty common to pass these Client references from parent to child actors. Sometimes I may choose to pass the exact method (a function) instead of the Client reference for the ease of unit testing. As long as you're not spawning an actor across the network boundary, I don't see any reason why this is a bad thing.
Regarding the Client object you describe, for network level things (e.g., connection state etc) I will leverage akka-http Client API. If you were to keep application level things, I would prefer having a separate actor to be dedicated for such use. It sounds a bit anti-pattern to me to keep application state in non-actor provided that you have Akka actor, which is designed to host state.

Related

Will Akka ShardRegion be a performance bottleneck if `ask` pattern is used instead of `tell`?

I'm a novice to Akka, and I want to create a distributed service by Akka gRPC and cluster sharding, which provides data retrieval service to clients.
So some RequestActor (maybe no such an actor at all with gRPC, I'm not sure) receives a client request, and forwards it to another ProcessingActor by shardRegion for query result.
There're two choices for this:
tell pattern
shardRegion ! Request(raw_request, localRequestActor)
ask pattern
shardRegion ? raw_request pipeTo(localRequestActor)
My questions are,
As all requests will be forwarded via shardRegion actor, so if I use the ask pattern, will shardRegion actor be the performance bottleneck? Or shardRegion just creates an internal actor to handle the future-promise stuff, and once the request is forwarded, shardRegion will not be involved any longer?
I know there's some performance/resource implication in ask compared with tell; on the other hand, ask provides the timeout mechanism, and we'll have to do it by ourselves with tell. As this is a request-response interaction, which is a better choice in my case?
Thanks!
You don't have any additional performance implication when using AskPattern with a shard region actor as an recipient. Because the actor which handles the Ask is created on the machine/ jvm where you instantiate the AskPattern. The shard region actor will not know about it.
In general it is a better practice to use tell and internal timeout handling within your actor for performance reasons. But if performance is not an issue for you, it's fair to use AskPattern due to less code IMHO.

Akka - understand the actors model

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.

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.

Akka / Actors: Share a single, limited resource among the actor hierarchy

I'm learning Akka, and I'm struggling to find a good pattern to share a single, limited resource among the whole actor hierarchy.
My use case is that I have a HTTP REST endpoint to which I'm only allowed 10 simultaneous connections at any time. Different actors at different levels of the hierarchy need to be able to make HTTP REST calls. I'm using non-blocking I/O to make the HTTP requests (AsyncHttpClient).
The obvious solution is to have a single actor in charge of this REST resource, and have any actors who want to access it send a message to it and expect a reply at a later stage, however:
Having a single actor in charge of this resource feels a bit fragile to me
How should any "client" actor know how to reach this resource manager actor? Is it best to create it at a well known location like /user/rest-manager and use an actor selection, or is it better to try to pass its ActorRef to every actor that needs it (but meaning it will need to be passed down in a lot of actors that don't use it, just so they can in turn pass it down)
In addition, how to deal with "blocking" the client actors when 10 connections are already in progress, especially since I'm using non-blocking I/O? Is it best practice to re-send a message to self (perhaps after some time) as a wait pattern?
I also thought of a token-based approach where the resource manager actor could reply with "access tokens" to client actors that needs to access the resource until exhaustion. However it means that client actors are supposed to "return" the token once they're done which doesn't sound ideal, and I will also need cater for actors dying without returning the token (with some sort of expiration timeout I guess).
What are the patterns / best practices to deal with that situation?
Updated: To indicate I'm using non-blocking I/O
My suggestions would be:
Use the Error Kernel pattern, as the REST endpoint, as you said, is a fragile code (I/O operations can generate any kind of errors). In other words, Master/Worker actor hierarchy, where Workers do the job, while Master does any supervision
Connection limit could be handled by Akka Routing feature, where number of Routees is, in your case, 10. This also drops into Master/Worker category
Addressing - either way sounds good
Connection timeout - to be handled by a client code, as it's always done in a majority of network libs.

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