Closes #4809 - Set a max number of requests per connection.
Implemented as part of #4975. Added a test case that proves that the connection is closed when the max usage count is reached. Improved logging. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
3c6c5075f8
commit
4a0af046b8
|
@ -254,10 +254,10 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
|
|||
protected Connection activate()
|
||||
{
|
||||
Pool<Connection>.Entry entry = pool.acquire();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("activated '{}'", entry);
|
||||
if (entry != null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("activated {}", entry);
|
||||
Connection connection = entry.getPooled();
|
||||
acquired(connection);
|
||||
return connection;
|
||||
|
@ -298,15 +298,13 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
|
|||
Pool<Connection>.Entry entry = (Pool<Connection>.Entry)attachable.getAttachment();
|
||||
if (entry == null)
|
||||
return true;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("releasing {}", entry);
|
||||
boolean reusable = pool.release(entry);
|
||||
if (!reusable)
|
||||
{
|
||||
remove(connection);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Released ({}) {}", reusable, entry);
|
||||
if (reusable)
|
||||
return true;
|
||||
remove(connection);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -325,9 +323,9 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
|
|||
if (entry == null)
|
||||
return false;
|
||||
attachable.setAttachment(null);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("removing {}", entry);
|
||||
boolean removed = pool.remove(entry);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Removed ({}) {}", removed, entry);
|
||||
if (removed || force)
|
||||
{
|
||||
released(connection);
|
||||
|
|
|
@ -351,6 +351,42 @@ public class ConnectionPoolTest
|
|||
assertThat(connectionPool.getConnectionCount(), Matchers.lessThanOrEqualTo(count));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("pools")
|
||||
public void testConnectionMaxUsage(ConnectionPoolFactory factory) throws Exception
|
||||
{
|
||||
startServer(new EmptyServerHandler());
|
||||
|
||||
int maxUsageCount = 2;
|
||||
startClient(destination ->
|
||||
{
|
||||
AbstractConnectionPool connectionPool = (AbstractConnectionPool)factory.factory.newConnectionPool(destination);
|
||||
connectionPool.setMaxUsageCount(maxUsageCount);
|
||||
return connectionPool;
|
||||
});
|
||||
client.setMaxConnectionsPerDestination(1);
|
||||
|
||||
// Send first request, we are within the max usage count.
|
||||
ContentResponse response1 = client.newRequest("localhost", connector.getLocalPort()).send();
|
||||
assertEquals(HttpStatus.OK_200, response1.getStatus());
|
||||
|
||||
HttpDestination destination = (HttpDestination)client.getDestinations().get(0);
|
||||
AbstractConnectionPool connectionPool = (AbstractConnectionPool)destination.getConnectionPool();
|
||||
|
||||
assertEquals(0, connectionPool.getActiveConnectionCount());
|
||||
assertEquals(1, connectionPool.getIdleConnectionCount());
|
||||
assertEquals(1, connectionPool.getConnectionCount());
|
||||
|
||||
// Send second request, max usage count will be reached,
|
||||
// the only connection must be closed.
|
||||
ContentResponse response2 = client.newRequest("localhost", connector.getLocalPort()).send();
|
||||
assertEquals(HttpStatus.OK_200, response2.getStatus());
|
||||
|
||||
assertEquals(0, connectionPool.getActiveConnectionCount());
|
||||
assertEquals(0, connectionPool.getIdleConnectionCount());
|
||||
assertEquals(0, connectionPool.getConnectionCount());
|
||||
}
|
||||
|
||||
private static class ConnectionPoolFactory
|
||||
{
|
||||
private final String name;
|
||||
|
|
|
@ -545,7 +545,7 @@ public class Pool<T> implements AutoCloseable, Dumpable
|
|||
public String toString()
|
||||
{
|
||||
long encoded = state.get();
|
||||
return String.format("%s@%x{hi=%d,lo=%d.p=%s}",
|
||||
return String.format("%s@%x{usage=%d,multiplex=%d,pooled=%s}",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
AtomicBiInteger.getHi(encoded),
|
||||
|
|
Loading…
Reference in New Issue