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;
|
package org.eclipse.jetty.http2.server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.eclipse.jetty.http2.BufferingFlowControlStrategy;
|
import org.eclipse.jetty.http2.BufferingFlowControlStrategy;
|
||||||
import org.eclipse.jetty.http2.FlowControlStrategy;
|
import org.eclipse.jetty.http2.FlowControlStrategy;
|
||||||
import org.eclipse.jetty.http2.HTTP2Connection;
|
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.api.server.ServerSessionListener;
|
||||||
import org.eclipse.jetty.http2.frames.Frame;
|
import org.eclipse.jetty.http2.frames.Frame;
|
||||||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
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.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.Dumpable;
|
||||||
import org.eclipse.jetty.util.component.LifeCycle;
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
|
|
||||||
@ManagedObject
|
@ManagedObject
|
||||||
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
|
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
|
||||||
{
|
{
|
||||||
private final Connection.Listener connectionListener = new ConnectionListener();
|
private final HTTP2SessionContainer sessionContainer = new HTTP2SessionContainer();
|
||||||
private final HttpConfiguration httpConfiguration;
|
private final HttpConfiguration httpConfiguration;
|
||||||
private int maxDynamicTableSize = 4096;
|
private int maxDynamicTableSize = 4096;
|
||||||
private int initialSessionRecvWindow = 1024 * 1024;
|
private int initialSessionRecvWindow = 1024 * 1024;
|
||||||
|
@ -66,6 +72,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
||||||
for (String p:protocols)
|
for (String p:protocols)
|
||||||
if (!HTTP2ServerConnection.isSupportedProtocol(p))
|
if (!HTTP2ServerConnection.isSupportedProtocol(p))
|
||||||
throw new IllegalArgumentException("Unsupported HTTP2 Protocol variant: "+p);
|
throw new IllegalArgumentException("Unsupported HTTP2 Protocol variant: "+p);
|
||||||
|
addBean(sessionContainer);
|
||||||
this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
|
this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
|
||||||
addBean(httpConfiguration);
|
addBean(httpConfiguration);
|
||||||
setInputBufferSize(Frame.DEFAULT_MAX_LENGTH + Frame.HEADER_LENGTH);
|
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(),
|
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
|
||||||
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
||||||
connection.addListener(connectionListener);
|
connection.addListener(sessionContainer);
|
||||||
return configure(connection, connector, endPoint);
|
return configure(connection, connector, endPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,18 +252,43 @@ 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 class ConnectionListener implements Connection.Listener
|
private class HTTP2SessionContainer implements Connection.Listener, Dumpable
|
||||||
{
|
{
|
||||||
|
private final Set<Session> sessions = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpened(Connection connection)
|
public void onOpened(Connection connection)
|
||||||
{
|
{
|
||||||
addManaged((LifeCycle)((HTTP2Connection)connection).getSession());
|
Session session = ((HTTP2Connection)connection).getSession();
|
||||||
|
sessions.add(session);
|
||||||
|
LifeCycle.start(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClosed(Connection connection)
|
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