Update Circuit Breaker configured as a standard plugin (#1785)

This commit is contained in:
Atri Sharma 2020-08-27 14:06:22 +05:30 committed by GitHub
parent 54a5dc2e6e
commit 6a7da3cd50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 213 additions and 112 deletions

View File

@ -78,6 +78,7 @@ import org.apache.solr.update.UpdateLog;
import org.apache.solr.update.processor.UpdateRequestProcessorChain;
import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
import org.apache.solr.util.DOMUtil;
import org.apache.solr.util.circuitbreaker.CircuitBreakerManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
@ -227,14 +228,6 @@ public class SolrConfig extends XmlConfigFile implements MapSerializable {
queryResultWindowSize = Math.max(1, getInt("query/queryResultWindowSize", 1));
queryResultMaxDocsCached = getInt("query/queryResultMaxDocsCached", Integer.MAX_VALUE);
enableLazyFieldLoading = getBool("query/enableLazyFieldLoading", false);
useCircuitBreakers = getBool("circuitBreakers/@enabled", false);
cpuCBEnabled = getBool("circuitBreakers/cpuBreaker/@enabled", false);
memCBEnabled = getBool("circuitBreakers/memBreaker/@enabled", false);
memCBThreshold = getInt("circuitBreakers/memBreaker/@threshold", 95);
cpuCBThreshold = getInt("circuitBreakers/cpuBreaker/@threshold", 95);
validateCircuitBreakerThresholds();
filterCacheConfig = CacheConfig.getConfig(this, "query/filterCache");
queryResultCacheConfig = CacheConfig.getConfig(this, "query/queryResultCache");
@ -365,6 +358,7 @@ public class SolrConfig extends XmlConfigFile implements MapSerializable {
.add(new SolrPluginInfo(IndexSchemaFactory.class, "schemaFactory", REQUIRE_CLASS))
.add(new SolrPluginInfo(RestManager.class, "restManager"))
.add(new SolrPluginInfo(StatsCache.class, "statsCache", REQUIRE_CLASS))
.add(new SolrPluginInfo(CircuitBreakerManager.class, "circuitBreaker"))
.build();
public static final Map<String, SolrPluginInfo> classVsSolrPluginInfo;
@ -531,13 +525,6 @@ public class SolrConfig extends XmlConfigFile implements MapSerializable {
public final int queryResultMaxDocsCached;
public final boolean enableLazyFieldLoading;
// Circuit Breaker Configuration
public final boolean useCircuitBreakers;
public final int memCBThreshold;
public final boolean memCBEnabled;
public final boolean cpuCBEnabled;
public final int cpuCBThreshold;
// IndexConfig settings
public final SolrIndexConfig indexConfig;
@ -817,16 +804,6 @@ public class SolrConfig extends XmlConfigFile implements MapSerializable {
loader.reloadLuceneSPI();
}
private void validateCircuitBreakerThresholds() {
if (useCircuitBreakers) {
if (memCBEnabled) {
if (memCBThreshold > 95 || memCBThreshold < 50) {
throw new IllegalArgumentException("Valid value range of memoryCircuitBreakerThresholdPct is 50 - 95");
}
}
}
}
public int getMultipartUploadLimitKB() {
return multipartUploadLimitKB;
}
@ -896,11 +873,7 @@ public class SolrConfig extends XmlConfigFile implements MapSerializable {
m.put("queryResultMaxDocsCached", queryResultMaxDocsCached);
m.put("enableLazyFieldLoading", enableLazyFieldLoading);
m.put("maxBooleanClauses", booleanQueryMaxClauseCount);
m.put("useCircuitBreakers", useCircuitBreakers);
m.put("cpuCircuitBreakerEnabled", cpuCBEnabled);
m.put("memoryCircuitBreakerEnabled", memCBEnabled);
m.put("memoryCircuitBreakerThresholdPct", memCBThreshold);
m.put("cpuCircuitBreakerThreshold", cpuCBThreshold);
for (SolrPluginInfo plugin : plugins) {
List<PluginInfo> infos = getPluginInfos(plugin.clazz.getName());
if (infos == null || infos.isEmpty()) continue;

View File

@ -1174,7 +1174,8 @@ public final class SolrCore implements SolrInfoBean, Closeable {
}
private CircuitBreakerManager initCircuitBreakerManager() {
CircuitBreakerManager circuitBreakerManager = CircuitBreakerManager.build(solrConfig);
final PluginInfo info = solrConfig.getPluginInfo(CircuitBreakerManager.class.getName());
CircuitBreakerManager circuitBreakerManager = CircuitBreakerManager.build(info);
return circuitBreakerManager;
}

View File

@ -303,7 +303,7 @@ public class SearchHandler extends RequestHandlerBase implements SolrCoreAware,
final RTimerTree timer = rb.isDebug() ? req.getRequestTimer() : null;
if (req.getCore().getSolrConfig().useCircuitBreakers) {
if (req.getCore().getCircuitBreakerManager().isEnabled()) {
List<CircuitBreaker> trippedCircuitBreakers;
if (timer != null) {

View File

@ -21,7 +21,6 @@ import java.lang.invoke.MethodHandles;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import org.apache.solr.core.SolrConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -52,11 +51,11 @@ public class CPUCircuitBreaker extends CircuitBreaker {
private static final ThreadLocal<Double> allowedCPUUsage = ThreadLocal.withInitial(() -> 0.0);
public CPUCircuitBreaker(SolrConfig solrConfig) {
super(solrConfig);
public CPUCircuitBreaker(CircuitBreakerConfig config) {
super(config);
this.enabled = solrConfig.cpuCBEnabled;
this.cpuUsageThreshold = solrConfig.cpuCBThreshold;
this.enabled = config.getCpuCBEnabled();
this.cpuUsageThreshold = config.getCpuCBThreshold();
}
@Override

View File

@ -17,8 +17,6 @@
package org.apache.solr.util.circuitbreaker;
import org.apache.solr.core.SolrConfig;
/**
* Default class to define circuit breakers for Solr.
* <p>
@ -35,16 +33,16 @@ import org.apache.solr.core.SolrConfig;
public abstract class CircuitBreaker {
public static final String NAME = "circuitbreaker";
protected final SolrConfig solrConfig;
protected final CircuitBreakerConfig config;
public CircuitBreaker(SolrConfig solrConfig) {
this.solrConfig = solrConfig;
public CircuitBreaker(CircuitBreakerConfig config) {
this.config = config;
}
// Global config for all circuit breakers. For specific circuit breaker configs, define
// your own config.
protected boolean isEnabled() {
return solrConfig.useCircuitBreakers;
return config.isEnabled();
}
/**
@ -61,4 +59,41 @@ public abstract class CircuitBreaker {
* Get error message when the circuit breaker triggers
*/
public abstract String getErrorMessage();
public static class CircuitBreakerConfig {
private final boolean enabled;
private final boolean memCBEnabled;
private final int memCBThreshold;
private final boolean cpuCBEnabled;
private final int cpuCBThreshold;
public CircuitBreakerConfig(final boolean enabled, final boolean memCBEnabled, final int memCBThreshold,
final boolean cpuCBEnabled, final int cpuCBThreshold) {
this.enabled = enabled;
this.memCBEnabled = memCBEnabled;
this.memCBThreshold = memCBThreshold;
this.cpuCBEnabled = cpuCBEnabled;
this.cpuCBThreshold = cpuCBThreshold;
}
public boolean isEnabled() {
return enabled;
}
public boolean getMemCBEnabled() {
return memCBEnabled;
}
public int getMemCBThreshold() {
return memCBThreshold;
}
public boolean getCpuCBEnabled() {
return cpuCBEnabled;
}
public int getCpuCBThreshold() {
return cpuCBThreshold;
}
}
}

View File

@ -21,7 +21,9 @@ import java.util.ArrayList;
import java.util.List;
import com.google.common.annotations.VisibleForTesting;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.util.plugin.PluginInfoInitialized;
/**
* Manages all registered circuit breaker instances. Responsible for a holistic view
@ -37,7 +39,7 @@ import org.apache.solr.core.SolrConfig;
* NOTE: The current way of registering new default circuit breakers is minimal and not a long term
* solution. There will be a follow up with a SIP for a schema API design.
*/
public class CircuitBreakerManager {
public class CircuitBreakerManager implements PluginInfoInitialized {
// Class private to potentially allow "family" of circuit breakers to be enabled or disabled
private final boolean enableCircuitBreakerManager;
@ -47,6 +49,18 @@ public class CircuitBreakerManager {
this.enableCircuitBreakerManager = enableCircuitBreakerManager;
}
@Override
public void init(PluginInfo pluginInfo) {
CircuitBreaker.CircuitBreakerConfig circuitBreakerConfig = buildCBConfig(pluginInfo);
// Install the default circuit breakers
CircuitBreaker memoryCircuitBreaker = new MemoryCircuitBreaker(circuitBreakerConfig);
CircuitBreaker cpuCircuitBreaker = new CPUCircuitBreaker(circuitBreakerConfig);
register(memoryCircuitBreaker);
register(cpuCircuitBreaker);
}
public void register(CircuitBreaker circuitBreaker) {
circuitBreakerList.add(circuitBreaker);
}
@ -121,19 +135,40 @@ public class CircuitBreakerManager {
*
* Any default circuit breakers should be registered here.
*/
public static CircuitBreakerManager build(SolrConfig solrConfig) {
CircuitBreakerManager circuitBreakerManager = new CircuitBreakerManager(solrConfig.useCircuitBreakers);
@SuppressWarnings({"rawtypes"})
public static CircuitBreakerManager build(PluginInfo pluginInfo) {
CircuitBreakerManager circuitBreakerManager = new CircuitBreakerManager(Boolean.parseBoolean(pluginInfo.attributes.get("enabled")));
// Install the default circuit breakers
CircuitBreaker memoryCircuitBreaker = new MemoryCircuitBreaker(solrConfig);
CircuitBreaker cpuCircuitBreaker = new CPUCircuitBreaker(solrConfig);
circuitBreakerManager.register(memoryCircuitBreaker);
circuitBreakerManager.register(cpuCircuitBreaker);
circuitBreakerManager.init(pluginInfo);
return circuitBreakerManager;
}
@VisibleForTesting
@SuppressWarnings({"rawtypes"})
public static CircuitBreaker.CircuitBreakerConfig buildCBConfig(PluginInfo pluginInfo) {
boolean enabled = Boolean.parseBoolean(pluginInfo.attributes.get("enabled"));
boolean cpuCBEnabled = false;
boolean memCBEnabled = false;
int memCBThreshold = 100;
int cpuCBThreshold = 100;
NamedList args = pluginInfo.initArgs;
if (args != null) {
cpuCBEnabled = args.getBooleanArg("cpuEnabled");
memCBEnabled = args.getBooleanArg("memEnabled");
memCBThreshold = Integer.parseInt((String) args.get("memThreshold"));
cpuCBThreshold = Integer.parseInt((String) args.get("cpuThreshold"));
}
return new CircuitBreaker.CircuitBreakerConfig(enabled, memCBEnabled, memCBThreshold, cpuCBEnabled, cpuCBThreshold);
}
public boolean isEnabled() {
return enableCircuitBreakerManager;
}
@VisibleForTesting
public List<CircuitBreaker> getRegisteredCircuitBreakers() {
return circuitBreakerList;

View File

@ -21,7 +21,6 @@ import java.lang.invoke.MethodHandles;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import org.apache.solr.core.SolrConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,10 +49,10 @@ public class MemoryCircuitBreaker extends CircuitBreaker {
private static final ThreadLocal<Long> seenMemory = ThreadLocal.withInitial(() -> 0L);
private static final ThreadLocal<Long> allowedMemory = ThreadLocal.withInitial(() -> 0L);
public MemoryCircuitBreaker(SolrConfig solrConfig) {
super(solrConfig);
public MemoryCircuitBreaker(CircuitBreakerConfig config) {
super(config);
this.enabled = solrConfig.memCBEnabled;
this.enabled = config.getMemCBEnabled();
long currentMaxHeap = MEMORY_MX_BEAN.getHeapMemoryUsage().getMax();
@ -61,7 +60,7 @@ public class MemoryCircuitBreaker extends CircuitBreaker {
throw new IllegalArgumentException("Invalid JVM state for the max heap usage");
}
int thresholdValueInPercentage = solrConfig.memCBThreshold;
int thresholdValueInPercentage = config.getMemCBThreshold();
double thresholdInFraction = thresholdValueInPercentage / (double) 100;
heapMemoryThreshold = (long) (currentMaxHeap * thresholdInFraction);

View File

@ -55,17 +55,6 @@
"queryResultMaxDocsCached":1,
"enableLazyFieldLoading":1,
"boolTofilterOptimizer":1,
"circuitBreakers":{
"enabled":10,
"memBreaker":{
"enabled":10,
"threshold":20
},
"cpuBreaker":{
"enabled":10,
"threshold":20
}
},
"maxBooleanClauses":1},
"jmx":{
"agentId":0,

View File

@ -78,10 +78,12 @@
</query>
<circuitBreakers enabled="true">
<cpuBreaker enabled="true" threshold="75"/>
<memBreaker enabled="true" threshold="75"/>
</circuitBreakers>
<circuitBreaker class="solr.CircuitBreakerManager" enabled="true">
<str name="memEnabled">true</str>
<str name="memThreshold">75</str>
<str name="cpuEnabled">true</str>
<str name="cpuThreshold">75</str>
</circuitBreaker>
<initParams path="/select">
<lst name="defaults">

View File

@ -266,9 +266,6 @@ public class SolrCoreTest extends SolrTestCaseJ4 {
assertEquals("wrong config for maxBooleanClauses", 1024, solrConfig.booleanQueryMaxClauseCount);
assertEquals("wrong config for enableLazyFieldLoading", true, solrConfig.enableLazyFieldLoading);
assertEquals("wrong config for queryResultWindowSize", 10, solrConfig.queryResultWindowSize);
assertEquals("wrong config for useCircuitBreakers", false, solrConfig.useCircuitBreakers);
assertEquals("wrong config for memoryCircuitBreakerThresholdPct", 95, solrConfig.memCBThreshold);
assertEquals("wrong config for cpuCircuitBreakerThreshold", 95, solrConfig.cpuCBThreshold);
}
/**

View File

@ -46,11 +46,6 @@ public class TestConfigOverlay extends SolrTestCase {
assertTrue(isEditableProp("query.queryResultMaxDocsCached", false, null));
assertTrue(isEditableProp("query.enableLazyFieldLoading", false, null));
assertTrue(isEditableProp("query.boolTofilterOptimizer", false, null));
assertTrue(isEditableProp("query.circuitBreakers.enabled", false, null));
assertTrue(isEditableProp("query.circuitBreakers.memBreaker.enabled", false, null));
assertTrue(isEditableProp("query.circuitBreakers.memBreaker.threshold", false, null));
assertTrue(isEditableProp("query.circuitBreakers.cpuBreaker.enabled", false, null));
assertTrue(isEditableProp("query.circuitBreakers.cpuBreaker.threshold", false, null));
assertTrue(isEditableProp("jmx.agentId", false, null));
assertTrue(isEditableProp("jmx.serviceUrl", false, null));
assertTrue(isEditableProp("jmx.rootName", false, null));

View File

@ -32,10 +32,11 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.util.circuitbreaker.CPUCircuitBreaker;
import org.apache.solr.util.circuitbreaker.CircuitBreaker;
import org.apache.solr.util.circuitbreaker.CircuitBreakerManager;
import org.apache.solr.util.circuitbreaker.MemoryCircuitBreaker;
import org.junit.After;
import org.junit.BeforeClass;
@ -93,7 +94,11 @@ public class TestCircuitBreaker extends SolrTestCaseJ4 {
removeAllExistingCircuitBreakers();
CircuitBreaker circuitBreaker = new MockCircuitBreaker(h.getCore().getSolrConfig());
PluginInfo pluginInfo = h.getCore().getSolrConfig().getPluginInfo(CircuitBreakerManager.class.getName());
CircuitBreaker.CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerManager.buildCBConfig(pluginInfo);
CircuitBreaker circuitBreaker = new MockCircuitBreaker(circuitBreakerConfig);
h.getCore().getCircuitBreakerManager().register(circuitBreaker);
@ -110,7 +115,10 @@ public class TestCircuitBreaker extends SolrTestCaseJ4 {
removeAllExistingCircuitBreakers();
CircuitBreaker circuitBreaker = new FakeMemoryPressureCircuitBreaker(h.getCore().getSolrConfig());
PluginInfo pluginInfo = h.getCore().getSolrConfig().getPluginInfo(CircuitBreakerManager.class.getName());
CircuitBreaker.CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerManager.buildCBConfig(pluginInfo);
CircuitBreaker circuitBreaker = new FakeMemoryPressureCircuitBreaker(circuitBreakerConfig);
h.getCore().getCircuitBreakerManager().register(circuitBreaker);
@ -132,7 +140,10 @@ public class TestCircuitBreaker extends SolrTestCaseJ4 {
try {
removeAllExistingCircuitBreakers();
CircuitBreaker circuitBreaker = new BuildingUpMemoryPressureCircuitBreaker(h.getCore().getSolrConfig());
PluginInfo pluginInfo = h.getCore().getSolrConfig().getPluginInfo(CircuitBreakerManager.class.getName());
CircuitBreaker.CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerManager.buildCBConfig(pluginInfo);
CircuitBreaker circuitBreaker = new BuildingUpMemoryPressureCircuitBreaker(circuitBreakerConfig);
h.getCore().getCircuitBreakerManager().register(circuitBreaker);
@ -185,7 +196,10 @@ public class TestCircuitBreaker extends SolrTestCaseJ4 {
try {
removeAllExistingCircuitBreakers();
CircuitBreaker circuitBreaker = new FakeCPUCircuitBreaker(h.getCore().getSolrConfig());
PluginInfo pluginInfo = h.getCore().getSolrConfig().getPluginInfo(CircuitBreakerManager.class.getName());
CircuitBreaker.CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerManager.buildCBConfig(pluginInfo);
CircuitBreaker circuitBreaker = new FakeCPUCircuitBreaker(circuitBreakerConfig);
h.getCore().getCircuitBreakerManager().register(circuitBreaker);
@ -260,8 +274,8 @@ public class TestCircuitBreaker extends SolrTestCaseJ4 {
private static class MockCircuitBreaker extends MemoryCircuitBreaker {
public MockCircuitBreaker(SolrConfig solrConfig) {
super(solrConfig);
public MockCircuitBreaker(CircuitBreakerConfig config) {
super(config);
}
@Override
@ -278,8 +292,8 @@ public class TestCircuitBreaker extends SolrTestCaseJ4 {
private static class FakeMemoryPressureCircuitBreaker extends MemoryCircuitBreaker {
public FakeMemoryPressureCircuitBreaker(SolrConfig solrConfig) {
super(solrConfig);
public FakeMemoryPressureCircuitBreaker(CircuitBreakerConfig config) {
super(config);
}
@Override
@ -292,8 +306,8 @@ public class TestCircuitBreaker extends SolrTestCaseJ4 {
private static class BuildingUpMemoryPressureCircuitBreaker extends MemoryCircuitBreaker {
private AtomicInteger count;
public BuildingUpMemoryPressureCircuitBreaker(SolrConfig solrConfig) {
super(solrConfig);
public BuildingUpMemoryPressureCircuitBreaker(CircuitBreakerConfig config) {
super(config);
this.count = new AtomicInteger(0);
}
@ -321,8 +335,8 @@ public class TestCircuitBreaker extends SolrTestCaseJ4 {
}
private static class FakeCPUCircuitBreaker extends CPUCircuitBreaker {
public FakeCPUCircuitBreaker(SolrConfig solrConfig) {
super(solrConfig);
public FakeCPUCircuitBreaker(CircuitBreakerConfig config) {
super(config);
}
@Override

View File

@ -550,7 +550,7 @@
Circuit Breaker Section - This section consists of configurations for
circuit breakers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<circuitBreaker>
<circuitBreaker class="solr.CircuitBreakerManager" enabled="true">
<!-- Enable Circuit Breakers
Circuit breakers are designed to allow stability and predictable query
@ -563,7 +563,12 @@
they are free to add their specific configuration but need to ensure that this flag is always
respected - this should have veto over all independent configuration flags.
-->
<useCircuitBreakers>false</useCircuitBreakers>
<!-- Memory Circuit Breaker Control Flag
Use the following flag to control the behaviour of this circuit breaker
-->
<str name="memEnabled">true</str>
<!-- Memory Circuit Breaker Threshold In Percentage
@ -580,7 +585,20 @@
in logs and the corresponding error message should tell you what transpired (if the failure
was caused by tripped circuit breakers).
-->
<memoryCircuitBreakerThresholdPct>100</memoryCircuitBreakerThresholdPct>
<str name="memThreshold">75</str>
<!-- CPU Based Circuit Breaker Control Flag
Use the following flag to control the behaviour of this circuit breaker
-->
<str name="cpuEnabled">true</str>
<!-- CPU Based Circuit Breaker Triggering Threshold
The triggering threshold is defined in units of CPU utilization. The configuration to control this is as below:
-->
<str name="cpuThreshold">75</str>
</circuitBreaker>

View File

@ -27,19 +27,24 @@ are enabled, requests may be rejected under the condition of high node duress wi
It is up to the client to handle this error and potentially build a retrial logic as this should ideally be a transient situation.
== Circuit Breaker Configurations
The following flag controls the global activation/deactivation of circuit breakers. If this flag is disabled, all circuit breakers
will be disabled globally. Per circuit breaker configurations are specified in their respective sections later.
All circuit breaker configurations are listed in the circuitBreaker tags in solrconfig.xml as shown below:
[source,xml]
----
<circuitBreakers enabled="true">
<circuitBreaker class="solr.CircuitBreakerManager" enabled="true">
<!-- All specific configs in this section -->
</circuitBreakers>
</circuitBreaker>
----
This flag acts as the highest authority and global controller of circuit breakers. For using specific circuit breakers, each one
The "enabled" attribute controls the global activation/deactivation of circuit breakers. If this flag is disabled, all circuit breakers
will be disabled globally. Per circuit breaker configurations are specified in their respective sections later.
This attribute acts as the highest authority and global controller of circuit breakers. For using specific circuit breakers, each one
needs to be individually enabled in addition to this flag being enabled.
CircuitBreakerManager is the default manager for all circuit breakers that should be defined in the tag unless the user wishes to use
a custom implementation.
== Currently Supported Circuit Breakers
=== JVM Heap Usage Based Circuit Breaker
@ -51,11 +56,18 @@ Configuration for JVM heap usage based circuit breaker:
[source,xml]
----
<memBreaker enabled="true" threshold="75"/>
<str name="memEnabled">true</str>
----
Note that this configuration will be overridden by the global circuit breaker flag -- if circuit breakers are disabled, this flag
will not help you. Also, the triggering threshold is defined as a percentage of the max heap allocated to the JVM.
will not help you.
The triggering threshold is defined as a percentage of the max heap allocated to the JVM. It is controlled by the below configuration:
[source,xml]
----
<str name="memThreshold">75</str>
----
It does not logically make sense to have a threshold below 50% and above 95% of the max heap allocated to the JVM. Hence, the range
of valid values for this parameter is [50, 95], both inclusive.
@ -76,11 +88,18 @@ Configuration for CPU utilization based circuit breaker:
[source,xml]
----
<cpuBreaker enabled="true" threshold="20"/>
<str name="cpuEnabled">true</str>
----
Note that this configuration will be overridden by the global circuit breaker flag -- if circuit breakers are disabled, this flag
will not help you. The triggering threshold is defined in units of CPU utilization.
will not help you.
The triggering threshold is defined in units of CPU utilization. The configuration to control this is as below:
[source,xml]
----
<str name="cpuThreshold">75</str>
----
== Performance Considerations
It is worth noting that while JVM or CPU circuit breakers do not add any noticeable overhead per query, having too many

View File

@ -172,24 +172,49 @@ This parameter sets the maximum number of documents to cache for any entry in th
<queryResultMaxDocsCached>200</queryResultMaxDocsCached>
----
=== useCircuitBreakers
=== circuitBreaker
Global control flag for enabling circuit breakers.
This set of configurations control the behaviour of circuit breakers.
[source,xml]
----
<useCircuitBreakers>true</useCircuitBreakers>
<circuitBreaker class="solr.CircuitBreakerManager" enabled="true">
<!-- All specific configs in this section -->
</circuitBreaker>
----
=== memoryCircuitBreakerThresholdPct
To control whether Circuit Breakers are globally enabled, use the "enabled" attribute.
=== Memory Circuit Breaker Settings
To turn memory circuit breaker on/off, use the following flag:
[source,xml]
----
<str name="memEnabled">true</str>
----
Memory threshold in percentage for JVM heap usage defined in percentage of maximum heap allocated
to the JVM (-Xmx). Ideally, this value should be in the range of 75-80% of maximum heap allocated
to the JVM.
to the JVM. The enabled flag can be used to control the specific toggle for this circuit breaker.
[source,xml]
----
<memoryCircuitBreakerThresholdPct>75</memoryCircuitBreakerThresholdPct>
<str name="memThreshold">75</str>
----
=== CPU Circuit Breaker Settings
To control turning on/off this feature, use the following flag:
[source,xml]
----
<str name="cpuEnabled">true</str>
----
Defines the triggering threshold in terms of the average per minute CPU load. The enabled flag can be used to control the specific toggle for this circuit breaker.
[source,xml]
----
<str name="cpuThreshold">75</str>
----
=== useColdSearcher