Stijn Geukens
Stijn Geukens

Reputation: 15628

Check available connections in PoolingClientConnectionManager

Is there a way (and how) to know the status of a connection pool? Like, how many connections are being used, how many are available, ...

We are currently facing issues where the application cannot get a connection from the pool (ConnectionPoolTimeoutException: Timeout waiting for connection from pool) so to track down the cause we would like to log some pool stats each time a new connection is requested.

I have been browsing the Apache HTTPClient API but did not find a way to get this information.

We use PoolingClientConnectionManager.

Upvotes: 1

Views: 6949

Answers (2)

ok2c
ok2c

Reputation: 27623

You can use methods of the ConnPoolControl interface to control parameters of the internal pool

Upvotes: 3

Lucas Basquerotto
Lucas Basquerotto

Reputation: 8143

You can have a detailed information total and per route with the code below:

public static void main(String[] args) {
    PoolingHttpClientConnectionManager connectionManager = HttpClientUtils.getConnectionManager();
    System.out.println(createHttpInfo(connectionManager));
}

private static String createHttpInfo(PoolingHttpClientConnectionManager connectionManager) {
    StringBuilder sb = new StringBuilder();
    sb.append("=========================").append("\n");
    sb.append("General Info:").append("\n");
    sb.append("-------------------------").append("\n");
    sb.append("MaxTotal: ").append(connectionManager.getMaxTotal()).append("\n");
    sb.append("DefaultMaxPerRoute: ").append(connectionManager.getDefaultMaxPerRoute()).append("\n");
    sb.append("ValidateAfterInactivity: ").append(connectionManager.getValidateAfterInactivity()).append("\n");
    sb.append("=========================").append("\n");

    PoolStats totalStats = connectionManager.getTotalStats();
    sb.append(createPoolStatsInfo("Total Stats", totalStats));

    Set<HttpRoute> routes = connectionManager.getRoutes();

    if (routes != null) {
        for (HttpRoute route : routes) {
            sb.append(createRouteInfo(connectionManager, route));
        }
    }

    return sb.toString();
}

private static String createRouteInfo(PoolingHttpClientConnectionManager connectionManager, HttpRoute route) {
    PoolStats routeStats = connectionManager.getStats(route);
    String info = createPoolStatsInfo(route.getTargetHost().toURI(), routeStats);
    return info;
}

private static String createPoolStatsInfo(String title, PoolStats poolStats) {
    StringBuilder sb = new StringBuilder();

    sb.append(title + ":").append("\n");
    sb.append("-------------------------").append("\n");

    if (poolStats != null) {
        sb.append("Available: ").append(poolStats.getAvailable()).append("\n");
        sb.append("Leased: ").append(poolStats.getLeased()).append("\n");
        sb.append("Max: ").append(poolStats.getMax()).append("\n");
        sb.append("Pending: ").append(poolStats.getPending()).append("\n");
    }

    sb.append("=========================").append("\n");

    return sb.toString();
}

Update (2019-01-07)

The connection manager is retrieved from an utilitarian class I've created (you can create it differently):

public class HttpClientUtils {

    private static final PoolingHttpClientConnectionManager connectionManager = createConnectionManager();

    private static PoolingHttpClientConnectionManager createConnectionManager() {
        try {
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
                    SSLContext.getDefault(),
                    new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"},
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", socketFactory)
                    .build();

            PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
            cm.setMaxTotal(200);
            cm.setDefaultMaxPerRoute(20);

            return cm;
        } catch (NoSuchAlgorithmException | RuntimeException ex) {
            Logger.getLogger(HttpClientUtils.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    public static PoolingHttpClientConnectionManager getConnectionManager() {
        return connectionManager;
    }
}

Upvotes: 3

Related Questions