Class AbstractConnector

All Implemented Interfaces:
Connector, Container, Destroyable, Dumpable, Dumpable.DumpableContainer, Graceful, LifeCycle
Direct Known Subclasses:
AbstractNetworkConnector, LocalConnector, MemoryConnector, UnixDomainServerConnector

@ManagedObject("Abstract implementation of the Connector Interface") public abstract class AbstractConnector extends ContainerLifeCycle implements Connector, Dumpable

An abstract implementation of Connector that provides a ConnectionFactory mechanism for creating Connection instances for various protocols (HTTP, SSL, etc).

Connector Services

The abstract connector manages the dependent services needed by all specific connector instances:
  • The Executor service is used to run all active tasks needed by this connector such as accepting connections or handle HTTP requests. The default is to use the Server.getThreadPool() as an executor.
  • The Scheduler service is used to monitor the idle timeouts of all connections and is also made available to the connections to time such things as asynchronous request timeouts. The default is to use a new ScheduledExecutorScheduler instance.
  • The ByteBufferPool service is made available to all connections to be used to acquire and release RetainableByteBuffer instances from a pool. The default is to use a new ArrayByteBufferPool instance.
These services are managed as aggregate beans by the ContainerLifeCycle super class and may either be managed or unmanaged beans.

Connection Factories

The connector keeps a collection of ConnectionFactory instances, each of which are known by their protocol name. The protocol name may be a real protocol (e.g. "http/1.1" or "h2") or it may be a private name that represents a special connection factory. For example, the name "SSL-http/1.1" is used for an SslConnectionFactory that has been instantiated with the HttpConnectionFactory as it's next protocol.

Configuring Connection Factories

The collection of available ConnectionFactory may be constructor injected or modified with the methods addConnectionFactory(ConnectionFactory), removeConnectionFactory(String) and setConnectionFactories(Collection). Only a single ConnectionFactory instance may be configured per protocol name, so if two factories with the same ConnectionFactory.getProtocol() are set, then the second will replace the first.

The protocol factory used for newly accepted connections is specified by the method setDefaultProtocol(String) or defaults to the protocol of the first configured factory.

Each Connection factory type is responsible for the configuration of the protocols that it accepts. Thus to configure the HTTP protocol, you pass a HttpConfiguration instance to the HttpConnectionFactory (or other factories that can also provide HTTP Semantics). Similarly the SslConnectionFactory is configured by passing it a SslContextFactory and a next protocol name.

Connection Factory Operation

ConnectionFactorys may simply create a Connection instance to support a specific protocol. For example, the HttpConnectionFactory will create a HttpConnection instance that can handle http/1.1, http/1.0 and http/0.9.

ConnectionFactorys may also create a chain of Connection instances, using other ConnectionFactory instances. For example, the SslConnectionFactory is configured with a next protocol name, so that once it has accepted a connection and created an SslConnection, it then used the next ConnectionFactory from the connector using the getConnectionFactory(String) method, to create a Connection instance that will handle the unencrypted bytes from the SslConnection. If the next protocol is "http/1.1", then the SslConnectionFactory will have a protocol name of "SSL-http/1.1" and lookup "http/1.1" for the protocol to run over the SSL connection.

ConnectionFactorys may also create temporary Connection instances that will exchange bytes over the connection to determine what is the next protocol to use. For example the ALPN protocol is an extension of SSL to allow a protocol to be specified during the SSL handshake. ALPN is used by the HTTP/2 protocol to negotiate the protocol that the client and server will speak. Thus to accept an HTTP/2 connection, the connector will be configured with ConnectionFactorys for "SSL-ALPN", "h2", "http/1.1" with the default protocol being "SSL-ALPN". Thus a newly accepted connection uses "SSL-ALPN", which specifies a SSLConnectionFactory with "ALPN" as the next protocol. Thus an SSL connection instance is created chained to an ALPN connection instance. The ALPN connection then negotiates with the client to determined the next protocol, which could be "h2" or the default of "http/1.1". Once the next protocol is determined, the ALPN connection calls getConnectionFactory(String) to create a connection instance that will replace the ALPN connection as the connection chained to the SSL connection.

Acceptors

The connector will execute a number of acceptor tasks to the Exception service passed to the constructor. The acceptor tasks run in a loop while the connector is running and repeatedly call the abstract accept(int) method. The implementation of the accept method must:
  1. block waiting for new connections
  2. accept the connection (eg socket accept)
  3. perform any configuration of the connection (eg. socket configuration)
  4. call the getDefaultConnectionFactory() ConnectionFactory.newConnection(Connector, EndPoint) method to create a new Connection instance.
The default number of acceptor tasks is the minimum of 1 and the number of available CPUs divided by 8. Having more acceptors may reduce the latency for servers that see a high rate of new connections (eg HTTP/1.0 without keep-alive). Typically the default is sufficient for modern persistent protocols (HTTP/1.1, HTTP/2 etc.)
  • Field Details

    • LOG

      protected static final org.slf4j.Logger LOG
  • Constructor Details

    • AbstractConnector

      public AbstractConnector(Server server, Executor executor, Scheduler scheduler, ByteBufferPool bufferPool, int acceptors, ConnectionFactory... factories)
      Parameters:
      server - The Server this connector will be added to, must not be null
      executor - An Executor for this connector or null to use the Server's Executor
      scheduler - A Scheduler for this connector or null to use the Server's Scheduler
      bufferPool - A ByteBufferPool for this connector or null to use the Server's ByteBufferPool
      acceptors - the number of acceptor threads to use, or -1 for a default value. If 0, then no acceptor threads will be launched and some other mechanism will need to be used to accept new connections.
      factories - The ConnectionFactory instances to use
  • Method Details

    • getServer

      public Server getServer()
      Description copied from interface: Connector
      Get the Server instance associated with this Connector.
      Specified by:
      getServer in interface Connector
      Returns:
      the Server instance associated with this Connector
    • getExecutor

      public Executor getExecutor()
      Description copied from interface: Connector
      Get the Executor used to submit tasks.
      Specified by:
      getExecutor in interface Connector
      Returns:
      the Executor used to submit tasks
    • getByteBufferPool

      public ByteBufferPool getByteBufferPool()
      Description copied from interface: Connector
      Get the ByteBufferPool to acquire buffers from and release buffers to.
      Specified by:
      getByteBufferPool in interface Connector
      Returns:
      the ByteBufferPool to acquire buffers from and release buffers to
    • getIdleTimeout

      @ManagedAttribute("The connection idle timeout in milliseconds") public long getIdleTimeout()
      Specified by:
      getIdleTimeout in interface Connector
      Returns:
      the max idle timeout for connections in milliseconds
    • setIdleTimeout

      public void setIdleTimeout(long idleTimeout)

      Sets the maximum Idle time for a connection, which roughly translates to the Socket.setSoTimeout(int) call, although with NIO implementations other mechanisms may be used to implement the timeout.

      The max idle time is applied:

      • When waiting for a new message to be received on a connection
      • When waiting for a new message to be sent on a connection

      This value is interpreted as the maximum time between some progress being made on the connection. So if a single byte is read or written, then the timeout is reset.

      Parameters:
      idleTimeout - the idle timeout
    • setShutdownIdleTimeout

      public void setShutdownIdleTimeout(long idle)
    • getShutdownIdleTimeout

      public long getShutdownIdleTimeout()
    • getAcceptors

      @ManagedAttribute("number of acceptor threads") public int getAcceptors()
      Returns:
      Returns the number of acceptor threads.
    • doStart

      protected void doStart() throws Exception
      Description copied from class: ContainerLifeCycle
      Starts the managed lifecycle beans in the order they were added.
      Overrides:
      doStart in class ContainerLifeCycle
      Throws:
      AbstractLifeCycle.StopException - If thrown, the lifecycle will immediately be stopped.
      Exception - If there was a problem starting. Will cause a transition to FAILED state
    • interruptAcceptors

      protected void interruptAcceptors()
    • shutdown

      public CompletableFuture<Void> shutdown()
      Description copied from interface: Graceful
      Shutdown the component. When this method returns, the component should not accept any new load.
      Specified by:
      shutdown in interface Graceful
      Returns:
      A future that is completed once all load on the component is completed
    • isShutdown

      public boolean isShutdown()
      Specified by:
      isShutdown in interface Graceful
      Returns:
      True if Graceful.shutdown() has been called.
    • doStop

      protected void doStop() throws Exception
      Description copied from class: ContainerLifeCycle
      Stops the managed lifecycle beans in the reverse order they were added.
      Overrides:
      doStop in class ContainerLifeCycle
      Throws:
      Exception - If there was a problem stopping. Will cause a transition to FAILED state
    • join

      public void join() throws InterruptedException
      Throws:
      InterruptedException
    • join

      public void join(long timeout) throws InterruptedException
      Throws:
      InterruptedException
    • accept

      protected abstract void accept(int acceptorID) throws IOException, InterruptedException
      Throws:
      IOException
      InterruptedException
    • isAccepting

      public boolean isAccepting()
      Returns:
      Is the connector accepting new connections
    • setAccepting

      public void setAccepting(boolean accepting)
    • getConnectionFactory

      public ConnectionFactory getConnectionFactory(String protocol)
      Specified by:
      getConnectionFactory in interface Connector
      Parameters:
      protocol - the next protocol
      Returns:
      the ConnectionFactory associated with the protocol name
    • getConnectionFactory

      public <T> T getConnectionFactory(Class<T> factoryType)
      Specified by:
      getConnectionFactory in interface Connector
    • addConnectionFactory

      public void addConnectionFactory(ConnectionFactory factory)
    • addFirstConnectionFactory

      public void addFirstConnectionFactory(ConnectionFactory factory)
    • addIfAbsentConnectionFactory

      public void addIfAbsentConnectionFactory(ConnectionFactory factory)
    • removeConnectionFactory

      public ConnectionFactory removeConnectionFactory(String protocol)
    • getConnectionFactories

      public Collection<ConnectionFactory> getConnectionFactories()
      Specified by:
      getConnectionFactories in interface Connector
    • setConnectionFactories

      public void setConnectionFactories(Collection<ConnectionFactory> factories)
    • clearConnectionFactories

      public void clearConnectionFactories()
    • getAcceptorPriorityDelta

      @ManagedAttribute("The priority delta to apply to acceptor threads") public int getAcceptorPriorityDelta()
    • setAcceptorPriorityDelta

      public void setAcceptorPriorityDelta(int acceptorPriorityDelta)
      Set the acceptor thread priority delta.

      This allows the acceptor thread to run at a different priority. Typically this would be used to lower the priority to give preference to handling previously accepted connections rather than accepting new connections

      Parameters:
      acceptorPriorityDelta - the acceptor priority delta
    • getProtocols

      @ManagedAttribute("Protocols supported by this connector") public List<String> getProtocols()
      Specified by:
      getProtocols in interface Connector
    • getDefaultProtocol

      @ManagedAttribute("This connector\'s default protocol") public String getDefaultProtocol()
    • setDefaultProtocol

      public void setDefaultProtocol(String defaultProtocol)
    • getDefaultConnectionFactory

      public ConnectionFactory getDefaultConnectionFactory()
      Description copied from interface: Connector
      Get the default ConnectionFactory associated with the default protocol name.
      Specified by:
      getDefaultConnectionFactory in interface Connector
      Returns:
      the default ConnectionFactory associated with the default protocol name
    • handleAcceptFailure

      protected boolean handleAcceptFailure(Throwable ex)
    • getConnectedEndPoints

      public Collection<EndPoint> getConnectedEndPoints()
      Specified by:
      getConnectedEndPoints in interface Connector
      Returns:
      immutable collection of connected endpoints
    • onEndPointOpened

      protected void onEndPointOpened(EndPoint endp)
    • onEndPointClosed

      protected void onEndPointClosed(EndPoint endp)
    • getScheduler

      public Scheduler getScheduler()
      Description copied from interface: Connector
      Get the Scheduler used to schedule tasks.
      Specified by:
      getScheduler in interface Connector
      Returns:
      the Scheduler used to schedule tasks
    • getName

      public String getName()
      Description copied from interface: Connector
      Get the connector name if set.

      A ContextHandler may be configured with virtual hosts in the form "@connectorName" and will only serve requests from the named connector.

      Specified by:
      getName in interface Connector
      Returns:
      The connector name or null.
    • setName

      public void setName(String name)
      Set a connector name. A context may be configured with virtual hosts in the form "@contextname" and will only serve requests from the named connector,
      Parameters:
      name - A connector name.
    • toString

      public String toString()
      Overrides:
      toString in class AbstractLifeCycle