diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 1129ff12f92..bac5b424e5d 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -248,6 +248,9 @@ Optimizations * SOLR-12333: Removed redundant lines for handling lists in JSON reponse writers. (David Smiley via Mikhail Khludnev) +* SOLR-11880: Avoid creating new exceptions for every request made to MDCAwareThreadPoolExecutor by distributed + search and update operations. (Varun Thacker, shalin) + Other Changes ---------------------- diff --git a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java index 4e2a794ce0a..b0d3dd8046b 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java +++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java @@ -81,8 +81,11 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory implements org. 0, Integer.MAX_VALUE, 5, TimeUnit.SECONDS, // terminate idle threads after 5 sec - new SynchronousQueue(), // directly hand off tasks - new DefaultSolrThreadFactory("httpShardExecutor") + new SynchronousQueue<>(), // directly hand off tasks + new DefaultSolrThreadFactory("httpShardExecutor"), + // the Runnable added to this executor handles all exceptions so we disable stack trace collection as an optimization + // see SOLR-11880 for more details + false ); protected InstrumentedPoolingHttpClientConnectionManager clientConnectionManager; diff --git a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java index ecc843fc451..8adf90205b8 100644 --- a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java +++ b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java @@ -20,7 +20,9 @@ import java.lang.invoke.MethodHandles; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import com.codahale.metrics.MetricRegistry; import org.apache.http.client.HttpClient; @@ -52,8 +54,13 @@ public class UpdateShardHandler implements SolrMetricProducer, SolrInfoBean { * and then undetected shard inconsistency as a result. * Therefore this thread pool is left unbounded. See SOLR-8205 */ - private ExecutorService updateExecutor = ExecutorUtil.newMDCAwareCachedThreadPool( - new SolrjNamedThreadFactory("updateExecutor")); + private ExecutorService updateExecutor = new ExecutorUtil.MDCAwareThreadPoolExecutor(0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue<>(), + new SolrjNamedThreadFactory("updateExecutor"), + // the Runnable added to this executor handles all exceptions so we disable stack trace collection as an optimization + // see SOLR-11880 for more details + false); private ExecutorService recoveryExecutor; diff --git a/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java b/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java index 74580167984..f56f7822364 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/ExecutorUtil.java @@ -105,7 +105,7 @@ public class ExecutorUtil { public static ExecutorService newMDCAwareSingleThreadExecutor(ThreadFactory threadFactory) { return new MDCAwareThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(), + new LinkedBlockingQueue<>(), threadFactory); } @@ -122,7 +122,7 @@ public class ExecutorUtil { public static ExecutorService newMDCAwareCachedThreadPool(ThreadFactory threadFactory) { return new MDCAwareThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, - new SynchronousQueue(), + new SynchronousQueue<>(), threadFactory); } @@ -131,20 +131,30 @@ public class ExecutorUtil { private static final int MAX_THREAD_NAME_LEN = 512; + private final boolean enableSubmitterStackTrace; + public MDCAwareThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); + this.enableSubmitterStackTrace = true; } public MDCAwareThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); + this.enableSubmitterStackTrace = true; } public MDCAwareThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, true); + } + + public MDCAwareThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, boolean enableSubmitterStackTrace) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); + this.enableSubmitterStackTrace = enableSubmitterStackTrace; } public MDCAwareThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); + this.enableSubmitterStackTrace = true; } @Override @@ -164,7 +174,7 @@ public class ExecutorUtil { String ctxStr = contextString.toString().replace("/", "//"); final String submitterContextStr = ctxStr.length() <= MAX_THREAD_NAME_LEN ? ctxStr : ctxStr.substring(0, MAX_THREAD_NAME_LEN); - final Exception submitterStackTrace = new Exception("Submitter stack trace"); + final Exception submitterStackTrace = enableSubmitterStackTrace ? new Exception("Submitter stack trace") : null; final List providersCopy = providers; final ArrayList ctx = providersCopy.isEmpty() ? null : new ArrayList<>(providersCopy.size()); if (ctx != null) { @@ -194,7 +204,11 @@ public class ExecutorUtil { if (t instanceof OutOfMemoryError) { throw t; } - log.error("Uncaught exception {} thrown by thread: {}", t, currentThread.getName(), submitterStackTrace); + if (enableSubmitterStackTrace) { + log.error("Uncaught exception {} thrown by thread: {}", t, currentThread.getName(), submitterStackTrace); + } else { + log.error("Uncaught exception {} thrown by thread: {}", t, currentThread.getName()); + } throw t; } finally { isServerPool.remove();