Skip to content

Latest commit

 

History

History
167 lines (116 loc) · 10.2 KB

File metadata and controls

167 lines (116 loc) · 10.2 KB

Server Connectors

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

The available implementations are:

  • org.eclipse.jetty.server.ServerConnector, for TCP/IP sockets.

  • org.eclipse.jetty.unixdomain.server.UnixDomainServerConnector for Unix-Domain sockets.

Both use a java.nio.channels.ServerSocketChannel to listen to a socket address and to accept socket connections.

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

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]

Likewise, UnixDomainServerConnector also wraps a ServerSocketChannel and can be configured with the Unix-Domain path to listen to:

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]

The acceptors are threads (typically only one) that compete to accept socket connections. When a connection is accepted, ServerConnector wraps the accepted SocketChannel and passes 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 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 ManagedSelector. 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 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), or more than one UnixDomainServerConnector (each listening on a different path), or ServerConnectors and UnixDomainServerConnectors, for example:

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]
Configuring Protocols

For each accepted socket connection, the server Connector asks a ConnectionFactory to create a Connection object that handles the traffic on that socket connection, parsing and generating bytes for a specific protocol (see this section for more details about Connection objects).

A server Connector can be configured with one or more ConnectionFactorys. If no ConnectionFactory is specified then HttpConnectionFactory is implicitly configured.

Clear-Text HTTP/1.1

HttpConnectionFactory creates HttpConnection objects that parse bytes and generate bytes for the HTTP/1.1 protocol.

This is how you configure Jetty to support clear-text HTTP/1.1:

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]
Encrypted HTTP/1.1 (https)

Supporting encrypted HTTP/1.1 (that is, requests with the https scheme) is supported by configuring an SslContextFactory that has access to the keyStore containing the private server key and public server certificate, in this way:

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]
Clear-Text HTTP/2

It is well known that the HTTP ports are 80 (for clear-text HTTP) and 443 for encrypted HTTP. By using those ports, a client had prior knowledge that the server would speak, respectively, the HTTP/1.x protocol and the TLS protocol (and, after decryption, the HTTP/1.x protocol).

HTTP/2 was designed to be a smooth transition from HTTP/1.1 for users and as such the HTTP ports were not changed. However the HTTP/2 protocol is, on the wire, a binary protocol, completely different from HTTP/1.1. Therefore, with HTTP/2, clients that connect to port 80 (or to a specific Unix-Domain path) may speak either HTTP/1.1 or HTTP/2, and the server must figure out which version of the HTTP protocol the client is speaking.

Jetty can support both HTTP/1.1 and HTTP/2 on the same clear-text port by configuring both the HTTP/1.1 and the HTTP/2 ConnectionFactorys:

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]

Note how the ConnectionFactorys passed to ServerConnector are in order: first HTTP/1.1, then HTTP/2. This is necessary to support both protocols on the same port: Jetty will start parsing the incoming bytes as HTTP/1.1, but then realize that they are HTTP/2 bytes and will therefore upgrade from HTTP/1.1 to HTTP/2.

This configuration is also typical when Jetty is installed in backend servers behind a load balancer that also takes care of offloading TLS. When Jetty is behind a load balancer, you can always prepend the PROXY protocol as described in this section.

Encrypted HTTP/2

When using encrypted HTTP/2, the unencrypted protocol is negotiated by client and server using an extension to the TLS protocol called ALPN.

Jetty supports ALPN and encrypted HTTP/2 with this configuration:

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]

Note how the ConnectionFactorys passed to ServerConnector are in order: TLS, ALPN, HTTP/2, HTTP/1.1.

Jetty starts parsing TLS bytes so that it can obtain the ALPN extension. With the ALPN extension information, Jetty can negotiate a protocol and pick, among the ConnectionFactorys supported by the ServerConnector, the ConnectionFactory correspondent to the negotiated protocol.

The fact that the HTTP/2 protocol comes before the HTTP/1.1 protocol indicates that HTTP/2 is the preferred protocol for the server.

Note also that the default protocol set in the ALPN ConnectionFactory, which is used in case ALPN is not supported by the client, is HTTP/1.1 — if the client does not support ALPN is probably an old client so HTTP/1.1 is the safest choice.

Jetty Behind a Load Balancer

It is often the case that Jetty receives connections from a load balancer configured to distribute the load among many Jetty backend servers.

From the Jetty point of view, all the connections arrive from the load balancer, rather than the real clients, but is possible to configure the load balancer to forward the real client IP address and IP port to the backend Jetty server using the PROXY protocol.

Note
The PROXY protocol is widely supported by load balancers such as HAProxy (via its send-proxy directive), Nginx(via its proxy_protocol on directive) and others.

To support this case, Jetty can be configured in this way:

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]

Note how the ConnectionFactorys passed to ServerConnector are in order: first PROXY, then HTTP/1.1. Note also how the PROXY ConnectionFactory needs to know its next protocol (in this example, HTTP/1.1).

Each ConnectionFactory is asked to create a Connection object for each accepted TCP connection; the Connection objects will be chained together to handle the bytes, each for its own protocol. Therefore the ProxyConnection will handle the PROXY protocol bytes and HttpConnection will handle the HTTP/1.1 bytes producing a request object and response object that will be processed by Handlers.

The load balancer may be configured to communicate with Jetty backend servers via Unix-Domain sockets (requires Java 16 or later). For example:

link:../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[role=include]

Note that the only difference when using Unix-Domain sockets is instantiating UnixDomainServerConnector instead of ServerConnector and configuring the Unix-Domain path instead of the IP port.