With the release of Scala 2.9.0, the Typesafe Stack was also announced, which combines the Scala language with the Akka framework. Now, though Scala has actors in its standard library, Akka uses its own implementation. And, if we look for other implementations, we'll also find that Lift and Scalaz have implementations too!
So, what is the difference between these implementations?
This answer isn't really mine. It was produced by Viktor Klang (of Akka fame) with the help of David Pollak (of Lift fame), Jason Zaugg (of Scalaz fame), Philipp Haller (of Scala Actors fame).
All I'm doing here is formatting it (which would be easier if Stack Overflow supported tables).
There are a few places I'll fill later when I have more time.
Design Philosophy
Scalaz Actors
Minimal complexity. Maximal generality, modularity and extensibility.
Lift Actors
Minimal complexity, Garbage Collection by JVM rather than worrying about an explicit lifecycle, error handling behavior consistent with other Scala & Java programs, lightweight/small memory footprint, mailbox, statically similar to Scala Actors and Erlang actors, high performance.
Scala Actors
Provide the full Erlang actor model in Scala, lightweight/small memory footprint.
Akka Actors
Simple and transparently distributable, high performance, lightweight and highly adaptable.
Versioning
Scalaz Actors Lift Actors Scala Actors Akka Actors
Current stable ver. 5 2.1 2.9.0 0.10
Minimum Scala ver. 2.8 2.7.7 2.8
Minimum Java ver. 1.5 1.5 1.6
Actor Model Support
Scalaz Actors Lift Actors Scala Actors Akka Actors
Spawn new actors Yes Yes Yes Yes
inside of actor
Send messages to Yes Yes Yes Yes
known actor
Change behavior Actors are Yes Yes: nested Yes:
for next message immutable react/receive become/unbecome
Supervision Not provided No Actor: Yes, Yes
(link/trapExit) Reactor: No
Level of state isolation
If user defines public methods on
their Actors, are they callable from
the outside?
Scalaz Actors: n/a. Actor is a sealed trait.
Lift Actors: Yes
Scala Actors: Yes
Akka Actors: No, actor instance is shielded behind an ActorRef.
Actor type
Scalaz Actors: Actor[A] extends A => ()
Lift Actors: LiftActor, SpecializeLiftActor[T]
Scala Actors: Reactor[T], Actor extends Reactor[Any]
Akka Actors: Actor[Any]
Actor lifecycle management
Scalaz Actors Lift Actors Scala Actors Akka Actors
Manual start No No Yes Yes
Manual stop No No No Yes
Restart-on-failure n/a Yes Yes Configurable per actor instance
Restart semantics n/a Rerun actor Restore actor to stable state by re-allocating it and
behavior throw away the old instance
Restart configurability n/a n/a X times, X times within Y time
Lifecycle hooks provided No lifecycle act preStart, postStop, preRestart, postRestart
Message send modes
Scalaz Actors Lift Actors Scala Actors Akka Actors
Fire-forget a ! message actor ! msg actor ! msg actorRef ! msg
a(message)
Send-receive-reply (see 1) actor !? msg actor !? msg actorRef !! msg
actor !! msg
Send-receive-future (see 2) actor !! msg actorRef !!! msg
Send-result-of- promise(message). future.onComplete( f => to ! f.result )
future to(actor)
Compose actor with actor comap f No No No
function (see 3)
(1) Any function f becomes such an actor:
val a: Msg => Promise[Rep] = f.promise
val reply: Rep = a(msg).get
(2) Any function f becomes such an actor:
val a = f.promise
val replyFuture = a(message)
(3) Contravariant functor: actor comap f. Also Kleisli composition in Promise.
Message reply modes
TBD
Scalaz Actors Lift Actors Scala Actors Akka Actors
reply-to-sender-in-message
reply-to-message
Message processing
Supports nested receives?
Scalaz Actors: --
Lift Actors: Yes (with a little hand coding).
Scala Actors: Yes, both thread-based receive and event-based react.
Akka Actors: No, nesting receives can lead to memory leaks and degraded performance over time.
Message Execution Mechanism
TBD
Scalaz Actors Lift Actors Scala Actors Akka Actors
Name for Execution Mechanism
Execution Mechanism is
configurable
Execution Mechanism can be
specified on a per-actor basis
Lifecycle of Execution Mechanism
must be explicitly managed
Thread-per-actor execution
mechanism
Event-driven execution mechanism
Mailbox type
Supports transient mailboxes
Supports persistent mailboxes
Distribution/Remote Actors
Scalaz Actors Lift Actors Scala Actors Akka Actors
Transparent remote n/a No Yes Yes
actors
Transport protocol n/a n/a Java Akka Remote Protocol
serialization (Protobuf on top of TCP)
on top of TCP
Dynamic clustering n/a n/a n/a In commercial offering
Howtos
TBD
Scalaz Actors Lift Actors Scala Actors Akka Actors
Define an actor
Create an actor instance
Start an actor instance
Stop an actor instance
scala.actors was the first serious attempt to implement Erlang-style concurrency in Scala that has inspired other library designers for making a better (in some cases) and more performant implementations. The biggest problem (at least for me), is that unlike Erlang processes, complemented with OTP (that allows for building fault-tolerant systems), scala.actors only offer a good foundation, a set of stable primitives that must be used for building a more high-level frameworks - at the end of the day, you’ll have to write your own supervisors, catalogs of actors, finite state machines, etc. on top of actors.
And here Akka comes to the rescue, offering a full-featured stack for actor-based development: more idiomatic actors, set of high-level abstractions for coordination (load balancers, actor pools, etc.) and building fault-tolerant systems (supervisors, ported from OTP, etc.), easily configurable schedulers (dispatchers), and so on. Sorry, if I sound rude, but I think, there will be no merge in 2.9.0+ - I’d rather expect Akka actors to gradually replace stdlib implementation.
Scalaz. Normally I have this library in the list of dependencies of all my projects, and when, for some reason, I can’t use Akka, non-blocking Scalaz Promises (with all the goodness, like sequence) combined with the standard actors are saving the day. I never used Scalaz actors as a replacement for scala.actors or Akka, however.
Actors: Scala 2.10 vs Akka 2.3 vs Lift 2.6 vs Scalaz 7.1
Test code & results for average latency and throughput on JVM 1.8.0_x.
Related
I`m using Akka FSM in my project and going to add persistence.
The straightforward solution is to use Persistent FSM
(https://doc.akka.io/docs/akka/current/persistence-fsm.html)
However in the official documentation exists warning Warning
Persistent FSM is no longer actively developed and will be replaced by Akka Typed Persistence. It is not advised to build new applications with Persistent FSM.
But there no examples how to use typed persistence for FSM actors.
All that I see is how to use typed persistence for Typed Actors.
Is there any chance to use Typed Persistence along with FSM actors?
There are no "FSM Actors" in Akka Typed because it is inherently based on a state-machine model.
From the Akka Typed Documentation:
With untyped actors there is explicit support for building Finite State Machines. No support is needed in Akka Typed as it is straightforward to represent FSMs with behaviors.
In other words, you need to change your Akka FSM Actor into an Akka Typed Actor and then use the Akka Typed persistence framework.
I started learning Akka Streams, which is a framework for processing data with back-pressure functionality. The library is part of Akka that describes itself as:
Akka is a toolkit and runtime for building highly concurrent,
distributed, and resilient message-driven applications on the JVM.
These capabilities comes from the nature of Akka actors. However, from my perspective, stream processing and actors are irrelevant concept to each other.
Question:
Do Akka Streams take advantage of these features of Akka actors? If yes, would you explain how actors help streams?
Akka Streams is a higher level abstraction than actors. It's an implementation of Reactive Streams which builds on top of the actor model. It takes advantage of all the actor features because it uses actors.
You can even go back to using actors directly in any part of the stream. Look at ActorPublisher and ActorSubscriber.
A good starting point is the akka stream quickstart.
Yes, an Actor is used to "materialize" each {Source, Flow, Sink} of a Stream. This means that when you create a Stream nothing actually happens until the stream is materialized, typically via the .run() method call.
As an example, here is a Stream being defined:
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Source, Flow, Sink}
val stream = Source.single[String]("test")
.via(Flow[String].filter(_.size > 0))
.to(Sink.foreach{println})
Even though the stream is now a val no computation has actually happened. The Stream is just a recipe for computation. To actually kick-off the work the Stream needs to be materialized. Here is an example that does not use implicits to clearly show how materialization occurs:
val actorSystem = ActorSystem()
val materializer = ActorMaterializer()(actorSystem)
stream.run()(materializer) //work begins
Now 3 Actors (at least) have been created: 1 for the Source.single, 1 for the Flow.filter, and 1 for the Sink.foreach. Note: you can use the same materializer to initiate other streams
val doesNothingStream = Source.empty[String]
.to(Sink.ignore)
.run()(materializer)
I'm new to the actor model and I wonder how runtime errors should be handled.
Suppose actor catches exception, what should it do then?
I definitely want the sender to be notified of any errors, so, at least sender could log the errors.
Should all the response messages contain status field or should there exist XXXErrorMessage class for every response message in my application?
What are best practices for error handling in actor model?
You should google "erlang supervisor design", since the Actor model was mostly paved in erlang. Then you can apply the described knowledge with Akka actors (which is becoming standard actor lib in Scala 2.10). Also read the above commented akka docs on supervision and fault tolerance.
Alternatively, you might choose not to use Actors, but Futures instead, which are easier to compose. Then you will have Future[Either[E, A]] types, which you can treat as a combined EitherT[Future, E, A] monad type using scalaz + akkaz and use it in for comprehensions for example.
I would go with Actors if I expect a lot of failure, need to restart and retry things, having to encapsulate mutable state, etc. If you don't need these, you may fall back to Futures and have a better sleep.
I found there is also an Akka actor model, so I am wondering what's the difference between the Akka's Actor and Scala's Actor model?
Well, there isn't. There is just Actor model, and Akka actors and Scala actors are two implementations of that model.
All Actor model says that your concurrency primitives are actors, which can:
receive a message and decide what to do next depending on the content of the message, including:
send messages to any actors they know about
create new actors
and provides certain guarantees, e.g.:
any actor will only handle a single message at a time
messages sent by actor X to actor Y will arrive in the order thay were sent
There is no difference between Scala and Akka actors on this level.
For differences in what they can do, see Different Scala Actor Implementations Overview. The biggest one, for me, is that Akka supports supervisors and ActorRegistry.
There is also a historical answer. The creators of Scala thought there should be an actor framework. Jonas Bonér tried it out, but was not completely satisfied so he started working on a new - which evolved into Akka. However, the Scala people thought it was better than their own - so at Jfokus 2011 they announced that Akka was to become the standard actor framework of Scala. However, that migration will take some time.
This depends a little on what you mean with "model" - you can either refer to the "execution model" or the "programming model" (and perhaps other models as well).
For execution models, there are basically two: thread-based or event-based. The Scala standard actor library contains both. The thread-based uses one thread for each actor, whereas the event-based uses a thread-pool. The former is more intuitive to understand, the latter is more efficient. Akka is built on the event-based model.
For programming model, there is a big difference between the scala standard library and Akka. In the scala standard library, you basically implement the "run" method - and if you want to wait for an incoming message, you get yourself into a waiting state (by calling "receive" or "react"). So, the programming model follow the "thread-metaphor". However, in Akka, the programming metaphor is that you implement a few life-cycle methods - but the "run"-method is written inside the framework. It actually turns out that this programming model works a lot better with the event-based execution model as well.
If you are interested in the different execution models and programming models of scala standard actors I have written a few posts on the issue.
I want to implement some kind of message bus in one of my Scala applications. The features would be:
ability to subscribe to 1 .. N types of messages
messages may have payloads
loose coupling (nodes only hold a reference to the bus)
lightweight (no fully blown enterprise message queue etc.)
What I plan to do is to implement all nodes and the bus itself as standard Scala actors. For example I want to define a trait Subscriber like this:
trait Subscriber[M <: Message[_]] {
this: Actor =>
def notify(message: M)
}
Ideally mixing in this trait should already register the subscription for the type M.
So does this idea make sense? Are there better approaches to realize a message bus?
Disclaimer: I am the PO of Akka
Hi Itti,
This has already been done for you in Akka, the Actor Kernel: www.akka.io
Docs: http://doc.akkasource.org/routing-scala
Pub/Sub: Akka Listeners
Routers: Akka Routers
Convenience: Akka Routing