add BackpressureBuffer, see #3253
- also make a Write’s “ack” be a Tcp.Event (to suit pipelines) - add stress test for BackpressureBuffer - add it to SslTlsSupportSpec - add it to the docs
This commit is contained in:
parent
025a91ecc2
commit
ea5b79e562
15 changed files with 764 additions and 248 deletions
|
|
@ -563,7 +563,7 @@ resending of all queued data:
|
|||
It should be noted that all writes which are currently buffered have also been
|
||||
sent to the connection actor upon entering this state, which means that the
|
||||
:class:`ResumeWriting` message is enqueued after those writes, leading to the
|
||||
reception of all outstanding :class:`CommandFailre` messages (which are ignored
|
||||
reception of all outstanding :class:`CommandFailed` messages (which are ignored
|
||||
in this state) before receiving the :class:`WritingResumed` signal. That latter
|
||||
message is sent by the connection actor only once the internally queued write
|
||||
has been fully completed, meaning that a subsequent write will not fail. This
|
||||
|
|
@ -590,36 +590,55 @@ first look at the SSL server:
|
|||
|
||||
.. includecode:: code/docs/io/japi/SslDocTest.java#server
|
||||
|
||||
Please refer to `the source code`_ to see all imports.
|
||||
|
||||
.. _the source code: @github@/akka-docs/rst/java/code/docs/io/japi/SslDocTest.java
|
||||
|
||||
The actor above binds to a local port and registers itself as the handler for
|
||||
new connections. When a new connection comes in it will create a
|
||||
:class:`javax.net.ssl.SSLEngine` (details not shown here since they vary wildly
|
||||
:class:`javax.net.ssl.SSLEngine` (details not shown here since they vary widely
|
||||
for different setups, please refer to the JDK documentation) and wrap that in
|
||||
an :class:`SslTlsSupport` pipeline stage (which is included in ``akka-actor``).
|
||||
This single-stage pipeline will be driven by a :class:`TcpPipelineHandler`
|
||||
actor which is also included in ``akka-actor``. In order to capture the generic
|
||||
command and event types consumed and emitted by that actor we need to create a
|
||||
wrapper—the nested :class:`Init` class—which also provides the
|
||||
:meth:`makeContext` method for creating the pipeline context needed by the
|
||||
supplied pipeline. With those things bundled up all that remains is creating a
|
||||
|
||||
This sample demonstrates a few more things: below the SSL pipeline stage we
|
||||
have inserted a backpressure buffer which will generate a
|
||||
:class:`HighWatermarkReached` event to tell the upper stages to suspend writing
|
||||
(generated at 10000 buffered bytes) and a :class:`LowWatermarkReached` when
|
||||
they can resume writing (when buffer empties below 1000 bytes); the buffer has
|
||||
a maximum capacity of 1MB. The implementation is very similar to the NACK-based
|
||||
backpressure approach presented above. Above the SSL stage comes an adapter
|
||||
which extracts only the payload data from the TCP commands and events, i.e. it
|
||||
speaks :class:`ByteString` above. The resulting byte streams are broken into
|
||||
frames by a :class:`DelimiterFraming` stage which chops them up on newline
|
||||
characters. The top-most stage then converts between :class:`String` and UTF-8
|
||||
encoded :class:`ByteString`.
|
||||
|
||||
As a result the pipeline will accept simple :class:`String` commands, encode
|
||||
them using UTF-8, delimit them with newlines (which are expected to be already
|
||||
present in the sending direction), transform them into TCP commands and events,
|
||||
encrypt them and send them off to the connection actor while buffering writes.
|
||||
|
||||
This pipeline is driven by a :class:`TcpPipelineHandler` actor which is also
|
||||
included in ``akka-actor``. In order to capture the generic command and event
|
||||
types consumed and emitted by that actor we need to create a wrapper—the nested
|
||||
:class:`Init` class—which also provides the the pipeline context needed by the
|
||||
supplied pipeline; in this case we use the :meth:`withLogger` convenience
|
||||
method which supplies a context that implements :class:`HasLogger` and
|
||||
:class:`HasActorContext` and should be sufficient for typical pipelines. With
|
||||
those things bundled up all that remains is creating a
|
||||
:class:`TcpPipelineHandler` and registering that one as the recipient of
|
||||
inbound traffic from the TCP connection.
|
||||
|
||||
Since we instructed that handler actor to send any events which are emitted by
|
||||
the SSL pipeline to ourselves, we can then just wait for the reception of the
|
||||
decrypted payload messages, compute a response—just ``"world"`` in this
|
||||
case—and reply by sending back a ``Tcp.Write``. It should be noted that
|
||||
decrypted payload messages, compute a response—just ``"world\n"`` in this
|
||||
case—and reply by sending back an ``Init.Command``. It should be noted that
|
||||
communication with the handler wraps commands and events in the inner types of
|
||||
the ``init`` object in order to keep things well separated. To ease handling of
|
||||
such path-dependent types there exist two helper methods, namely
|
||||
:class:`Init.command` for creating a command and :class:`Init.event` for
|
||||
unwrapping an event.
|
||||
|
||||
.. warning::
|
||||
|
||||
The :class:`TcpPipelineHandler` does currently not handle back-pressure from
|
||||
the TCP socket, i.e. it will just lose data when the kernel buffer
|
||||
overflows. This will be fixed before Akka 2.2 final.
|
||||
|
||||
Looking at the client side we see that not much needs to be changed:
|
||||
|
||||
.. includecode:: code/docs/io/japi/SslDocTest.java#client
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue