Skip to content

Commit

Permalink
Improvements to the Jetty server documentation.
Browse files Browse the repository at this point in the history
Added section on troubleshooting.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
  • Loading branch information
sbordet committed Apr 22, 2020
1 parent 13094fa commit 1d96dda
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,4 @@ include::.asciidoctorconfig[]
include::client/client.adoc[]
include::server/server.adoc[]
include::arch.adoc[]
include::troubleshooting.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Writing HTTP applications is typically simple, especially when using blocking AP
However, there are subtle cases where it is worth clarifying what a server application should do to obtain the desired results when run by Jetty.

[[eg-server-http-application-1xx]]
==== Managing 1xx Responses
==== Sending 1xx Responses

The link:https://tools.ietf.org/html/rfc7231#section-5.1.1[HTTP/1.1 RFC] allows for `1xx` informational responses to be sent before a real content response.
Unfortunately the servlet specification does not provide a way for these to be sent, so Jetty has had to provide non-standard handling of these headers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@

A `Connector` is the component that handles incoming requests from clients, and works in conjunction with `ConnectionFactory` instances.

The primary implementation is `org.eclipse.jetty.server.ServerConnector`.`ServerConnector` uses a `java.nio.channels.ServerSocketChannel` to listen to a TCP port and to accept TCP connections.
The primary implementation is `org.eclipse.jetty.server.ServerConnector`.
`ServerConnector` uses a `java.nio.channels.ServerSocketChannel` to listen to a TCP port and to accept TCP connections.

Since `ServerConnector` wraps a `ServerSocketChannel`, it can be configured in a similar way, for example the port to listen to, the network address to bind to, etc.:

Expand All @@ -32,18 +33,18 @@ include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=configur

The _acceptors_ are threads (typically only one) that compete to accept TCP connections on the listening port.
When a connection is accepted, `ServerConnector` wraps the accepted `SocketChannel` and passes it to the xref:eg-arch-io-selector-manager[`SelectorManager`].
Therefore, there is a little moment where the acceptor thread is not accepting new connections because it is busy wrapping the just accepted one to pass it to the `SelectorManager`.
Therefore, there is a little moment where the acceptor thread is not accepting new connections because it is busy wrapping the just accepted connection to pass it to the `SelectorManager`.
Connections that are ready to be accepted but are not accepted yet are queued in a bounded queue (at the OS level) whose capacity can be configured with the `ServerConnector.acceptQueueSize` parameter.

If your application must withstand a very high rate of connections opened, configuring more than one acceptor thread may be beneficial: when one acceptor thread accepts one connection, another acceptor thread can take over accepting connections.

The _selectors_ are components that manage a set of connected sockets, implemented by xref:eg-arch-io-selector-manager[`ManagedSelector`].
Each selector requires one thread and uses the Java NIO mechanism to efficiently handle the set of connected sockets.
Each selector requires one thread and uses the Java NIO mechanism to efficiently handle a set of connected sockets.
As a rule of thumb, a single selector can easily manage up to 1000-5000 sockets, although the number may vary greatly depending on the application.

For example, web site applications tend to use sockets for one or more HTTP requests to retrieve resources and then the socket is idle for most of the time.
In this case a single selector may be able to manage many sockets because chances are that they will be idle most of the time.
On the contrary, web messaging applications tend to send many small messages at a very high frequency so that the socket is rarely idle.
On the contrary, web messaging applications tend to send many small messages at a very high frequency so that sockets are rarely idle.
In this case a single selector may be able to manage less sockets because chances are that many of them will be active at the same time.

It is possible to configure more than one `ServerConnector`, each listening on a different port:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,19 @@ A client making a request to `+https://shop.domain.com/cart+` is directed by Jet
Therefore, in general, a web application is deployed to a _context_ which can be seen as the pair `(virtual_host, context_path)`.
In the first case the contexts were `(domain.com, /shop)` and `(domain.com, /api)`, while in the second case the contexts were `(shop.domain.com, /)` and `(api.domain.com, /)`.
Server applications using the Jetty Server Libraries create and configure a _context_ for each web application.
Many __context__s can be deployed together to enrich the web application offering -- for example a catalog context, a shop context, an API context, an administration context, etc.

[[eg-server-http-handler-use-context]]
Web applications can be written using exclusively the Servlet APIs, since developers know well the Servlet API and because they guarantee better portability across Servlet container implementations.

Embedded web applications based on the Servlet APIs are described in xref:eg-server-http-handler-use-servlet[this section].

Embedded web applications may also require additional features such as access to Jetty specific APIs, or utility features such as redirection from HTTP to HTTPS, support for `gzip` content compression, etc.
The Jetty Server Libraries provides a number of out-of-the-box __Handler__s that implement the most common functionalities and are described in xref:eg-server-http-handler-use-util[this section].

[[eg-server-http-handler-use-util]]
==== Custom and Utility Handlers

[[eg-server-http-handler-use-util-context]]
===== ContextHandler

`ContextHandler` is a `Handler` that represents a _context_ for a web application.
Expand All @@ -62,7 +73,7 @@ Server
└── ShopHandler
----

[[eg-server-http-handler-use-context-collection]]
[[eg-server-http-handler-use-util-context-collection]]
===== ContextHandlerCollection

Server applications may need to deploy to Jetty more than one web application.
Expand Down Expand Up @@ -93,63 +104,7 @@ Server
└── RESTHandler
----

[[eg-server-http-handler-use-servlet-context]]
===== ServletContextHandler

``Handler``s are easy to write, but often web applications have already been written using the Servlet APIs, using ``Servlet``s and ``Filter``s.

`ServletContextHandler` is a `ContextHandler` that provides support for the Servlet APIs and implements the behaviors required by the Servlet specification.

The Maven artifact coordinates are:

[source,xml,subs=normal]
----
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>{version}</version>
</dependency>
----

[source,java,indent=0]
----
include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=servletContextHandler]
----

The `Handler` and Servlet components tree structure looks like the following:

[source,screen,subs=normal]
----
Server
└── ServletContextHandler /shop
├── _ShopCartServlet /cart/*_
└── _CrossOriginFilter /*_
----

Note how the Servlet components (they are not ``Handler``s) are represented in _italic_.

Note also how adding a `Servlet` or a `Filter` returns a _holder_ object that can be used to specify additional configuration for that particular `Servlet` or `Filter`.

When a request arrives to `ServletContextHandler` the request URI will be matched against the ``Filter``s and ``Servlet`` mappings and only those that match will process the request, as dictated by the Servlet specification.

IMPORTANT: `ServletContextHandler` is a terminal `Handler`, that is it always calls `Request.setHandled(true)` when invoked.
Server applications must be careful when creating the `Handler` tree to put ``ServletContextHandler``s as last ``Handler``s in a `HandlerList` or as children of `ContextHandlerCollection`.

[[eg-server-http-handler-use-webapp-context]]
===== WebAppContext

`WebAppContext` is a `ServletContextHandler` that auto configures itself by reading a `web.xml` Servlet configuration file.

Server applications can specify a `+*.war+` file or a directory with the structure of a `+*.war+` file to `WebAppContext` to deploy a standard Servlet web application packaged as a `war` (as defined by the Servlet specification).

Where server applications using `ServletContextHandler` must manually invoke methods to add ``Servlet``s and ``Filter``s, `WebAppContext` reads `WEB-INF/web.xml` to add ``Servlet``s and ``Filter``s.

[source,java,indent=0]
----
include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=webAppContextHandler]
----

[[eg-server-http-handler-use-resource-handler]]
[[eg-server-http-handler-use-util-resource-handler]]
===== ResourceHandler -- Static Content

Static content such as images or files (HTML, JavaScript, CSS) can be sent by Jetty very efficiently because Jetty can write the content asynchronously, using direct ``ByteBuffer``s to minimize data copy, and using a memory cache for faster access to the data to send.
Expand Down Expand Up @@ -188,17 +143,6 @@ include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=multiple
If the resource is not found, `ResourceHandler` will not call `Request.setHandled(true)` so what happens next depends on the `Handler` tree structure.
See also xref:eg-server-http-handler-use-util-default-handler[how to use] `DefaultHandler`.

[[eg-server-http-handler-use-default-servlet]]
===== DefaultServlet -- Static Content for Servlets

If you have a xref:eg-server-http-handler-use-servlet-context[Servlet web application], you may want to use a `DefaultServlet` instead of `ResourceHandler`.
The features are similar, but `DefaultServlet` is more commonly used to serve static files for Servlet web applications.

[source,java,indent=0]
----
include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=defaultServlet]
----

[[eg-server-http-handler-use-util-gzip-handler]]
===== GzipHandler

Expand Down Expand Up @@ -372,3 +316,77 @@ In the example above, `ContextHandlerCollection` will try to match a request to

NOTE: `DefaultHandler` just sends a nicer HTTP `404` response in case of wrong requests from clients.
Jetty will send an HTTP `404` response anyway if `DefaultHandler` is not used.

[[eg-server-http-handler-use-servlet]]
==== Servlet API Handlers

[[eg-server-http-handler-use-servlet-context]]
===== ServletContextHandler

``Handler``s are easy to write, but often web applications have already been written using the Servlet APIs, using ``Servlet``s and ``Filter``s.

`ServletContextHandler` is a `ContextHandler` that provides support for the Servlet APIs and implements the behaviors required by the Servlet specification.

The Maven artifact coordinates are:

[source,xml,subs=normal]
----
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>{version}</version>
</dependency>
----

[source,java,indent=0]
----
include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=servletContextHandler]
----

The `Handler` and Servlet components tree structure looks like the following:

[source,screen,subs=normal]
----
Server
└── ServletContextHandler /shop
├── _ShopCartServlet /cart/*_
└── _CrossOriginFilter /*_
----

Note how the Servlet components (they are not ``Handler``s) are represented in _italic_.

Note also how adding a `Servlet` or a `Filter` returns a _holder_ object that can be used to specify additional configuration for that particular `Servlet` or `Filter`.

When a request arrives to `ServletContextHandler` the request URI will be matched against the ``Filter``s and ``Servlet`` mappings and only those that match will process the request, as dictated by the Servlet specification.

IMPORTANT: `ServletContextHandler` is a terminal `Handler`, that is it always calls `Request.setHandled(true)` when invoked.
Server applications must be careful when creating the `Handler` tree to put ``ServletContextHandler``s as last ``Handler``s in a `HandlerList` or as children of `ContextHandlerCollection`.

[[eg-server-http-handler-use-webapp-context]]
===== WebAppContext

`WebAppContext` is a `ServletContextHandler` that auto configures itself by reading a `web.xml` Servlet configuration file.

Server applications can specify a `+*.war+` file or a directory with the structure of a `+*.war+` file to `WebAppContext` to deploy a standard Servlet web application packaged as a `war` (as defined by the Servlet specification).

Where server applications using `ServletContextHandler` must manually invoke methods to add ``Servlet``s and ``Filter``s, `WebAppContext` reads `WEB-INF/web.xml` to add ``Servlet``s and ``Filter``s.

[source,java,indent=0]
----
include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=webAppContextHandler]
----

// TODO: add a section on Configuration (system/server classes)
// TODO: add a section about how to setup JSP support
// TODO: add a section on ClassLoading (see old docs)

[[eg-server-http-handler-use-default-servlet]]
===== DefaultServlet -- Static Content for Servlets

If you have a xref:eg-server-http-handler-use-servlet-context[Servlet web application], you may want to use a `DefaultServlet` instead of `ResourceHandler`.
The features are similar, but `DefaultServlet` is more commonly used to serve static files for Servlet web applications.

[source,java,indent=0]
----
include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=defaultServlet]
----
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,7 @@ However, in some cases the additional features are not required, or additional c
In these cases, implementing your own `Handler` may be a better solution.
Refer to xref:eg-server-http-handler-implement[this section] for more information about how to write your own ``Handler``s.

// TODO: document ScopedHandler? Is this really necessary or just an implementation detail that application will never worry about?

include::server-http-handler-use.adoc[]
include::server-http-handler-implement.adoc[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

[[eg-server-http-security]]
==== Securing HTTP Server Applications

// TODO: ConstraintSecurityHandler and Authenticators and LoginServices
TODO

Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=simple]

The example above shows the simplest HTTP/1.1 server; it has no support for HTTP sessions, for HTTP authentication, or for any of the features required by the Servlet specification.

All these features are provided by the Jetty Server Libraries and server applications only need to put the required components together to provide all the required features, and it is discussed in details in xref:eg-server-http-handler-use[this section].
All these features are provided by the Jetty Server Libraries, and server applications only need to put the required components together to provide all the required features.

The ``Handler``s provided by the Jetty Server Libraries allow writing server applications that have functionalities similar to Apache HTTPD or Nginx (for example: URL redirection, URL rewriting, serving static content, reverse proxying, etc.), as well as generating content dynamically by processing incoming requests.
Read xref:eg-server-http-handler[this section] for further details.

If you are interested in writing your server application based on the Servlet APIs, jump to xref:eg-server-http-handler-use-servlet[this section].

[[eg-server-http-request-processing]]
==== Server Request Processing
Expand All @@ -75,15 +80,6 @@ Request handing is slightly different for each protocol; in HTTP/2 Jetty takes i

However, the diagram below captures the essence of request handling that is common among all protocols that carry HTTP requests.

First, the Jetty I/O layer emits an event that a socket has data to read.
This event is converted to a call to `AbstractConnection.onFillable()`, where the `Connection` first reads from the `EndPoint` into a `ByteBuffer`, and then calls a protocol specific parser to parse the bytes in the `ByteBuffer`.

The parser emit events such that are protocol specific; the HTTP/2 parser, for example, emits events for each HTTP/2 frame that has been parsed.
The parser events are then converted to protocol independent events such as _"request start"_, _"request headers"_, _"request content chunk"_, etc.
that in turn are converted into method calls to `HttpChannel`.

When enough of the HTTP request is arrived, the `Connection` calls `HttpChannel.handle()` that calls the `Handler` chain, that eventually calls the server application code.

[plantuml]
----
skinparam backgroundColor transparent
Expand All @@ -109,6 +105,15 @@ HttpChannel -> Server : handle()
Server -> Handlers : handle()
----

First, the Jetty I/O layer emits an event that a socket has data to read.
This event is converted to a call to `AbstractConnection.onFillable()`, where the `Connection` first reads from the `EndPoint` into a `ByteBuffer`, and then calls a protocol specific parser to parse the bytes in the `ByteBuffer`.

The parser emit events that are protocol specific; the HTTP/2 parser, for example, emits events for each HTTP/2 frame that has been parsed.
The parser events are then converted to protocol independent events such as _"request start"_, _"request headers"_, _"request content chunk"_, etc.
that in turn are converted into method calls to `HttpChannel`.

When enough of the HTTP request is arrived, the `Connection` calls `HttpChannel.handle()` that calls the `Handler` chain, that eventually calls the server application code.

[[eg-server-http-channel-events]]
===== HttpChannel Events

Expand Down Expand Up @@ -141,7 +146,7 @@ Currently, the following events are available:

Please refer to the `HttpChannel.Listener` link:{JDURL}/org/eclipse/jetty/server/HttpChannel.Listener.html[javadocs] for the complete list of events.

Server applications can register `HttpChannel.Listener` by adding them as beans to the `Connector`:
Server applications can register `HttpChannel.Listener` by adding them as xref:eg-arch-bean[beans] to the `Connector`:

[source,java,indent=0]
----
Expand All @@ -150,4 +155,5 @@ include::../../{doc_code}/embedded/server/http/HTTPServerDocs.java[tags=httpChan

include::server-http-connector.adoc[]
include::server-http-handler.adoc[]
include::server-http-security.adoc[]
include::server-http-application.adoc[]
Loading

0 comments on commit 1d96dda

Please sign in to comment.