Draft 3 for week 1.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
Simone Bordet 2019-07-31 21:17:55 +02:00
parent f342faa444
commit b5a15f18f6
4 changed files with 169 additions and 42 deletions

View File

@ -115,48 +115,9 @@ for the complete list of configurable parameters.
Once the `ClientConnector` is configured and started, it can be used to connect
to the server via `ClientConnector.connect(SocketAddress, Map<String, Object>)`
which in turn will call `SocketChannel.connect(SocketAddress)`.
`ClientConnector` wraps the `SocketChannel` connected to the server with two
related components:
an link:{JDURL}/org/eclipse/jetty/io/EndPoint.html[`EndPoint`] and a
link:{JDURL}/org/eclipse/jetty/io/Connection.html[`Connection`].
`EndPoint` is the Jetty abstraction for a `SocketChannel`: you can read bytes
from an `EndPoint` via `EndPoint.fill(ByteBuffer)`, you can write bytes to an
`EndPoint` via `EndPoint.flush(ByteBuffer...)` and
`EndPoint.write(Callback, ByteBuffer...)`, you can close an `EndPoint` via
`EndPoint.close()`, etc.
There is primarily one implementation of `EndPoint`:
link:{JDURL}/org/eclipse/jetty/io/SocketChannelEndPoint.html[`SocketChannelEndPoint`].
`Connection` is the Jetty abstraction that is responsible to serialize objects
to bytes and then writing the serialized bytes to the `EndPoint`, as well as
deserializing bytes read from the `EndPoint` into objects.
For example, a HTTP/1.1 `Connection` implementation is responsible to serialize
a HTTP request object into its correspondent HTTP/1.1 request bytes, and to
deserialize HTTP/1.1 response bytes into a response object that can be used by
applications.
`Connection` is the abstraction that "speaks" a specific protocol such as
HTTP/1.1, or HTTP/2, or WebSocket: it is able to read incoming communication
as well as write outgoing communication in that protocol.
There are many implementation of `Connection`, typically one for each protocol
that the Jetty client libraries can speak.
``Connection``s can be nested, for example in case of encrypted communication
using the TLS protocol: the outermost TLS `Connection` performs the decryption
and encryption, and the innermost protocol `Connection` serializes the
decrypted bytes into objects and deserializes objects into bytes to be encrypted.
Certain protocols, such as WebSocket, start with the communication with the
server using one protocol (e.g. HTTP/1.1), but then change the communication
to use another protocol (e.g. WebSocket).
`EndPoint` supports changing the `Connection` object on-the-fly so that the
HTTP/1.1 `Connection` can be used during the initial communication and later
be replaced by a WebSocket `Connection`.
TODO: add a section on `UpgradeFrom` and `UpgradeTo`?
// TODO: from down here, moved to io-arch.adoc
When establishing a TCP connection to a server, applications need to tell
`ClientConnector` how to create the `Connection` for that particular

View File

@ -20,3 +20,108 @@
[[io-arch]]
== Jetty I/O Architecture
Jetty libraries (both client and server) use Java NIO to handle I/O, so that
at its core Jetty I/O is completely non-blocking.
The core class of Jetty I/O is
link:{JDURL}/org/eclipse/jetty/io/SelectorManager.html[`SelectorManager`].
`SelectorManager` manages internally a configurable number of
link:{JDURL}/org/eclipse/jetty/io/ManagedSelector.html[`ManagedSelector`]s.
Each `ManagedSelector` wraps an instance of `java.nio.channels.Selector` that
in turn manages a number of `java.nio.channels.SocketChannel` instances.
NOTE: TODO: add image
`SocketChannel` instances can be created by clients when connecting to a server
and by a server when accepting connections from client.
In both cases the `SocketChannel` instance is passed to `SelectorManager` to be
registered for use within Jetty.
It is therefore possible to create the `SocketChannel` instances outside Jetty,
even perform some initial network traffic also outside Jetty (for example for
authentication purposes), and then pass the `SocketChannel` instance to
`SelectorManager` for use within Jetty.
This example shows how to connect to a server:
[source,java,indent=0]
----
include::{docbits}/embedded/SelectorManagerDocSnippets.java[tags=connect]
----
This example shows how to accept a client connection:
[source,java,indent=0]
----
include::{docbits}/embedded/SelectorManagerDocSnippets.java[tags=accept]
----
``SocketChannel``s that are passed to `SelectorManager` are wrapped into two
related components:
an link:{JDURL}/org/eclipse/jetty/io/EndPoint.html[`EndPoint`] and a
link:{JDURL}/org/eclipse/jetty/io/Connection.html[`Connection`].
`EndPoint` is the Jetty abstraction for a `SocketChannel`: you can read bytes
from an `EndPoint` via `EndPoint.fill(ByteBuffer)`, you can write bytes to an
`EndPoint` via `EndPoint.flush(ByteBuffer...)` and
`EndPoint.write(Callback, ByteBuffer...)`, you can close an `EndPoint` via
`EndPoint.close()`, etc.
`Connection` is the Jetty abstraction that is responsible to serialize objects
to bytes and then writing the serialized bytes to the `EndPoint`, as well as
deserializing bytes read from the `EndPoint` into objects.
For example, a HTTP/1.1 client-side `Connection` implementation is responsible
to serialize a HTTP request object into its correspondent HTTP/1.1 request bytes,
and to deserialize HTTP/1.1 response bytes into a HTTP response object.
Conversely, a HTTP/1.1 server-side `Connection` implementation is responsible
to deserialize HTTP/1.1 request bytes into a HTTP request object and to serialize
a HTTP response object into its correspondent HTTP/1.1 response bytes.
`Connection` is the abstraction that "speaks" a specific protocol such as
HTTP/1.1, or HTTP/2, or WebSocket: it is able to read incoming communication
as well as write outgoing communication in that protocol.
While there is primarily just one implementation of `EndPoint`:
link:{JDURL}/org/eclipse/jetty/io/SocketChannelEndPoint.html[`SocketChannelEndPoint`]
(used both on the client-side and on the server-side), there are many
implementations of `Connection`, typically two for each protocol(one for the
client-side and one for the server-side).
``Connection``s can be nested, for example in case of encrypted communication
using the TLS protocol: the outermost TLS `Connection` performs the decryption
and encryption, and the innermost protocol `Connection` serializes the
decrypted bytes into objects and deserializes objects into bytes to be encrypted.
Certain protocols, such as WebSocket, start the communication with the server
using one protocol (e.g. HTTP/1.1), but then change the communication to use
another protocol (e.g. WebSocket).
`EndPoint` supports changing the `Connection` object on-the-fly via
`EndPoint.upgrade(Connection)`.
This allows to use the HTTP/1.1 `Connection` during the initial communication
and later replace it with a WebSocket `Connection`.
NOTE: TODO: add a section on `UpgradeFrom` and `UpgradeTo`?
`SelectorManager` is an abstract class because while it knows how to create
concrete `EndPoint` instances, it does not know how to create protocol
specific `Connection` instances.
Creating `Connection` instances is performed on the server-side by
link:{JDURL}/org/eclipse/jetty/server/ConnectionFactory.html[`ConnectionFactory`]s.
and on the client-side by
link:{JDURL}/org/eclipse/jetty/io/ClientConnectionFactory.html[`ClientConnectionFactory`]s
On the server-side, the component that aggregates a `SelectorManager` with a
set of ``ConnectionFactory``s is
link:{JDURL}/org/eclipse/jetty/server/ServerConnector.html[`ServerConnector`]s.
NOTE: TODO: add a link to a server-side specific architecture section
On the client-side, the components that aggregates a `SelectorManager` with a
set of ``ClientConnectionFactory``s are
link:{JDURL}/org/eclipse/jetty/client/HttpClientTransport.html[`HttpClientTransport`]
subclasses.
NOTE: TODO: add a link to a client-side specific architecture section

View File

@ -36,7 +36,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
import static java.lang.System.Logger.Level.INFO;
public class EmbeddedClientConnector
public class ClientConnectorDocSnippets
{
public void simplest() throws Exception
{
@ -145,6 +145,6 @@ public class EmbeddedClientConnector
public static void main(String[] args) throws Exception
{
new EmbeddedClientConnector().connect();
new ClientConnectorDocSnippets().connect();
}
}

View File

@ -0,0 +1,61 @@
//
// ========================================================================
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package embedded.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Map;
import org.eclipse.jetty.io.SelectorManager;
public class SelectorManagerDocSnippets
{
// tag::connect[]
public void connect(SelectorManager selectorManager, Map<String, Object> context) throws IOException
{
String host = "host";
int port = 8080;
// Create an unconnected SocketChannel.
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
// Connect and register to Jetty.
if (socketChannel.connect(new InetSocketAddress(host, port)))
selectorManager.accept(socketChannel, context);
else
selectorManager.connect(socketChannel, context);
}
// end::connect[]
// tag::accept[]
public void accept(ServerSocketChannel acceptor, SelectorManager selectorManager) throws IOException
{
// Wait until a client connects.
SocketChannel socketChannel = acceptor.accept();
socketChannel.configureBlocking(false);
// Accept and register to Jetty.
Object attachment = null;
selectorManager.accept(socketChannel, attachment);
}
// end::accept[]
}