Improvements to reliable delivery docs (#28738)
* Add punctuation and fix some typo's * I passed through the introduction section and the section on point-to-point delivery.
This commit is contained in:
parent
ba450ee96b
commit
36187362be
1 changed files with 36 additions and 35 deletions
|
|
@ -25,14 +25,14 @@ To use reliable delivery, add the module to your project:
|
|||
|
||||
## Introduction
|
||||
|
||||
Normal @ref:[message delivery reliability](../general/message-delivery-reliability.md) is at-most once delivery, which
|
||||
Normal @ref:[message delivery reliability](../general/message-delivery-reliability.md) is at-most-once delivery, which
|
||||
means that messages may be lost. That should be rare, but still possible.
|
||||
|
||||
For interactions between some actors that is not acceptable and at-least once delivery or effectively once processing
|
||||
For interactions between some actors, that is not acceptable and at-least-once delivery or effectively-once processing
|
||||
is needed. The tools for reliable delivery described here help with implementing that. It can't be achieved
|
||||
automatically under the hood without collaboration from the application because confirming when a message has been
|
||||
automatically under the hood without collaboration from the application. This is because confirming when a message has been
|
||||
fully processed is a business level concern. Only ensuring that it was transferred over the network or delivered to
|
||||
the mailbox of the actor would not be enough, since it may crash right after without being processed.
|
||||
the mailbox of the actor would not be enough, since the actor may crash right before being able to process the message.
|
||||
|
||||
Lost messages are detected, resent and deduplicated as needed. In addition, it also includes flow control for
|
||||
the sending of messages to avoid that a fast producer overwhelms a slower consumer or sends messages at
|
||||
|
|
@ -50,7 +50,7 @@ There are 3 supported patterns, which are described in the following sections:
|
|||
|
||||
## Point-to-point
|
||||
|
||||
Point-to-point reliable delivery between a single producer actor sending messages and a single consumer actor
|
||||
This pattern implements point-to-point reliable delivery between a single producer actor sending messages and a single consumer actor
|
||||
receiving the messages.
|
||||
|
||||
Messages are sent from the producer to @apidoc[ProducerController] and via @apidoc[ConsumerController] actors, which
|
||||
|
|
@ -65,33 +65,34 @@ The `ProducerController` sends `RequestNext` to the producer, which is then allo
|
|||
message to the `ProducerController`. Thereafter the producer will receive a new `RequestNext`
|
||||
when it's allowed to send one more message.
|
||||
|
||||
The producer and `ProducerController` actors are supposed to be local so that these messages are
|
||||
fast and not lost. This is enforced by a runtime check.
|
||||
The producer and `ProducerController` actors are required to be local so that message delivery is
|
||||
both fast and guaranteed. This requirement is enforced by a runtime check.
|
||||
|
||||
Similarly, on the consumer side the destination consumer actor will start the flow by sending an
|
||||
initial `ConsumerController.Start` message to the `ConsumerController`.
|
||||
|
||||
For the `ProducerController` to know where to send the messages it must be connected with the
|
||||
`ConsumerController`. You do this is with `ProducerController.RegisterConsumer` or
|
||||
`ConsumerController.RegisterToProducerController` messages. When using the the point-to-point pattern
|
||||
it is the application's responsibility to connect them together. For example, by sending the `ActorRef`
|
||||
in an ordinary message to the other side, or register the `ActorRef` in the @ref:[Receptionist](actor-discovery.md)
|
||||
and find it on the other side.
|
||||
For the `ProducerController` to know where to send the messages, it must be connected with the
|
||||
`ConsumerController`. This can be done with the `ProducerController.RegisterConsumer` or
|
||||
`ConsumerController.RegisterToProducerController` messages. When using the point-to-point pattern,
|
||||
it is the application's responsibility to connect them together. For example, this can be done by sending the `ActorRef`
|
||||
in an ordinary message to the other side, or by registering the `ActorRef` in the @ref:[Receptionist](actor-discovery.md)
|
||||
so it can be found on the other side.
|
||||
|
||||
You must also take measures to reconnect them if any of the sides crashes, for example by watching it
|
||||
for termination.
|
||||
|
||||
Received messages from the producer are wrapped in `ConsumerController.Delivery` when sent to the consumer,
|
||||
which is supposed to reply with `ConsumerController.Confirmed` when it has processed the message.
|
||||
Next message is not delivered until the previous is confirmed. More messages from the producer that arrive
|
||||
Messages sent by the producer are wrapped in `ConsumerController.Delivery` when received by a consumer and the consumer
|
||||
should reply with `ConsumerController.Confirmed` when it has processed the message.
|
||||
|
||||
The next message is not delivered until the previous one is confirmed. Any messages from the producer that arrive
|
||||
while waiting for the confirmation are stashed by the `ConsumerController` and delivered when the previous
|
||||
message is confirmed.
|
||||
|
||||
The consumer and the `ConsumerController` actors are supposed to be local so that these messages are fast
|
||||
and not lost. This is enforced by a runtime check.
|
||||
Similar to the producer side, the consumer and the `ConsumerController` actors are required to be local so that message delivery is
|
||||
both fast and guaranteed. This requirement is enforced by a runtime check.
|
||||
|
||||
Many unconfirmed messages can be in flight between the `ProducerController` and `ConsumerController`, but
|
||||
it is limited by a flow control window. The flow control is driven by the consumer side, which means that
|
||||
their number is limited by a flow control window. The flow control is driven by the consumer side, which means that
|
||||
the `ProducerController` will not send faster than the demand requested by the `ConsumerController`.
|
||||
|
||||
### Point-to-point example
|
||||
|
|
@ -129,25 +130,25 @@ Java
|
|||
|
||||
### Point-to-point delivery semantics
|
||||
|
||||
As long as neither producer nor consumer crash the messages are delivered to the consumer actor in the same order
|
||||
as they were sent as they were sent to the `ProducerController`, without loss or duplicates. Meaning effectively
|
||||
once processing without any business level deduplication.
|
||||
As long as neither producer nor consumer crash, the messages are delivered to the consumer actor in the same order
|
||||
as they were sent to the `ProducerController`, without loss or duplicates. This means effectively-once
|
||||
processing without any business level deduplication.
|
||||
|
||||
Unconfirmed messages may be lost if the producer crashes. To avoid that you need to enable the @ref:[durable
|
||||
queue](#durable-producer) on the producer side. The stored unconfirmed messages will be redelivered when the
|
||||
corresponding producer is started again. Even if the same `ConsumerController` instance is used there may be
|
||||
Unconfirmed messages may be lost if the producer crashes. To avoid that, you need to enable the @ref:[durable
|
||||
queue](#durable-producer) on the producer side. By doing so, any stored unconfirmed messages will be redelivered when the
|
||||
corresponding producer is started again. Even if the same `ConsumerController` instance is used, there may be
|
||||
delivery of messages that had already been processed but the fact that they were confirmed had not been stored yet.
|
||||
Meaning at-least once delivery.
|
||||
This means that we have at-least-once delivery.
|
||||
|
||||
If the consumer crashes a new `ConsumerController` can be connected to the original `ProducerConsumer`
|
||||
If the consumer crashes, a new `ConsumerController` can be connected to the original `ProducerConsumer`
|
||||
without restarting it. The `ProducerConsumer` will then redeliver all unconfirmed messages. In that case
|
||||
the unconfirmed messages will be delivered to the new consumer, and some of these may already have been
|
||||
the unconfirmed messages will be delivered to the new consumer and some of these may already have been
|
||||
processed by the previous consumer.
|
||||
Meaning at-least once delivery.
|
||||
Again, this means that we have at-least-once delivery.
|
||||
|
||||
## Work pulling
|
||||
|
||||
Work pulling is a pattern where several worker actors pull tasks in their own pace from
|
||||
Work pulling is a pattern where several worker actors pull tasks at their own pace from
|
||||
a shared work manager instead of that the manager pushes work to the workers blindly
|
||||
without knowing their individual capacity and current availability.
|
||||
|
||||
|
|
@ -230,17 +231,17 @@ For work pulling the order of the messages should not matter, because each messa
|
|||
to one of the workers with demand and can therefore be processed in any order.
|
||||
|
||||
As long as neither producers nor workers crash (or workers being removed for other reasons) the messages are
|
||||
delivered to the workers without loss or duplicates. Meaning effectively once processing without any
|
||||
delivered to the workers without loss or duplicates. Meaning effectively-once processing without any
|
||||
business level deduplication.
|
||||
|
||||
Unconfirmed messages may be lost if the producer crashes. To avoid that you need to enable the @ref:[durable
|
||||
queue](#durable-producer) on the producer side. The stored unconfirmed messages will be redelivered when the
|
||||
corresponding producer is started again. Those messages may be routed to different workers than before
|
||||
and some of them may have already been processed but the fact that they were confirmed had not been stored
|
||||
yet. Meaning at-least once delivery.
|
||||
yet. Meaning at-least-once delivery.
|
||||
|
||||
If a worker crashes or is stopped gracefully the unconfirmed messages will be redelivered to other workers.
|
||||
In that case some of these may already have been processed by the previous worker. Meaning at-least once delivery.
|
||||
In that case some of these may already have been processed by the previous worker. Meaning at-least-once delivery.
|
||||
|
||||
## Sharding
|
||||
|
||||
|
|
@ -328,13 +329,13 @@ Java
|
|||
### Sharding delivery semantics
|
||||
|
||||
As long as neither producer nor consumer crash the messages are delivered to the consumer actor in the same order
|
||||
as they were sent to the `ShardingProducerController`, without loss or duplicates. Meaning effectively once
|
||||
as they were sent to the `ShardingProducerController`, without loss or duplicates. Meaning effectively-once
|
||||
processing without any business level deduplication.
|
||||
|
||||
Unconfirmed messages may be lost if the producer crashes. To avoid that you need to enable the @ref:[durable
|
||||
queue](#durable-producer) on the producer side. The stored unconfirmed messages will be redelivered when the
|
||||
corresponding producer is started again. In that case there may be delivery of messages that had already been
|
||||
processed but the fact that they were confirmed had not been stored yet. Meaning at-least once delivery.
|
||||
processed but the fact that they were confirmed had not been stored yet. Meaning at-least-once delivery.
|
||||
|
||||
If the consumer crashes or the shard is rebalanced the unconfirmed messages will be redelivered. In that case
|
||||
some of these may already have been processed by the previous consumer.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue