Grizzly 2.3.4: Client-side Connection Pool

New client-side connection pool API has been introduced in Grizzly 2.3.4. This API is completely different from one provided by Grizzly 1.9.x, it has more features and hopefully is nicer and easier to use 🙂
There are 2 main abstractions: SingleEndpointPool and MultiEndpointPool, which represent a connection pool to a single and multiple endpoints* respectively. Each connection pool abstraction has a builder, which helps to construct and initialize a connection pool of a specific configuration.
Let’s talk about these 2 connection pool types separately:

  • SingleEndpointPool
    Represents a connection pool to a single endpoint*. For example if we want to create a connection pool to “grizzly.java.net:443” and set the maximum number of connections in pool equal to 8 – the code will look like:

    TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance()
                    .processor(myFilterChain)
                    .build();
    transport.start();
    
    SingleEndpointPool pool = SingleEndpointPool
                    .builder(SocketAddress.class)
                    .connectorHandler(transport)
                    .endpointAddress(new InetSocketAddress("grizzly.java.net", 443))
                    .maxPoolSize(8)
                    .build();
    
    try {
        // use the connection pool
        ............
    } finally {
        pool.close();
        transport.stop();
    }

    A Connection could be asynchronously obtained from the pool using either Future or CompletionHandler:

    Future<Connection> connectionFuture = pool.take();

    or

    CompletionHandler<Connection> myCompletionHandler = createMyCompletionHandler();
    pool.take(myCompletionHandler);

    Please note, if you try to retrieve a Connection using Future, but suddenly changed your mind and don’t want to wait for a Connection, you have to use the code like:

    if (!connectionFuture.cancel(false)) {
        // means Connection is ready
        pool.release(connectionFuture.get());
    }

    to properly cancel the asynchronous operation and return a Connection (if there is any) back to the pool. In general it is highly important to return a Connection back to a pool once you don’t need it to avoid connection pool starvation, which will make connection pool useless.

    pool.release(connection);

    Other interesting feature of Grizzly connection pool – is an ability to attach/detach connections to/from a pool. For example if you retrieved a connection, but don’t plan to use it as part of the pool or don’t plan to return it back to the pool – you can detach this connection

    Connection connection = pool.take().get(10, TimeUnit.SECONDS);
    pool.detach(connection);

    and the pool will be able to establish a new connection (lazily, if needed) to reimburse it. On other hand if you have a connection, created outside the pool (or detached from the pool) and you want to attach this connection to the pool – you can call:

    pool.attach(foreignConnection);

    When the pool is not needed anymore (usually when you exit application) – it is recommended to close it:

    pool.close();

    During the close() operation execution all the idle connections will be closed. The busy connections, which were not returned back to the pool yet, will be kept open and will be closed once you will try to return them back to the pool.

  • MultiEndpointPool
    Represents a connection pool to multiple endpoints*. We can think of MutliEndpointPool as an Endpoint-to-SingleEndpointPool map, where each endpoint is represented by an EndpointKey. The MultiEndpointPool supports pretty much the same set of operations as SingleEndpointPool, but some of these operations (especially related to the Connection allocation) require EndpointKey parameter. Here is an example of MultiEndpointPool, which is used to allocate connections to 2 different servers:

    // Build a connection pool
    MultiEndpointPool pool = MultiEndpointPool
              .builder(SocketAddress.class)
              .connectorHandler(transport)
              .maxConnectionsPerEndpoint(4)
              .maxConnectionsTotal(16)
              .build();
    
    // define endpoints
    EndpointKey endpointKey1 =
               new EndpointKey("endpoint1",
                               new InetSocketAddress("grizzly.java.net", 80));
    EndpointKey endpointKey2 =
               new EndpointKey("endpoint2",
                               new InetSocketAddress("mytecc.wordpress.com", 80));
    Connection c1 = null;
    Connection c2 = null;
    try {
        c1 = pool.take(endpointKey1).get();
        c2 = pool.take(endpointKey2).get();
    ..........................
    } finally {
        if (c1 != null) {
            pool.release(c1);
        }
        if (c2 != null) {
            pool.release(c2);
        }
    }

The SingleEndpointPool and the MultiEndpointPool have similar configuration properties, which could be tuned: max pool size, connect timeout, keep-alive timeout, reconnect delay etc. Additionally for MultiEndpointPool it is possible to tune max connections per endpoint property, which lets us limit the maximum number of connections to a single endpoint.
You can find the complete connection pool example here.

The Grizzly connection pool implementation is available as a Maven module:

<dependency>
    <groupId>org.glassfish.grizzly</groupId>
    <artifactId>connection-pool</artifactId>
    <version>2.3.4</version>
</dependency>

or could be downloaded here.

Here is the full list of configuration properties, which can be used to customize:

  • SingleEndpointPool
    Property Description Notes
    connectorHandler The ConnectorHandler to be used to establish Connections to the endpoint mandatory
    endpointAddress The remote endpoint address to open Connection to mandatory
    localEndpointAddress The local endpoint address to bind Connection to optional
    corePoolSize The number of Connections, kept in the pool, that are immune to keep-alive mechanism Default value: 0
    maxPoolSize The max number of Connections kept by this pool Default value: 4
    connectTimeout The connect timeout, after which, if a connection is not established, it is considered failed value < 0 disables the timeout. By default disabled
    reconnectDelay The delay to be used before the pool will repeat the attempt to connect to the endpoint after previous connect had failed value < 0 disables reconnect. By default disabled
    maxReconnectAttempts The maximum number of attempts to reconnect that will be made before notification of failure occurs Default value: 5
    keepAliveTimeout The maximum amount of time an idle Connection will be kept in the pool. The idle Connections will be closed till the pool size is greater than corePoolSize value < 0 disables keep-alive mechanism. Default value: 30 seconds
    keepAliveCheckInterval The interval, which specifies how often the pool will perform idle Connections check Default value: 5 seconds
  • MultiEndpointPool
    Property Description Notes
    defaultConnectorHandler The default ConnectorHandler to be used to establish Connections to an endpoint mandatory. It is still possible to set a ConnectorHandler per each endpoint separately
    maxConnectionsPerEndpoint The maximum number of Connections each SingleEndpointPool sub-pool is allowed to have Default value: 2
    maxConnectionsTotal The total maximum number of Connections to be kept by the pool Default value: 16
    connectTimeout The connect timeout, after which, if a connection is not established, it is considered failed value < 0 disables the timeout. By default disabled
    reconnectDelay The delay to be used before the pool will repeat the attempt to connect to the endpoint after previous connect had failed value < 0 disables reconnect. By default disabled
    maxReconnectAttempts The maximum number of attempts to reconnect that will be made before notification of failure occurs Default value: 5
    keepAliveTimeout The maximum amount of time an idle Connection will be kept in the pool value < 0 disables keep-alive mechanism. Default value: 30 seconds
    keepAliveCheckInterval The interval, which specifies how often the pool will perform idle Connections check Default value: 5 seconds


* term endpoint is abstract, it can be either SocketAddress, which represents host:port for TCP and UDP Transports; or any other endpoint type  understood by a custom Grizzly Transport

Advertisements
This entry was posted in Uncategorized and tagged , , , . Bookmark the permalink.

2 Responses to Grizzly 2.3.4: Client-side Connection Pool

  1. Sean says:

    How do I create a Jersey using Grizzly and a SingleEndpointPool?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s