474888 - HttpClient JMX support.

This commit is contained in:
Simone Bordet 2015-08-13 15:16:14 +02:00
parent 4c7d5f661e
commit 69b90ef59b
10 changed files with 90 additions and 13 deletions

View File

@ -31,10 +31,13 @@ import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ManagedObject
public abstract class AbstractHttpClientTransport extends ContainerLifeCycle implements HttpClientTransport
{
protected static final Logger LOG = Log.getLogger(HttpClientTransport.class);
@ -59,6 +62,12 @@ public abstract class AbstractHttpClientTransport extends ContainerLifeCycle imp
this.client = client;
}
@ManagedAttribute(value = "The number of selectors", readonly = true)
public int getSelectors()
{
return selectors;
}
@Override
protected void doStart() throws Exception
{

View File

@ -33,12 +33,15 @@ import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Sweeper;
@ManagedObject("The connection pool")
public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
{
protected static final Logger LOG = Log.getLogger(ConnectionPool.class);
@ -60,11 +63,24 @@ public class ConnectionPool implements Closeable, Dumpable, Sweeper.Sweepable
this.activeConnections = new BlockingArrayQueue<>(maxConnections);
}
@ManagedAttribute(value = "The number of connections", readonly = true)
public int getConnectionCount()
{
return connectionCount.get();
}
@ManagedAttribute(value = "The number of idle connections", readonly = true)
public int getIdleConnectionCount()
{
return idleConnections.size();
}
@ManagedAttribute(value = "The number of active connections", readonly = true)
public int getActiveConnectionCount()
{
return activeConnections.size();
}
public BlockingQueue<Connection> getIdleConnections()
{
return idleConnections;

View File

@ -62,6 +62,8 @@ import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Jetty;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.SocketAddressResolver;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -106,6 +108,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
* });
* </pre>
*/
@ManagedObject("The HTTP client")
public class HttpClient extends ContainerLifeCycle
{
private static final Logger LOG = Log.getLogger(HttpClient.class);
@ -503,11 +506,13 @@ public class HttpClient extends ContainerLifeCycle
}
else
{
addManaged(destination);
if (LOG.isDebugEnabled())
LOG.debug("Created {}", destination);
}
if (!isRunning())
destinations.remove(origin);
removeDestination(destination);
}
}
@ -516,6 +521,7 @@ public class HttpClient extends ContainerLifeCycle
protected boolean removeDestination(HttpDestination destination)
{
removeBean(destination);
return destinations.remove(destination.getOrigin()) != null;
}
@ -594,6 +600,7 @@ public class HttpClient extends ContainerLifeCycle
/**
* @return the max time, in milliseconds, a connection can take to connect to destinations
*/
@ManagedAttribute("The timeout, in milliseconds, for connect() operations")
public long getConnectTimeout()
{
return connectTimeout;
@ -634,6 +641,7 @@ public class HttpClient extends ContainerLifeCycle
/**
* @return the max time, in milliseconds, a connection can be idle (that is, without traffic of bytes in either direction)
*/
@ManagedAttribute("The timeout, in milliseconds, to close idle connections")
public long getIdleTimeout()
{
return idleTimeout;
@ -688,6 +696,7 @@ public class HttpClient extends ContainerLifeCycle
* @return whether this {@link HttpClient} follows HTTP redirects
* @see Request#isFollowRedirects()
*/
@ManagedAttribute("Whether HTTP redirects are followed")
public boolean isFollowRedirects()
{
return followRedirects;
@ -753,6 +762,7 @@ public class HttpClient extends ContainerLifeCycle
/**
* @return the max number of connections that this {@link HttpClient} opens to {@link Destination}s
*/
@ManagedAttribute("The max number of connections per each destination")
public int getMaxConnectionsPerDestination()
{
return maxConnectionsPerDestination;
@ -777,6 +787,7 @@ public class HttpClient extends ContainerLifeCycle
/**
* @return the max number of requests that may be queued to a {@link Destination}.
*/
@ManagedAttribute("The max number of requests queued per each destination")
public int getMaxRequestsQueuedPerDestination()
{
return maxRequestsQueuedPerDestination;
@ -803,6 +814,7 @@ public class HttpClient extends ContainerLifeCycle
/**
* @return the size of the buffer used to write requests
*/
@ManagedAttribute("The request buffer size")
public int getRequestBufferSize()
{
return requestBufferSize;
@ -819,6 +831,7 @@ public class HttpClient extends ContainerLifeCycle
/**
* @return the size of the buffer used to read responses
*/
@ManagedAttribute("The response buffer size")
public int getResponseBufferSize()
{
return responseBufferSize;
@ -853,6 +866,7 @@ public class HttpClient extends ContainerLifeCycle
/**
* @return whether TCP_NODELAY is enabled
*/
@ManagedAttribute(value = "Whether the TCP_NODELAY option is enabled", name = "tcpNoDelay")
public boolean isTCPNoDelay()
{
return tcpNoDelay;
@ -900,6 +914,7 @@ public class HttpClient extends ContainerLifeCycle
* @return whether request events must be strictly ordered
* @see #setStrictEventOrdering(boolean)
*/
@ManagedAttribute("Whether request/response events must be strictly ordered")
public boolean isStrictEventOrdering()
{
return strictEventOrdering;
@ -940,6 +955,7 @@ public class HttpClient extends ContainerLifeCycle
* @return whether destinations that have no connections should be removed
* @see #setRemoveIdleDestinations(boolean)
*/
@ManagedAttribute("Whether idle destinations are removed")
public boolean isRemoveIdleDestinations()
{
return removeIdleDestinations;
@ -965,6 +981,7 @@ public class HttpClient extends ContainerLifeCycle
/**
* @return whether {@code connect()} operations are performed in blocking mode
*/
@ManagedAttribute("Whether the connect() operation is blocking")
public boolean isConnectBlocking()
{
return connectBlocking;

View File

@ -36,12 +36,15 @@ import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public abstract class HttpDestination implements Destination, Closeable, Dumpable
@ManagedObject
public abstract class HttpDestination extends ContainerLifeCycle implements Destination, Closeable, Dumpable
{
protected static final Logger LOG = Log.getLogger(HttpDestination.class);
@ -130,12 +133,14 @@ public abstract class HttpDestination implements Destination, Closeable, Dumpabl
}
@Override
@ManagedAttribute(value = "The destination scheme", readonly = true)
public String getScheme()
{
return origin.getScheme();
}
@Override
@ManagedAttribute(value = "The destination host", readonly = true)
public String getHost()
{
// InetSocketAddress.getHostString() transforms the host string
@ -144,11 +149,18 @@ public abstract class HttpDestination implements Destination, Closeable, Dumpabl
}
@Override
@ManagedAttribute(value = "The destination port", readonly = true)
public int getPort()
{
return origin.getAddress().getPort();
}
@ManagedAttribute(value = "The number of queued requests", readonly = true)
public int getQueuedRequestCount()
{
return exchanges.size();
}
public Origin.Address getConnectAddress()
{
return proxy == null ? origin.getAddress() : proxy.getAddress();

View File

@ -19,14 +19,17 @@
package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.thread.Sweeper;
@ManagedObject
public abstract class PoolingHttpDestination<C extends Connection> extends HttpDestination implements Callback
{
private final ConnectionPool connectionPool;
@ -35,6 +38,7 @@ public abstract class PoolingHttpDestination<C extends Connection> extends HttpD
{
super(client, origin);
this.connectionPool = newConnectionPool(client);
addBean(connectionPool);
Sweeper sweeper = client.getBean(Sweeper.class);
if (sweeper != null)
sweeper.offer(connectionPool);
@ -45,6 +49,7 @@ public abstract class PoolingHttpDestination<C extends Connection> extends HttpD
return new ConnectionPool(this, client.getMaxConnectionsPerDestination(), this);
}
@ManagedAttribute(value = "The connection pool", readonly = true)
public ConnectionPool getConnectionPool()
{
return connectionPool;
@ -195,7 +200,7 @@ public abstract class PoolingHttpDestination<C extends Connection> extends HttpD
public void dump(Appendable out, String indent) throws IOException
{
super.dump(out, indent);
ContainerLifeCycle.dump(out, indent, Arrays.asList(connectionPool));
ContainerLifeCycle.dump(out, indent, Collections.singletonList(connectionPool));
}
@Override

View File

@ -27,7 +27,9 @@ import org.eclipse.jetty.client.Origin;
import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedObject;
@ManagedObject("The HTTP/1.1 client transport")
public class HttpClientTransportOverHTTP extends AbstractHttpClientTransport
{
public HttpClientTransportOverHTTP()

View File

@ -18,9 +18,6 @@
package org.eclipse.jetty.client;
import static java.nio.file.StandardOpenOption.CREATE;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -33,6 +30,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -124,8 +122,8 @@ public class HttpClientTest extends AbstractHttpClientServerTest
client.stop();
Assert.assertEquals(0, client.getDestinations().size());
Assert.assertEquals(0, connectionPool.getIdleConnections().size());
Assert.assertEquals(0, connectionPool.getActiveConnections().size());
Assert.assertEquals(0, connectionPool.getIdleConnectionCount());
Assert.assertEquals(0, connectionPool.getActiveConnectionCount());
Assert.assertFalse(connection.getEndPoint().isOpen());
}
@ -543,10 +541,10 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new RespondThenConsumeHandler());
// Prepare a big file to upload
Path targetTestsDir = testdir.getEmptyDir().toPath();
Path targetTestsDir = testdir.getEmptyPathDir();
Files.createDirectories(targetTestsDir);
Path file = Paths.get(targetTestsDir.toString(), "http_client_conversation.big");
try (OutputStream output = Files.newOutputStream(file, CREATE))
try (OutputStream output = Files.newOutputStream(file, StandardOpenOption.CREATE))
{
byte[] kb = new byte[1024];
for (int i = 0; i < 10 * 1024; ++i)
@ -813,7 +811,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
});
}
assertTrue(latch.await(10, TimeUnit.SECONDS));
Assert.assertTrue(latch.await(10, TimeUnit.SECONDS));
}
@Test
@ -1119,7 +1117,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
}
});
final Exchanger<Response> ex = new Exchanger<Response>();
final Exchanger<Response> ex = new Exchanger<>();
BufferingResponseListener listener = new BufferingResponseListener()
{
@Override

View File

@ -30,7 +30,10 @@ import org.eclipse.jetty.fcgi.FCGI;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
@ManagedObject("The FastCGI/1.0 client transport")
public class HttpClientTransportOverFCGI extends AbstractHttpClientTransport
{
private final boolean multiplexed;
@ -53,6 +56,7 @@ public class HttpClientTransportOverFCGI extends AbstractHttpClientTransport
return multiplexed;
}
@ManagedAttribute(value = "The scripts root directory", readonly = true)
public String getScriptRoot()
{
return scriptRoot;

View File

@ -33,8 +33,11 @@ import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
@ManagedObject("The HTTP/2 client transport")
public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements HttpClientTransport
{
private final HTTP2Client client;
@ -46,6 +49,12 @@ public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements
this.client = client;
}
@ManagedAttribute(value = "The number of selectors", readonly = true)
public int getSelectors()
{
return client.getSelectors();
}
@Override
protected void doStart() throws Exception
{

View File

@ -26,6 +26,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler;
@ -48,6 +50,7 @@ public interface SocketAddressResolver
/**
* <p>Creates {@link SocketAddress} instances synchronously in the caller thread.</p>
*/
@ManagedObject("The synchronous address resolver")
public static class Sync implements SocketAddressResolver
{
@Override
@ -91,6 +94,7 @@ public interface SocketAddressResolver
* });
* </pre>
*/
@ManagedObject("The asynchronous address resolver")
public static class Async implements SocketAddressResolver
{
private static final Logger LOG = Log.getLogger(SocketAddressResolver.class);
@ -124,6 +128,7 @@ public interface SocketAddressResolver
return scheduler;
}
@ManagedAttribute(value = "The timeout, in milliseconds, to resolve an address", readonly = true)
public long getTimeout()
{
return timeout;