From fcd6185265f2075d47b99be7d0c8ffcbc3f9c5eb Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Thu, 29 Aug 2019 14:26:40 +0200 Subject: [PATCH] Move generic mailbox docs from classic to main mailboxes doc (#27493) * Move generic mailbox docs from classic to main mailboxes doc * 'Mailbox configuration examples' could still be converted, but let's keep PR's small * Clarify configuration mailbox selection Co-Authored-By: Helena Edelson --- akka-docs/src/main/paradox/mailboxes.md | 189 +----------------- akka-docs/src/main/paradox/typed/mailboxes.md | 182 ++++++++++++++++- 2 files changed, 182 insertions(+), 189 deletions(-) diff --git a/akka-docs/src/main/paradox/mailboxes.md b/akka-docs/src/main/paradox/mailboxes.md index e808aa9e50..1e282644f5 100644 --- a/akka-docs/src/main/paradox/mailboxes.md +++ b/akka-docs/src/main/paradox/mailboxes.md @@ -27,6 +27,8 @@ An Akka `Mailbox` holds the messages that are destined for an `Actor`. Normally each `Actor` has its own mailbox, but with for example a `BalancingPool` all routees will share a single mailbox instance. +For more details on advanced mailbox config and custom mailbox implementations, see @ref[Mailboxes](typed/mailboxes.md#mailbox-implementations). + ## Mailbox Selection ### Requiring a Message Queue Type for an Actor @@ -60,148 +62,7 @@ The type of the queue in the mailbox created for an actor will be checked agains ### Requiring a Message Queue Type for a Dispatcher A dispatcher may also have a requirement for the mailbox type used by the -actors running on it. An example is the BalancingDispatcher which requires a -message queue that is thread-safe for multiple concurrent consumers. Such a -requirement is formulated within the dispatcher configuration section like -this: - -``` -my-dispatcher { - mailbox-requirement = org.example.MyInterface -} -``` - -The given requirement names a class or interface which will then be ensured to -be a supertype of the message queue’s implementation. In case of a -conflict—e.g. if the actor requires a mailbox type which does not satisfy this -requirement—then actor creation will fail. - -### How the Mailbox Type is Selected - -When an actor is created, the `ActorRefProvider` first determines the -dispatcher which will execute it. Then the mailbox is determined as follows: - - 1. If the actor’s deployment configuration section contains a `mailbox` key -then that names a configuration section describing the mailbox type to be -used. - 2. If the actor’s `Props` contains a mailbox selection—i.e. `withMailbox` -was called on it—then that names a configuration section describing the -mailbox type to be used (note that this needs to be an absolute config path, -for example `myapp.special-mailbox`, and is not nested inside the `akka` namespace). - 3. If the dispatcher’s configuration section contains a `mailbox-type` key -the same section will be used to configure the mailbox type. - 4. If the actor requires a mailbox type as described above then the mapping for -that requirement will be used to determine the mailbox type to be used; if -that fails then the dispatcher’s requirement—if any—will be tried instead. - 5. If the dispatcher requires a mailbox type as described above then the -mapping for that requirement will be used to determine the mailbox type to -be used. - 6. The default mailbox `akka.actor.default-mailbox` will be used. - -### Default Mailbox - -When the mailbox is not specified as described above the default mailbox -is used. By default it is an unbounded mailbox, which is backed by a -`java.util.concurrent.ConcurrentLinkedQueue`. - -`SingleConsumerOnlyUnboundedMailbox` is an even more efficient mailbox, and -it can be used as the default mailbox, but it cannot be used with a BalancingDispatcher. - -Configuration of `SingleConsumerOnlyUnboundedMailbox` as default mailbox: - -``` -akka.actor.default-mailbox { - mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox" -} -``` - -### Which Configuration is passed to the Mailbox Type - -Each mailbox type is implemented by a class which extends `MailboxType` -and takes two constructor arguments: a `ActorSystem.Settings` object and -a `Config` section. The latter is computed by obtaining the named -configuration section from the actor system’s configuration, overriding its -`id` key with the configuration path of the mailbox type and adding a -fall-back to the default mailbox configuration section. - -## Builtin Mailbox Implementations - -Akka comes shipped with a number of mailbox implementations: - - * - **UnboundedMailbox** (default) - * The default mailbox - * Backed by a `java.util.concurrent.ConcurrentLinkedQueue` - * Blocking: No - * Bounded: No - * Configuration name: `"unbounded"` or `"akka.dispatch.UnboundedMailbox"` - * - **SingleConsumerOnlyUnboundedMailbox** - This queue may or may not be faster than the default one depending on your use-case—be sure to benchmark properly! - * Backed by a Multiple-Producer Single-Consumer queue, cannot be used with `BalancingDispatcher` - * Blocking: No - * Bounded: No - * Configuration name: `"akka.dispatch.SingleConsumerOnlyUnboundedMailbox"` - * - **NonBlockingBoundedMailbox** - * Backed by a very efficient Multiple-Producer Single-Consumer queue - * Blocking: No (discards overflowing messages into deadLetters) - * Bounded: Yes - * Configuration name: `"akka.dispatch.NonBlockingBoundedMailbox"` - * - **UnboundedControlAwareMailbox** - * Delivers messages that extend `akka.dispatch.ControlMessage` with higher priority - * Backed by two `java.util.concurrent.ConcurrentLinkedQueue` - * Blocking: No - * Bounded: No - * Configuration name: "akka.dispatch.UnboundedControlAwareMailbox" - * - **UnboundedPriorityMailbox** - * Backed by a `java.util.concurrent.PriorityBlockingQueue` - * Delivery order for messages of equal priority is undefined - contrast with the UnboundedStablePriorityMailbox - * Blocking: No - * Bounded: No - * Configuration name: "akka.dispatch.UnboundedPriorityMailbox" - * - **UnboundedStablePriorityMailbox** - * Backed by a `java.util.concurrent.PriorityBlockingQueue` wrapped in an `akka.util.PriorityQueueStabilizer` - * FIFO order is preserved for messages of equal priority - contrast with the UnboundedPriorityMailbox - * Blocking: No - * Bounded: No - * Configuration name: "akka.dispatch.UnboundedStablePriorityMailbox" - -Other bounded mailbox implementations which will block the sender if the capacity is reached and -configured with non-zero `mailbox-push-timeout-time`. - -@@@ note - -The following mailboxes should only be used with zero `mailbox-push-timeout-time`. - -@@@ - - * **BoundedMailbox** - * Backed by a `java.util.concurrent.LinkedBlockingQueue` - * Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No - * Bounded: Yes - * Configuration name: "bounded" or "akka.dispatch.BoundedMailbox" - * **BoundedPriorityMailbox** - * Backed by a `java.util.PriorityQueue` wrapped in an `akka.util.BoundedBlockingQueue` - * Delivery order for messages of equal priority is undefined - contrast with the `BoundedStablePriorityMailbox` - * Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No - * Bounded: Yes - * Configuration name: `"akka.dispatch.BoundedPriorityMailbox"` - * **BoundedStablePriorityMailbox** - * Backed by a `java.util.PriorityQueue` wrapped in an `akka.util.PriorityQueueStabilizer` and an `akka.util.BoundedBlockingQueue` - * FIFO order is preserved for messages of equal priority - contrast with the BoundedPriorityMailbox - * Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No - * Bounded: Yes - * Configuration name: "akka.dispatch.BoundedStablePriorityMailbox" - * **BoundedControlAwareMailbox** - * Delivers messages that extend `akka.dispatch.ControlMessage` with higher priority - * Backed by two `java.util.concurrent.ConcurrentLinkedQueue` and blocking on enqueue if capacity has been reached - * Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No - * Bounded: Yes - * Configuration name: "akka.dispatch.BoundedControlAwareMailbox" +actors running on it. This can be configured as documented at [typed/mailboxes.md#requiring-a-message-queue-type-for-a-dispatcher] ## Mailbox configuration examples @@ -276,50 +137,6 @@ Scala Java : @@snip [DispatcherDocTest.java](/akka-docs/src/test/java/jdocs/dispatcher/DispatcherDocTest.java) { #control-aware-dispatcher } -## Creating your own Mailbox type - -An example is worth a thousand quacks: - -Scala -: @@snip [MyUnboundedMailbox.scala](/akka-docs/src/test/scala/docs/dispatcher/MyUnboundedMailbox.scala) { #mailbox-marker-interface } - -Java -: @@snip [MyUnboundedMessageQueueSemantics.java](/akka-docs/src/test/java/jdocs/dispatcher/MyUnboundedMessageQueueSemantics.java) { #mailbox-marker-interface } - - -Scala -: @@snip [MyUnboundedMailbox.scala](/akka-docs/src/test/scala/docs/dispatcher/MyUnboundedMailbox.scala) { #mailbox-implementation-example } - -Java -: @@snip [MyUnboundedMailbox.java](/akka-docs/src/test/java/jdocs/dispatcher/MyUnboundedMailbox.java) { #mailbox-implementation-example } - -And then you specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher -configuration, or the mailbox configuration. - -@@@ note - -Make sure to include a constructor which takes -`akka.actor.ActorSystem.Settings` and `com.typesafe.config.Config` -arguments, as this constructor is invoked reflectively to construct your -mailbox type. The config passed in as second argument is that section from -the configuration which describes the dispatcher or mailbox setting using -this mailbox type; the mailbox type will be instantiated once for each -dispatcher or mailbox setting using it. - -@@@ - -You can also use the mailbox as a requirement on the dispatcher like this: - -@@snip [DispatcherDocSpec.scala](/akka-docs/src/test/scala/docs/dispatcher/DispatcherDocSpec.scala) { #custom-mailbox-config-java } - -Or by defining the requirement on your actor class like this: - -Scala -: @@snip [DispatcherDocSpec.scala](/akka-docs/src/test/scala/docs/dispatcher/DispatcherDocSpec.scala) { #require-mailbox-on-actor } - -Java -: @@snip [DispatcherDocTest.java](/akka-docs/src/test/java/jdocs/dispatcher/DispatcherDocTest.java) { #require-mailbox-on-actor } - ## Special Semantics of `system.actorOf` In order to make `system.actorOf` both synchronous and non-blocking while diff --git a/akka-docs/src/main/paradox/typed/mailboxes.md b/akka-docs/src/main/paradox/typed/mailboxes.md index 2b161c6085..13a6cf58a5 100644 --- a/akka-docs/src/main/paradox/typed/mailboxes.md +++ b/akka-docs/src/main/paradox/typed/mailboxes.md @@ -25,7 +25,9 @@ For advanced use cases it is also possible to defer mailbox selection to config ## Selecting what mailbox is used -To select mailbox for an actor use `MailboxSelector` to create a `Props` instance for spawning your actor: +### Selecting a Mailbox Type for an Actor + +To select a specific mailbox for an actor use `MailboxSelector` to create a `Props` instance for spawning your actor: Scala : @@snip [MailboxDocSpec.scala](/akka-actor-typed-tests/src/test/scala/docs/akka/typed/MailboxDocSpec.scala) { #select-mailbox } @@ -33,8 +35,182 @@ Scala Java : @@snip [MailboxDocTest.java](/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/MailboxDocTest.java) { #select-mailbox } -`fromConfig` takes an absolute config path to a block defining the dispatcher in the config file like this: +`fromConfig` takes an absolute config path to a block defining the dispatcher in the config file: @@snip [MailboxDocSpec.scala](/akka-actor-typed-tests/src/test/resources/mailbox-config-sample.conf) { } -For more details on advanced mailbox config and custom mailbox implementations, see @ref[Classic Mailboxes](../mailboxes.md#builtin-mailbox-implementations). +### Requiring a Message Queue Type for a Dispatcher + +A dispatcher may also have a requirement for the mailbox type used by the +actors running on it. An example is the @apidoc[BalancingDispatcher] which requires a +message queue that is thread-safe for multiple concurrent consumers. Such a +requirement is formulated within the dispatcher configuration section: + +``` +my-dispatcher { + mailbox-requirement = org.example.MyInterface +} +``` + +The given requirement names a class or interface which will then be ensured to +be a supertype of the message queue's implementation. In case of a +conflict—e.g. if the actor requires a mailbox type which does not satisfy this +requirement—then actor creation will fail. + +### How the Mailbox Type is Selected + +When an actor is created, the `ActorRefProvider` first determines the +dispatcher which will execute it. Then the mailbox is determined as follows: + + 1. If the actor's deployment configuration section contains a `mailbox` key, +this refers to a configuration section describing the mailbox type. + 2. If the actor's `Props` contains a mailbox selection then that names a configuration section describing the +mailbox type to be used. This needs to be an absolute config path, +for example `myapp.special-mailbox`, and is not nested inside the `akka` namespace. + 3. If the dispatcher's configuration section contains a `mailbox-type` key +the same section will be used to configure the mailbox type. + 4. If the actor requires a mailbox type as described above then the mapping for +that requirement will be used to determine the mailbox type to be used; if +that fails then the dispatcher's requirement—if any—will be tried instead. + 5. If the dispatcher requires a mailbox type as described above then the +mapping for that requirement will be used to determine the mailbox type to +be used. + 6. The default mailbox `akka.actor.default-mailbox` will be used. + +### Default Mailbox + +The default mailbox is used when the mailbox is not specified. +This is an unbounded mailbox, backed by a +`java.util.concurrent.ConcurrentLinkedQueue`. + +`SingleConsumerOnlyUnboundedMailbox` is an even more efficient mailbox, and +it can be used as the default mailbox, but it cannot be used with a BalancingDispatcher. + +Configuration of `SingleConsumerOnlyUnboundedMailbox` as default mailbox: + +``` +akka.actor.default-mailbox { + mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox" +} +``` + +### Which Configuration is passed to the Mailbox Type + +Each mailbox type is implemented by a class which extends `MailboxType` +and takes two constructor arguments: a `ActorSystem.Settings` object and +a `Config` section. The latter is computed by obtaining the named +configuration section from the `ActorSystem` configuration, overriding its +`id` key with the configuration path of the mailbox type and adding a +fall-back to the default mailbox configuration section. + +## Mailbox Implementations + +Akka ships with a number of mailbox implementations: + + * + **UnboundedMailbox** (default) + * The default mailbox + * Backed by a `java.util.concurrent.ConcurrentLinkedQueue` + * Blocking: No + * Bounded: No + * Configuration name: `"unbounded"` or `"akka.dispatch.UnboundedMailbox"` + * + **SingleConsumerOnlyUnboundedMailbox** + Depending on your use case, this queue may or may not be faster than the default one — be sure to benchmark properly! + * Backed by a Multiple-Producer Single-Consumer queue, cannot be used with `BalancingDispatcher` + * Blocking: No + * Bounded: No + * Configuration name: `"akka.dispatch.SingleConsumerOnlyUnboundedMailbox"` + * + **NonBlockingBoundedMailbox** + * Backed by a very efficient Multiple-Producer Single-Consumer queue + * Blocking: No (discards overflowing messages into deadLetters) + * Bounded: Yes + * Configuration name: `"akka.dispatch.NonBlockingBoundedMailbox"` + * + **UnboundedControlAwareMailbox** + * Delivers messages that extend `akka.dispatch.ControlMessage` with higher priority + * Backed by two `java.util.concurrent.ConcurrentLinkedQueue` + * Blocking: No + * Bounded: No + * Configuration name: "akka.dispatch.UnboundedControlAwareMailbox" + * + **UnboundedPriorityMailbox** + * Backed by a `java.util.concurrent.PriorityBlockingQueue` + * Delivery order for messages of equal priority is undefined - contrast with the UnboundedStablePriorityMailbox + * Blocking: No + * Bounded: No + * Configuration name: "akka.dispatch.UnboundedPriorityMailbox" + * + **UnboundedStablePriorityMailbox** + * Backed by a `java.util.concurrent.PriorityBlockingQueue` wrapped in an `akka.util.PriorityQueueStabilizer` + * FIFO order is preserved for messages of equal priority - contrast with the UnboundedPriorityMailbox + * Blocking: No + * Bounded: No + * Configuration name: "akka.dispatch.UnboundedStablePriorityMailbox" + +Other bounded mailbox implementations which will block the sender if the capacity is reached and +configured with non-zero `mailbox-push-timeout-time`. + +@@@ note + +The following mailboxes should only be used with zero `mailbox-push-timeout-time`. + +@@@ + + * **BoundedMailbox** + * Backed by a `java.util.concurrent.LinkedBlockingQueue` + * Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No + * Bounded: Yes + * Configuration name: "bounded" or "akka.dispatch.BoundedMailbox" + * **BoundedPriorityMailbox** + * Backed by a `java.util.PriorityQueue` wrapped in an `akka.util.BoundedBlockingQueue` + * Delivery order for messages of equal priority is undefined - contrast with the `BoundedStablePriorityMailbox` + * Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No + * Bounded: Yes + * Configuration name: `"akka.dispatch.BoundedPriorityMailbox"` + * **BoundedStablePriorityMailbox** + * Backed by a `java.util.PriorityQueue` wrapped in an `akka.util.PriorityQueueStabilizer` and an `akka.util.BoundedBlockingQueue` + * FIFO order is preserved for messages of equal priority - contrast with the BoundedPriorityMailbox + * Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No + * Bounded: Yes + * Configuration name: "akka.dispatch.BoundedStablePriorityMailbox" + * **BoundedControlAwareMailbox** + * Delivers messages that extend `akka.dispatch.ControlMessage` with higher priority + * Backed by two `java.util.concurrent.ConcurrentLinkedQueue` and blocking on enqueue if capacity has been reached + * Blocking: Yes if used with non-zero `mailbox-push-timeout-time`, otherwise No + * Bounded: Yes + * Configuration name: "akka.dispatch.BoundedControlAwareMailbox" + +## Custom Mailbox type + +The best way to show how to create your own Mailbox type is by example: + +Scala +: @@snip [MyUnboundedMailbox.scala](/akka-docs/src/test/scala/docs/dispatcher/MyUnboundedMailbox.scala) { #mailbox-marker-interface } + +Java +: @@snip [MyUnboundedMessageQueueSemantics.java](/akka-docs/src/test/java/jdocs/dispatcher/MyUnboundedMessageQueueSemantics.java) { #mailbox-marker-interface } + + +Scala +: @@snip [MyUnboundedMailbox.scala](/akka-docs/src/test/scala/docs/dispatcher/MyUnboundedMailbox.scala) { #mailbox-implementation-example } + +Java +: @@snip [MyUnboundedMailbox.java](/akka-docs/src/test/java/jdocs/dispatcher/MyUnboundedMailbox.java) { #mailbox-implementation-example } + +And then you specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher +configuration, or the mailbox configuration. + +@@@ note + +Make sure to include a constructor which takes +`akka.actor.ActorSystem.Settings` and `com.typesafe.config.Config` +arguments, as this constructor is invoked reflectively to construct your +mailbox type. The config passed in as second argument is that section from +the configuration which describes the dispatcher or mailbox setting using +this mailbox type; the mailbox type will be instantiated once for each +dispatcher or mailbox setting using it. + +@@@ +