Fixes #2828 - AbstractHTTP2ServerConnectionFactory concurrent connect low performance.
Now HTTP/2 sessions are not added to the Jetty component tree, but rather just held by HTTP2SessionContainer that is added to the Jetty container tree at startup. HTTP2SessionContainer uses a concurrent Set to hold HTTP/2 sessions to have good add/remove performance. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
ddd80deeb9
commit
d3e75c5936
|
@ -18,13 +18,17 @@
|
|||
|
||||
package org.eclipse.jetty.http2.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.jetty.http2.BufferingFlowControlStrategy;
|
||||
import org.eclipse.jetty.http2.FlowControlStrategy;
|
||||
import org.eclipse.jetty.http2.HTTP2Connection;
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.api.server.ServerSessionListener;
|
||||
import org.eclipse.jetty.http2.frames.Frame;
|
||||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
||||
|
@ -38,12 +42,14 @@ import org.eclipse.jetty.server.HttpConfiguration;
|
|||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
|
||||
@ManagedObject
|
||||
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
|
||||
{
|
||||
private final Connection.Listener connectionListener = new ConnectionListener();
|
||||
private final HTTP2SessionContainer sessionContainer = new HTTP2SessionContainer();
|
||||
private final HttpConfiguration httpConfiguration;
|
||||
private int maxDynamicTableSize = 4096;
|
||||
private int initialSessionRecvWindow = 1024 * 1024;
|
||||
|
@ -66,6 +72,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
for (String p:protocols)
|
||||
if (!HTTP2ServerConnection.isSupportedProtocol(p))
|
||||
throw new IllegalArgumentException("Unsupported HTTP2 Protocol variant: "+p);
|
||||
addBean(sessionContainer);
|
||||
this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
|
||||
addBean(httpConfiguration);
|
||||
setInputBufferSize(Frame.DEFAULT_MAX_LENGTH + Frame.HEADER_LENGTH);
|
||||
|
@ -234,7 +241,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
|
||||
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
|
||||
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
||||
connection.addListener(connectionListener);
|
||||
connection.addListener(sessionContainer);
|
||||
return configure(connection, connector, endPoint);
|
||||
}
|
||||
|
||||
|
@ -245,18 +252,43 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
|
||||
}
|
||||
|
||||
private class ConnectionListener implements Connection.Listener
|
||||
private class HTTP2SessionContainer implements Connection.Listener, Dumpable
|
||||
{
|
||||
private final Set<Session> sessions = ConcurrentHashMap.newKeySet();
|
||||
|
||||
@Override
|
||||
public void onOpened(Connection connection)
|
||||
{
|
||||
addManaged((LifeCycle)((HTTP2Connection)connection).getSession());
|
||||
Session session = ((HTTP2Connection)connection).getSession();
|
||||
sessions.add(session);
|
||||
LifeCycle.start(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(Connection connection)
|
||||
{
|
||||
removeBean(((HTTP2Connection)connection).getSession());
|
||||
Session session = ((HTTP2Connection)connection).getSession();
|
||||
if (sessions.remove(session))
|
||||
LifeCycle.stop(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dump()
|
||||
{
|
||||
return ContainerLifeCycle.dump(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
ContainerLifeCycle.dumpObject(out, this);
|
||||
ContainerLifeCycle.dump(out, indent, sessions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x[size=%d]", getClass().getSimpleName(), hashCode(), sessions.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue