I need to implement back pressure where sending a message to an actor blocks if it's message box size has reached some predefined value, see http://blog.abhinav.ca/blog/2014/01/13/akka-and-backpressure/
Is there such a mailbox in akka.net? If yes, what's it named? AFAIK I should pass name of such a mailbox here:
spawnOpt
system
"worker"
(actorOf2 (fun (mb: Actor<int>) (msg: int) -> ()))
[SpawnOption.Mailbox "........"]
I understand that it means synchronous actor-to-actor communication. If akka.net is against it, what design you can suggest to implement a data processing pipeline, like load data -> [* * *] -> process -> [* * * * *] -> save data? (where [* * *] stands for a bounded queue of at most 3 messages).
Yes, there is the BoundedDequeBasedMailbox
https://github.com/akkadotnet/akka.net/blob/dev/src/core/Akka/Dispatch/BoundedDequeBasedMailbox.cs
That being said, JVM Akka have changed the behavior on that one so that instead of blocking, it drops messages when overflowing.
This is because if you use a blocking mailbox in a akka.remote scenario, and the endpoint reader tries to push a message to the target actor, the reader will be blocked, thus blocking the remote message pipeline.
So it works as intended locally, and will most likely be changed the same way as JVM Akka later.
OK, thanks. I cannot get it work, either of those does not work:
[SpawnOption.Mailbox "BoundedDequeBasedMailbox"]
[SpawnOption.Mailbox (typeof<Dispatch.BoundedDequeBasedMailbox>.FullName)]
[SpawnOption.Mailbox (typeof<Dispatch.BoundedDequeBasedMailbox>.AssemblyQualifiedName)]
It always raises exception:
> Akka.Configuration.ConfigurationException: Configuration problem while creating akka://WorkersSystem/user/worker with dispatcher [akka.actor.default-dispatcher] and mailbox [BoundedDequeBasedMailbox] ---> System.NullReferenceException: Object reference not set to an instance of an object.
at Akka.Dispatch.Mailboxes.FromConfig(String path)
at Akka.Dispatch.Mailboxes.CreateMailbox(Props props, Config dispatcherConfig)
at Akka.Actor.ActorCell.Init(Boolean sendSupervise, Func`1 createMailbox)
at Akka.Actor.LocalActorRef.<>c__DisplayClass7_0.<.ctor>b__0(LocalActorRef self)
at Akka.Actor.LocalActorRef..ctor(ActorSystem system, Props props, MessageDispatcher dispatcher, Func`1 createMailbox, IInternalActorRef supervisor, ActorPath path, Func`2 createActorCell)
at Akka.Actor.LocalActorRef..ctor(ActorSystemImpl system, Props props, MessageDispatcher dispatcher, Func`1 createMailbox, IInternalActorRef supervisor, ActorPath path)
at Akka.Actor.LocalActorRefProvider.ActorOf(ActorSystemImpl system, Props props, IInternalActorRef supervisor, ActorPath path, Boolean systemService, Deploy deploy, Boolean lookupDeploy, Boolean async)
--- End of inner exception stack trace ---
at Akka.Actor.LocalActorRefProvider.ActorOf(ActorSystemImpl system, Props props, IInternalActorRef supervisor, ActorPath path, Boolean systemService, Deploy deploy, Boolean lookupDeploy, Boolean async)
at Akka.Actor.ActorCell.MakeChild(Props props, String name, Boolean async, Boolean systemService)
at Akka.Actor.ActorCell.ActorOf(Props props, String name)
at <StartupCode$FSI_0007>.$FSI_0007.main@() in
That said and getting into account that it will change its behavior soon, how do you guys deal with unbounded nature of mailboxes? Do you use some poor man feedback algorithm or what? I mean, I just cannot imagine what to do if (when) producers are faster than consumers. I believe it's a so common risk that it should be solved in the library itself.
Try [SpawnOption.Mailbox "akka.actor.mailbox.bounded-deque-based"].
Also, backpressure is covered by Akka.Streams module, which is about to be released soon (you can build it and run already from akka-streams branch). Until then dynamic push-pull model can be realized as a communication pattern.
@Horusiath thanks, it works.
I'm very interested to try Streams. Is stuff in akka-streams branch any usable?
@vasily-kirichenko yes, you can build it and use. Only 2 notes:
Great! I've not found a larger examples or docs except https://github.com/akkadotnet/akka.net/blob/akka-streams/src/examples/Streams/StreamsExamples/Program.cs
Are there any? Or Scala docs work OK?
It's mostly compatible - if you throw out implicit parameters and graph DSL, which are unrepresentative in pure C# (therefore it's closer to Java graph DSL in this regard).
@Horusiath if you change naming convention to keep close with Linq, no one could find a proper documentation for Akka Streams. Because most of Akka.Net users actively using Akka Jvm docs, even if they don't know Scala/Java
@alexvaluyskiy I believe that potential C# developers will find more intuitive to use methods like Select or Where instead of going to JVM docs to find what Map and Filter are supposed to mean ;)
Docs can be improved, but public API, once settled, cannot.
Hi all,
I have the same need. This question is pretty old and now we have streams and I've been reading.. a lot. But the question I have, and I cannot find the answer, is this: Given an Actor model, where my consumer is way slower than the producer, how can I add backpressure? I've read the documentation for streams, the integration part looks like will contain the answer to my question, but after reading, I still have no idea how to do it without a major rewrite.
When I found this issue, I was exciting when discovering that I could use a bounded mailbox but after reading all the answers it looks like more than 2 years ago there were plans to drop that functionality, sad :(, is the functionality dropped? This approach looks more straightforward to me, I just configure the max bound and no change on my actor model.
Any example on how can I move from an existing actor model, to apply back pressure?
I'm sorry I asked but I really cannot figure this out by just reading the documentation.
Any help will be appreciated,
Thanks!
@erlis by design actor-actor communication is designed to be one-way best-effort (which means no confirmations, no redelivieries and no backpressure). The reason for this was that it's the most low-level primitive with the lowest cost. You can build any other communication mechanic on top of it.
Using bounded mailbox is not a good way to introduce backpressure (if I remember correctly, once mailbox is full, it could either drop overflowing messages or block sender thread until receiver frees the mailbox).
If you want to have actor-actor backpressure, most low-effort (but not the most performance wise) way to do it is request-response semantic e.g: using Ask method.
For actor-stream communication:
ActorPublisher/ActorSubscriber (I'm not sure, if this won't be removed in the future)Flow.Ask/Source.Ask, which basically works like SelectAsync+Ask, but also tracks if actor is alive.