Draft 1 for week 1.
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
6753b43d41
commit
ecfa45c365
|
@ -1,14 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>10.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-documentation</artifactId>
|
||||
<name>Jetty :: Documentation</name>
|
||||
<packaging>pom</packaging>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
|
||||
<html.common.directory>${project.build.directory}/html/common</html.common.directory>
|
||||
|
@ -25,6 +27,15 @@
|
|||
<html.directory>${project.build.directory}/current</html.directory>
|
||||
<javadoc.version>${project.version}</javadoc.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -81,7 +92,6 @@
|
|||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<version>${asciidoctor.maven.plugin.version}</version>
|
||||
<configuration>
|
||||
<basedir>${basedir}/src/main/asciidoc</basedir>
|
||||
<attributes>
|
||||
<JDURL>http://www.eclipse.org/jetty/javadoc/${javadoc.version}</JDURL>
|
||||
<JXURL>http://download.eclipse.org/jetty/stable-9/xref</JXURL>
|
||||
|
@ -95,10 +105,11 @@
|
|||
<MVNCENTRAL>http://central.maven.org/maven2</MVNCENTRAL>
|
||||
<VERSION>${project.version}</VERSION>
|
||||
<TIMESTAMP>${maven.build.timestamp}</TIMESTAMP>
|
||||
<docbits>${basedir}/src/main/java</docbits>
|
||||
</attributes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<execution>
|
||||
<id>quickstart-guide</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
|
@ -142,7 +153,7 @@
|
|||
</execution>
|
||||
<execution>
|
||||
<id>embedded-guide</id>
|
||||
<phase>generate-resources</phase>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>process-asciidoc</goal>
|
||||
</goals>
|
||||
|
@ -176,6 +187,7 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>alt-formats</id>
|
||||
|
@ -208,9 +220,8 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<imagesdir/>
|
||||
<imagesdir />
|
||||
<backend>docbook</backend>
|
||||
<basedir>${basedir}/src/main/asciidoc</basedir>
|
||||
<attributes>
|
||||
<revnumber>${project.version}</revnumber>
|
||||
<JDURL>http://www.eclipse.org/jetty/javadoc/${javadoc.version}</JDURL>
|
||||
|
@ -233,9 +244,9 @@
|
|||
<sourceHighlighter>coderay</sourceHighlighter>
|
||||
<attributes>
|
||||
<icons>font</icons>
|
||||
<pagenums/>
|
||||
<toc/>
|
||||
<idprefix/>
|
||||
<pagenums />
|
||||
<toc />
|
||||
<idprefix />
|
||||
<idseparator>-</idseparator>
|
||||
</attributes>
|
||||
<sourceDirectory>${basedir}/src/main/asciidoc/contribution-guide</sourceDirectory>
|
||||
|
@ -254,9 +265,9 @@
|
|||
<sourceHighlighter>coderay</sourceHighlighter>
|
||||
<attributes>
|
||||
<icons>font</icons>
|
||||
<pagenums/>
|
||||
<toc/>
|
||||
<idprefix/>
|
||||
<pagenums />
|
||||
<toc />
|
||||
<idprefix />
|
||||
<idseparator>-</idseparator>
|
||||
</attributes>
|
||||
<sourceDirectory>${basedir}/src/main/asciidoc/quickstart-distribution-guide</sourceDirectory>
|
||||
|
@ -284,4 +295,5 @@
|
|||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[client-concepts]]
|
||||
=== Client Libraries Concepts
|
||||
|
||||
The Jetty client libraries implement a network client speaking different protocols
|
||||
such as HTTP/1.1, HTTP/2, WebSocket and FastCGI.
|
||||
|
||||
It is possible to implement your own custom protocol on top of the Jetty client
|
||||
libraries (TODO: perhaps add a section about this).
|
||||
|
||||
There are conceptually three layers that compose the Jetty client libraries, from
|
||||
more abstract to more concrete:
|
||||
|
||||
. The API layer, that exposes semantic APIs to application so that they can write
|
||||
code such as "GET me the resource at this URI"
|
||||
. The protocol layer, where the API request is converted into the appropriate
|
||||
protocol bytes, for example encrypted HTTP/2
|
||||
. The infrastructure layer, that handles the low level I/O and deals with network,
|
||||
buffer, threads, etc.
|
||||
|
||||
[[client-concepts-infrastructure]]
|
||||
==== Client Libraries Infrastructure Layer
|
||||
|
||||
The Jetty client libraries reuse the same components also used on the server-side
|
||||
to handle the low-level network, the thread pooling, the scheduler, etc.
|
||||
The main client-side component is the
|
||||
link:{JDURL}/org/eclipse/jetty/io/ClientConnector.html[`ClientConnector`].
|
||||
|
||||
The `ClientConnector` primarily wraps the
|
||||
link:{JDURL}/org/eclipse/jetty/io/SelectorManager.html[`SelectorManager`]
|
||||
and aggregates other four components: the thread pool (in form of an `Executor`),
|
||||
the `Scheduler`, the `ByteBufferPool` and the `SslContextFactory.Client`.
|
||||
|
||||
The `ClientConnector` is where you want to set those five components after you
|
||||
have configured them.
|
||||
If you don't explicitly set those five components on the `ClientConnector`, then
|
||||
appropriate defaults will be chosen.
|
||||
|
||||
The simplest example that creates and start a `ClientConnector`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{docbits}/embedded/client/EmbeddedClientConnector.java[tags=simplest]
|
||||
----
|
||||
|
||||
A more typical example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{docbits}/embedded/client/EmbeddedClientConnector.java[tags=typical]
|
||||
----
|
||||
|
||||
A more advanced example that customizes the `ClientConnector` by overriding
|
||||
factory methods:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{docbits}/embedded/client/EmbeddedClientConnector.java[tags=advanced]
|
||||
----
|
||||
|
||||
Since `ClientConnector` is the component that handles the low-level network, it
|
||||
is also the component where you want to configure the parameters that control
|
||||
how it should handle the low-level network.
|
||||
|
||||
The most common parameters are:
|
||||
|
||||
* `ClientConnector.selectors`: the number of ``java.nio.Selector``s components
|
||||
(defaults to `1`) that are present to handle the ``SocketChannel``s opened by
|
||||
the `ClientConnector`. You typically want to increase the number of selectors
|
||||
only for those use cases where each selector should handle more than few hundreds
|
||||
_concurrent_ socket events.
|
||||
For example, one selector typically runs well for `250` _concurrent_ socket
|
||||
events; as a rule of thumb, you can multiply that number by `10` to obtain the
|
||||
number of opened sockets a selector can handle (`2500`), based on the assumption
|
||||
that not all the `2500` sockets will be active _at the same time_.
|
||||
* `ClientConnector.idleTimeout`: the duration of time after which
|
||||
`ClientConnector` closes a socket due to inactivity (defaults to `30` seconds).
|
||||
This is an important parameter to configure, and you typically want the client
|
||||
idle timeout to be shorter than the server idle timeout, to avoid race
|
||||
conditions where the client attempts to use a socket just before the idle
|
||||
timeout expires, but the server is already closing it.
|
||||
* `ClientConnector.connectBlocking`: whether the operation of connecting a
|
||||
socket to the server (i.e. `SocketChannel.connect(SocketAddress)`) must be a
|
||||
blocking or a non-blocking operation (defaults to `false`).
|
||||
For `localhost` or same datacenter hosts you want to set this parameter to
|
||||
`true` because DNS resolution will be immediate (and likely never fail).
|
||||
For generic Internet hosts (e.g. when you are implementing a web spider) you
|
||||
want to set this parameter to `false`.
|
||||
* `ClientConnector.connectTimeout`: the duration of time after which
|
||||
`ClientConnector` aborts a connection attempt to the server (defaults to `5`
|
||||
seconds).
|
||||
This time includes the DNS lookup time _and_ the TCP connect time.
|
||||
|
||||
Please refer to the `ClientConnector`
|
||||
link:{JDURL}/org/eclipse/jetty/io/ClientConnector.html[javadocs]
|
||||
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`?
|
||||
|
||||
When establishing a TCP connection to a server, applications need to tell
|
||||
`ClientConnector` how to create the `Connection` for that particular
|
||||
TCP connection.
|
||||
This is done via a
|
||||
link:{JDURL}/org/eclipse/jetty/io/ClientConnectionFactory.html[`ClientConnectionFactory`].
|
||||
that must be passed in the context `Map` as follows:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::{docbits}/embedded/client/EmbeddedClientConnector.java[tags=connect]
|
||||
----
|
||||
|
||||
|
||||
TODO: expand on what is the API to use, what parameters the context Map must
|
||||
have, and basically how we can write a generic network client with it.
|
||||
|
||||
[[client-concepts-protocol]]
|
||||
==== Client Libraries Protocol Layer
|
||||
|
||||
The protocol layer builds on top of the infrastructure layer to generate the
|
||||
bytes to be written to the network and to parse the bytes received from the
|
||||
network.
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[client]]
|
||||
== Jetty Client Libraries
|
||||
|
||||
The Eclipse Jetty Project provides not only server-side libraries so that you
|
||||
can embed a server in your code, but it also provides client-side libraries
|
||||
that allow you to embed a client - for example a HTTP client invoking a third
|
||||
party HTTP service - in your application.
|
||||
|
||||
The client libraries are designed to be non-blocking and offer both synchronous
|
||||
and asynchronous APIs and come with a large number of configuration options.
|
||||
|
||||
There are primarily two client libraries:
|
||||
|
||||
* link:#client-http[The HTTP client library]
|
||||
* link:#client-websocket[The WebSocket client library]
|
||||
|
||||
include::client-concepts.adoc[]
|
|
@ -59,6 +59,7 @@ endif::[]
|
|||
// suppress automatic id generation
|
||||
:sectids!:
|
||||
|
||||
include::client/client.adoc[]
|
||||
include::embedding/chapter.adoc[]
|
||||
include::maven/chapter.adoc[]
|
||||
include::clients/http/chapter.adoc[]
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
package embedded.client;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.SelectorManager;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
import static java.lang.System.Logger.Level.INFO;
|
||||
|
||||
public class EmbeddedClientConnector
|
||||
{
|
||||
public void simplest() throws Exception
|
||||
{
|
||||
// tag::simplest[]
|
||||
ClientConnector clientConnector = new ClientConnector();
|
||||
clientConnector.start();
|
||||
// end::simplest[]
|
||||
}
|
||||
|
||||
public void typical() throws Exception
|
||||
{
|
||||
// tag::typical[]
|
||||
// Create and configure the SslContextFactory.
|
||||
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
|
||||
sslContextFactory.addExcludeProtocols("TLSv1", "TLSv1.1");
|
||||
|
||||
// Create and configure the thread pool.
|
||||
QueuedThreadPool threadPool = new QueuedThreadPool();
|
||||
threadPool.setName("client");
|
||||
|
||||
// Create and configure the ClientConnector.
|
||||
ClientConnector clientConnector = new ClientConnector();
|
||||
clientConnector.setSslContextFactory(sslContextFactory);
|
||||
clientConnector.setExecutor(threadPool);
|
||||
clientConnector.start();
|
||||
// end::typical[]
|
||||
}
|
||||
|
||||
public void advanced() throws Exception
|
||||
{
|
||||
// tag::advanced[]
|
||||
class CustomClientConnector extends ClientConnector
|
||||
{
|
||||
@Override
|
||||
protected SelectorManager newSelectorManager()
|
||||
{
|
||||
return new ClientSelectorManager(getExecutor(), getScheduler(), getSelectors())
|
||||
{
|
||||
@Override
|
||||
protected void endPointOpened(EndPoint endpoint)
|
||||
{
|
||||
System.getLogger("endpoint").log(INFO, "opened %s", endpoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void endPointClosed(EndPoint endpoint)
|
||||
{
|
||||
System.getLogger("endpoint").log(INFO, "closed %s", endpoint);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Create and configure the thread pool.
|
||||
QueuedThreadPool threadPool = new QueuedThreadPool();
|
||||
threadPool.setName("client");
|
||||
|
||||
// Create and configure the scheduler.
|
||||
Scheduler scheduler = new ScheduledExecutorScheduler("scheduler-client", false);
|
||||
|
||||
// Create and configure the custom ClientConnector.
|
||||
CustomClientConnector clientConnector = new CustomClientConnector();
|
||||
clientConnector.setExecutor(threadPool);
|
||||
clientConnector.setScheduler(scheduler);
|
||||
clientConnector.start();
|
||||
// end::advanced[]
|
||||
}
|
||||
|
||||
public void connect() throws Exception
|
||||
{
|
||||
class CustomHTTPConnection extends AbstractConnection
|
||||
{
|
||||
public CustomHTTPConnection(EndPoint endPoint, Executor executor)
|
||||
{
|
||||
super(endPoint, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen()
|
||||
{
|
||||
super.onOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFillable()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
ClientConnector clientConnector = new ClientConnector();
|
||||
clientConnector.start();
|
||||
|
||||
String host = "wikipedia.org";
|
||||
int port = 80;
|
||||
SocketAddress address = new InetSocketAddress(host, port);
|
||||
|
||||
ClientConnectionFactory connectionFactory = (endPoint, context) ->
|
||||
{
|
||||
System.getLogger("connection").log(INFO, "Creating connection for {0}", endPoint);
|
||||
return new CustomHTTPConnection(endPoint, clientConnector.getExecutor());
|
||||
};
|
||||
Map<String, Object> context = new HashMap<>();
|
||||
context.put(ClientConnector.CLIENT_CONNECTION_FACTORY_CONTEXT_KEY, connectionFactory);
|
||||
clientConnector.connect(address, context);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
new EmbeddedClientConnector().connect();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue