484818 - Expose interesting HTTP/2 attributes and operations via JMX.
Added flow control stall times and improved dump().
This commit is contained in:
parent
997b868ecd
commit
fdadc942e9
|
@ -18,6 +18,10 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.http2;
|
package org.eclipse.jetty.http2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import org.eclipse.jetty.http2.api.Stream;
|
import org.eclipse.jetty.http2.api.Stream;
|
||||||
|
@ -25,15 +29,20 @@ import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedOperation;
|
import org.eclipse.jetty.util.annotation.ManagedOperation;
|
||||||
|
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.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
|
||||||
@ManagedObject
|
@ManagedObject
|
||||||
public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
|
public abstract class AbstractFlowControlStrategy implements FlowControlStrategy, Dumpable
|
||||||
{
|
{
|
||||||
protected static final Logger LOG = Log.getLogger(FlowControlStrategy.class);
|
protected static final Logger LOG = Log.getLogger(FlowControlStrategy.class);
|
||||||
|
|
||||||
private final AtomicLong sessionStalls = new AtomicLong();
|
private final AtomicLong sessionStall = new AtomicLong();
|
||||||
|
private final AtomicLong sessionStallTime = new AtomicLong();
|
||||||
|
private final Map<IStream, Long> streamsStalls = new ConcurrentHashMap<>();
|
||||||
|
private final AtomicLong streamsStallTime = new AtomicLong();
|
||||||
private int initialStreamSendWindow;
|
private int initialStreamSendWindow;
|
||||||
private int initialStreamRecvWindow;
|
private int initialStreamRecvWindow;
|
||||||
|
|
||||||
|
@ -174,38 +183,62 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
|
||||||
|
|
||||||
protected void onSessionStalled(ISession session)
|
protected void onSessionStalled(ISession session)
|
||||||
{
|
{
|
||||||
|
sessionStall.set(System.nanoTime());
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Session stalled {}", session);
|
LOG.debug("Session stalled {}", session);
|
||||||
sessionStalls.incrementAndGet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onStreamStalled(IStream stream)
|
protected void onStreamStalled(IStream stream)
|
||||||
{
|
{
|
||||||
|
streamsStalls.put(stream, System.nanoTime());
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Stream stalled {}", stream);
|
LOG.debug("Stream stalled {}", stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onSessionUnstalled(ISession session)
|
protected void onSessionUnstalled(ISession session)
|
||||||
{
|
{
|
||||||
|
sessionStallTime.addAndGet(System.nanoTime() - sessionStall.getAndSet(0));
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Session unstalled {}", session);
|
LOG.debug("Session unstalled {}", session);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onStreamUnstalled(IStream stream)
|
protected void onStreamUnstalled(IStream stream)
|
||||||
{
|
{
|
||||||
|
Long time = streamsStalls.remove(stream);
|
||||||
|
if (time != null)
|
||||||
|
streamsStallTime.addAndGet(System.nanoTime() - time);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Stream unstalled {}", stream);
|
LOG.debug("Stream unstalled {}", stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ManagedAttribute(value = "The number of times the session flow control has stalled", readonly = true)
|
@ManagedAttribute(value = "The time, in milliseconds, that the session flow control has stalled", readonly = true)
|
||||||
public long getSessionStallCount()
|
public long getSessionStallTime()
|
||||||
{
|
{
|
||||||
return sessionStalls.get();
|
return TimeUnit.NANOSECONDS.toMillis(sessionStallTime.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value = "The time, in milliseconds, that the streams flow control has stalled", readonly = true)
|
||||||
|
public long getStreamsStallTime()
|
||||||
|
{
|
||||||
|
return TimeUnit.NANOSECONDS.toMillis(streamsStallTime.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ManagedOperation(value = "Resets the statistics", impact = "ACTION")
|
@ManagedOperation(value = "Resets the statistics", impact = "ACTION")
|
||||||
public void reset()
|
public void reset()
|
||||||
{
|
{
|
||||||
sessionStalls.set(0);
|
sessionStallTime.set(0);
|
||||||
|
streamsStallTime.set(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String dump()
|
||||||
|
{
|
||||||
|
return ContainerLifeCycle.dump(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dump(Appendable out, String indent) throws IOException
|
||||||
|
{
|
||||||
|
out.append(toString()).append(System.lineSeparator());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,4 +198,15 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
||||||
Atomics.updateMax(maxSessionRecvWindow, sessionWindow);
|
Atomics.updateMax(maxSessionRecvWindow, sessionWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format("%s@%x[ratio=%.2f,sessionStallTime=%dms,streamsStallTime=%dms]",
|
||||||
|
getClass().getSimpleName(),
|
||||||
|
hashCode(),
|
||||||
|
bufferRatio,
|
||||||
|
getSessionStallTime(),
|
||||||
|
getStreamsStallTime());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ import org.eclipse.jetty.server.HttpConfiguration;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.annotation.Name;
|
import org.eclipse.jetty.util.annotation.Name;
|
||||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
|
||||||
import org.eclipse.jetty.util.component.LifeCycle;
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
|
|
||||||
@ManagedObject
|
@ManagedObject
|
||||||
|
@ -159,7 +158,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
||||||
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
|
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ConnectionListener extends ContainerLifeCycle implements Connection.Listener
|
private class ConnectionListener implements Connection.Listener
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onOpened(Connection connection)
|
public void onOpened(Connection connection)
|
||||||
|
|
Loading…
Reference in New Issue