Skip to content

Commit

Permalink
Issue #5287 - share compression pools and size with max num threads
Browse files Browse the repository at this point in the history
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
  • Loading branch information
lachlan-roberts committed Oct 2, 2020
1 parent 21e00c0 commit 8325608
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@
import org.eclipse.jetty.http.pathmap.PathSpecSet;
import org.eclipse.jetty.server.HttpOutput;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.AsciiLowerCaseSet;
import org.eclipse.jetty.util.IncludeExclude;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.compression.CompressionPool;
import org.eclipse.jetty.util.compression.DeflaterPool;
import org.eclipse.jetty.util.compression.InflaterPool;
import org.slf4j.Logger;
Expand Down Expand Up @@ -163,9 +163,8 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
private static final HttpField TE_CHUNKED = new PreEncodedHttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED.asString());
private static final Pattern COMMA_GZIP = Pattern.compile(".*, *gzip");

private final InflaterPool _inflaterPool;
private final DeflaterPool _deflaterPool;

private InflaterPool _inflaterPool;
private DeflaterPool _deflaterPool;
private int _minGzipSize = DEFAULT_MIN_GZIP_SIZE;
private boolean _syncFlush = false;
private int _inflateBufferSize = -1;
Expand Down Expand Up @@ -202,11 +201,15 @@ else if (type.startsWith("image/") ||

if (LOG.isDebugEnabled())
LOG.debug("{} mime types {}", this, _mimeTypes);
}

_deflaterPool = newDeflaterPool();
_inflaterPool = newInflaterPool();
addBean(_deflaterPool);
addBean(_inflaterPool);
@Override
protected void doStart() throws Exception
{
Server server = getServer();
_inflaterPool = InflaterPool.ensurePool(server);
_deflaterPool = DeflaterPool.ensurePool(server);
super.doStart();
}

/**
Expand Down Expand Up @@ -921,16 +924,6 @@ public void setInflaterPoolCapacity(int capacity)
_inflaterPool.setCapacity(capacity);
}

protected InflaterPool newInflaterPool()
{
return new InflaterPool(CompressionPool.DEFAULT_CAPACITY, true);
}

protected DeflaterPool newDeflaterPool()
{
return new DeflaterPool(CompressionPool.DEFAULT_CAPACITY, Deflater.DEFAULT_COMPRESSION, true);
}

@Override
public String toString()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

import java.util.zip.Deflater;

import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.thread.ThreadPool;

public class DeflaterPool extends CompressionPool<Deflater>
{
private final int compressionLevel;
Expand Down Expand Up @@ -60,4 +63,20 @@ protected void reset(Deflater deflater)
{
deflater.reset();
}

public static DeflaterPool ensurePool(ContainerLifeCycle containerLifeCycle)
{
DeflaterPool pool = containerLifeCycle.getBean(DeflaterPool.class);
if (pool != null)
return pool;

int capacity = CompressionPool.DEFAULT_CAPACITY;
ThreadPool.SizedThreadPool threadPool = containerLifeCycle.getBean(ThreadPool.SizedThreadPool.class);
if (threadPool != null)
capacity = threadPool.getMaxThreads();

pool = new DeflaterPool(capacity, Deflater.DEFAULT_COMPRESSION, true);
containerLifeCycle.addBean(pool);
return pool;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

import java.util.zip.Inflater;

import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.thread.ThreadPool;

public class InflaterPool extends CompressionPool<Inflater>
{
private final boolean nowrap;
Expand Down Expand Up @@ -57,4 +60,20 @@ protected void reset(Inflater inflater)
{
inflater.reset();
}

public static InflaterPool ensurePool(ContainerLifeCycle containerLifeCycle)
{
InflaterPool pool = containerLifeCycle.getBean(InflaterPool.class);
if (pool != null)
return pool;

int capacity = CompressionPool.DEFAULT_CAPACITY;
ThreadPool.SizedThreadPool threadPool = containerLifeCycle.getBean(ThreadPool.SizedThreadPool.class);
if (threadPool != null)
capacity = threadPool.getMaxThreads();

pool = new InflaterPool(capacity, true);
containerLifeCycle.addBean(pool);
return pool;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.compression.CompressionPool;
import org.eclipse.jetty.util.compression.DeflaterPool;
import org.eclipse.jetty.util.compression.InflaterPool;
Expand All @@ -31,7 +32,7 @@
* A collection of components which are the resources needed for websockets such as
* {@link ByteBufferPool}, {@link WebSocketExtensionRegistry}, and {@link DecoratedObjectFactory}.
*/
public class WebSocketComponents
public class WebSocketComponents extends ContainerLifeCycle
{
private final DecoratedObjectFactory objectFactory;
private final WebSocketExtensionRegistry extensionRegistry;
Expand All @@ -41,19 +42,20 @@ public class WebSocketComponents

public WebSocketComponents()
{
this(new WebSocketExtensionRegistry(), new DecoratedObjectFactory(), new MappedByteBufferPool(),
new InflaterPool(CompressionPool.DEFAULT_CAPACITY, true),
new DeflaterPool(CompressionPool.DEFAULT_CAPACITY, Deflater.DEFAULT_COMPRESSION, true));
this(null, null, null, null, null);
}

public WebSocketComponents(WebSocketExtensionRegistry extensionRegistry, DecoratedObjectFactory objectFactory,
ByteBufferPool bufferPool, InflaterPool inflaterPool, DeflaterPool deflaterPool)
{
this.extensionRegistry = extensionRegistry;
this.objectFactory = objectFactory;
this.bufferPool = bufferPool;
this.deflaterPool = deflaterPool;
this.inflaterPool = inflaterPool;
this.extensionRegistry = (extensionRegistry == null) ? new WebSocketExtensionRegistry() : extensionRegistry;
this.objectFactory = (objectFactory == null) ? new DecoratedObjectFactory() : objectFactory;
this.bufferPool = (bufferPool == null) ? new MappedByteBufferPool() : bufferPool;
this.inflaterPool = (inflaterPool == null) ? new InflaterPool(CompressionPool.DEFAULT_CAPACITY, true) : inflaterPool;
this.deflaterPool = (deflaterPool == null) ? new DeflaterPool(CompressionPool.DEFAULT_CAPACITY, Deflater.DEFAULT_COMPRESSION, true) : deflaterPool;

addBean(inflaterPool);
addBean(deflaterPool);
}

public ByteBufferPool getBufferPool()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,50 @@
import javax.servlet.ServletContext;

import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.compression.DeflaterPool;
import org.eclipse.jetty.util.compression.InflaterPool;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry;

/**
* A collection of components which are the resources needed for websockets such as
* {@link ByteBufferPool}, {@link WebSocketExtensionRegistry}, and {@link DecoratedObjectFactory}.
*
* These components should be accessed through {@link WebSocketServerComponents#ensureWebSocketComponents} so that
* These components should be accessed through {@link WebSocketServerComponents#getWebSocketComponents} so that
* the instance can be shared by being stored as a bean on the ContextHandler.
*/
public class WebSocketServerComponents extends WebSocketComponents
{
public static final String WEBSOCKET_COMPONENTS_ATTRIBUTE = WebSocketComponents.class.getName();

public static WebSocketComponents ensureWebSocketComponents(ServletContext servletContext)
WebSocketServerComponents(InflaterPool inflaterPool, DeflaterPool deflaterPool)
{
// Ensure a mapping exists
WebSocketComponents components = (WebSocketComponents)servletContext.getAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
super(null, null, null, inflaterPool, deflaterPool);
}

public static WebSocketComponents ensureWebSocketComponents(Server server, ServletContext servletContext)
{
WebSocketComponents components = server.getBean(WebSocketComponents.class);
if (components == null)
{
components = new WebSocketServerComponents();
servletContext.setAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE, components);
InflaterPool inflaterPool = InflaterPool.ensurePool(server);
DeflaterPool deflaterPool = DeflaterPool.ensurePool(server);
components = new WebSocketServerComponents(inflaterPool, deflaterPool);
server.addBean(components);
}

servletContext.setAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE, components);
return components;
}

public static WebSocketComponents getWebSocketComponents(ServletContext servletContext)
{
WebSocketComponents components = (WebSocketComponents)servletContext.getAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
if (components == null)
throw new IllegalStateException("WebSocketComponents has not been created");

return components;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ private static ServerContainer initialize(ServletContextHandler context)
JavaxWebSocketServerContainer serverContainer = JavaxWebSocketServerContainer.getContainer(context.getServletContext());
if (serverContainer == null)
{
WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(context.getServletContext());
WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(context.getServer(), context.getServletContext());
FilterHolder filterHolder = WebSocketUpgradeFilter.ensureFilter(context.getServletContext());
WebSocketMapping mapping = WebSocketMapping.ensureMapping(context.getServletContext(), WebSocketMapping.DEFAULT_KEY);
serverContainer = JavaxWebSocketServerContainer.ensureContainer(context.getServletContext());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public static JavaxWebSocketServerContainer ensureContainer(ServletContext servl
// Create the Jetty ServerContainer implementation
container = new JavaxWebSocketServerContainer(
WebSocketMapping.ensureMapping(servletContext, WebSocketMapping.DEFAULT_KEY),
WebSocketServerComponents.ensureWebSocketComponents(servletContext),
WebSocketServerComponents.getWebSocketComponents(servletContext),
coreClientSupplier);
contextHandler.addManaged(container);
contextHandler.addEventListener(container);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public static JettyWebSocketServerContainer ensureContainer(ServletContext servl
container = new JettyWebSocketServerContainer(
contextHandler,
WebSocketMapping.ensureMapping(servletContext, WebSocketMapping.DEFAULT_KEY),
WebSocketServerComponents.ensureWebSocketComponents(servletContext), executor);
WebSocketServerComponents.getWebSocketComponents(servletContext), executor);
servletContext.setAttribute(JETTY_WEBSOCKET_CONTAINER_ATTRIBUTE, container);
contextHandler.addManaged(container);
contextHandler.addEventListener(container);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public void init() throws ServletException
{
ServletContext servletContext = getServletContext();

components = WebSocketServerComponents.ensureWebSocketComponents(servletContext);
components = WebSocketServerComponents.getWebSocketComponents(servletContext);
mapping = new WebSocketMapping(components);

String max = getInitParameter("idleTimeout");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public static void configure(ServletContextHandler context, Configurator configu
*/
private static JettyWebSocketServerContainer initialize(ServletContextHandler context)
{
WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(context.getServletContext());
WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(context.getServer(), context.getServletContext());
WebSocketMapping mapping = WebSocketMapping.ensureMapping(context.getServletContext(), WebSocketMapping.DEFAULT_KEY);
JettyWebSocketServerContainer container = JettyWebSocketServerContainer.ensureContainer(context.getServletContext());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void start() throws Exception
JettyWebSocketServletContainerInitializer.configure(contextHandler, (context, container) ->
{
container.addMapping("/", (req, resp) -> serverSocket);
WebSocketComponents components = WebSocketServerComponents.ensureWebSocketComponents(context);
WebSocketComponents components = WebSocketServerComponents.getWebSocketComponents(context);
components.getExtensionRegistry().register(BlockingOutgoingExtension.class.getName(), BlockingOutgoingExtension.class);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public void init(FilterConfig config) throws ServletException
if (mappingKey != null)
mapping = WebSocketMapping.ensureMapping(context, mappingKey);
else
mapping = new WebSocketMapping(WebSocketServerComponents.ensureWebSocketComponents(context));
mapping = new WebSocketMapping(WebSocketServerComponents.getWebSocketComponents(context));

String max = config.getInitParameter("idleTimeout");
if (max == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public static WebSocketMapping ensureMapping(ServletContext servletContext, Stri

if (mapping == null)
{
mapping = new WebSocketMapping(WebSocketServerComponents.ensureWebSocketComponents(servletContext));
mapping = new WebSocketMapping(WebSocketServerComponents.getWebSocketComponents(servletContext));
servletContext.setAttribute(mappingKey, mapping);
}

Expand Down

0 comments on commit 8325608

Please sign in to comment.