断路器

Solr 的断路器基础设施可以防止导致节点超出其容量或宕机的操作。断路器的前提是确保更高的服务质量,并且只接受在当前资源配置中可服务的请求负载。

何时使用断路器

当用户希望用请求吞吐量换取更高的 Solr 稳定性时,应使用断路器。如果启用了断路器,则可能会在节点压力较大的情况下拒绝请求,并显示 HTTP 错误代码 429“请求过多”。

客户端需要处理此错误,并可能构建重试逻辑,因为这应该是一个瞬态情况。

在对分片集合的请求中,断路器仅在处理初始请求的节点上进行检查,而不针对节点间请求进行检查。因此,建议在 Solr 节点之间对客户端请求进行负载平衡,以避免热点。

断路器配置

断路器可以针对整个节点全局配置,也可以针对每个集合单独配置,或进行组合配置。在全局断路器之前检查每个集合的断路器,并且如果存在冲突,则每个集合的断路器优先。通常,任何每个集合的断路器阈值都低于全局阈值。

断路器可以注册自身以针对查询请求和/或更新请求进行检查。用户可以针对每种请求类型注册具有不同阈值的相同类型的断路器。

全局断路器

可以使用环境变量(例如,在 solr.in.sh 中)或系统属性在全局范围内配置断路器。可用的变量为

名称 环境变量名称 系统属性名称

JVM 堆使用情况

SOLR_CIRCUITBREAKER_QUERY_MEMSOLR_CIRCUITBREAKER_UPDATE_MEM

solr.circuitbreaker.query.memsolr.circuitbreaker.update.mem

系统 CPU 使用情况

SOLR_CIRCUITBREAKER_QUERY_CPUSOLR_CIRCUITBREAKER_UPDATE_CPU

solr.circuitbreaker.query.cpusolr.circuitbreaker.update.cpu

系统负载平均值

SOLR_CIRCUITBREAKER_QUERY_LOADAVGSOLR_CIRCUITBREAKER_UPDATE_LOADAVG

solr.circuitbreaker.query.loadavgsolr.circuitbreaker.update.loadavg

例如,您可以通过设置以下环境变量来启用一个全局 CPU 断路器,当 CPU 负载高于 95% 时拒绝更新请求:SOLR_CIRCUITBREAKER_UPDATE_CPU=95

每个集合的断路器

断路器配置为 solrconfig.xml 中的独立 <circuitBreaker> 条目,如下面的示例所示。默认情况下,仅搜索请求会受到影响。

当前支持的断路器

从 Solr 9.4 开始,使用 CircuitBreakerManager 的旧版配置语法已弃用,但仍将继续工作。此旧版插件在配置 cpuThreshold 时使用的“CPU”断路器实际上是下面描述的 LoadAverageCircuitBreaker。此外,CircuitBreakerManager 将返回 HTTP 503 代码,而不是新断路器使用的 HTTP 429 代码。

JVM 堆使用

此断路器跟踪 JVM 堆内存使用情况,如果堆使用量超过分配给 JVM 的最大堆的配置百分比,则会拒绝带有 429 错误代码的传入请求。此断路器的主要配置是控制断路器跳闸的阈值百分比。

要启用和配置基于 JVM 堆使用的断路器,请添加以下内容

solrconfig.xml 中的每个集合
<circuitBreaker class="org.apache.solr.util.circuitbreaker.MemoryCircuitBreaker">
 <double name="threshold">75</double>
</circuitBreaker>
solr.in.sh 中的全局
SOLR_CIRCUITBREAKER_QUERY_MEM=75

threshold 被定义为分配给 JVM 的最大堆的百分比。

对于断路器配置,值“0”映射到 0% 使用率,值“100”映射到 100% 使用率。

在逻辑上,低于 50% 或高于 95% 的分配给 JVM 的最大堆的阈值是没有意义的。因此,此参数的有效值范围为 [50, 95],包括两者。

考虑以下示例

JVM 已分配 5GB 的最大堆(-Xmx),并且 threshold 设置为 75。在这种情况下,断路器跳闸的堆使用量为 3.75GB。

系统 CPU 使用率断路器

此断路器跟踪系统 CPU 使用率,并在最近的 CPU 使用率超过可配置阈值时触发。

这由 JMX 指标 OperatingSystemMXBean.getSystemCpuLoad() 跟踪。它测量整个系统的近期 CPU 使用率。此指标由 com.sun.management 包提供,但并非在所有 JVM 上都实现。如果指标不可用,则断路器将被禁用并记录错误消息。然后,一种可替代的方法是使用 系统负载平均断路器

要启用和配置基于 CPU 使用率的断路器

solrconfig.xml 中的每个集合
<circuitBreaker class="org.apache.solr.util.circuitbreaker.CPUCircuitBreaker">
 <double  name="threshold">75</double>
</circuitBreaker>
solr.in.sh 中的全局
SOLR_CIRCUITBREAKER_QUERY_CPU=75

触发阈值以百分比 CPU 使用率进行定义。“0”值映射到 0% 使用率,“100”值映射到 100% 使用率。当 CPU 使用率等于或大于 75% 时,上述示例将触发。

系统负载平均断路器

此断路器跟踪系统负载平均值,并在近期负载平均值超过可配置阈值时触发。

这由 JMX 指标 OperatingSystemMXBean.getSystemLoadAverage() 跟踪。它测量整个系统的近期负载平均值。“负载平均值”是正在使用或正在等待 CPU 的进程数,通常平均在一分钟内。某些系统在负载平均值中包括等待 IO 的进程。查看系统和 JVM 的文档以了解此指标。有关更多信息,请参阅 负载的维基百科页面

要启用和配置负载平均断路器

solrconfig.xml 中的每个集合
<circuitBreaker class="org.apache.solr.util.circuitbreaker.LoadAverageCircuitBreaker">
 <double  name="threshold">8.0</double>
</circuitBreaker>
solr.in.sh 中的全局
SOLR_CIRCUITBREAKER_QUERY_LOADAVG=8.0

触发阈值是一个与负载平均值匹配的浮点数。当负载平均值等于或大于 8.0 时,上述示例断路器将触发。

系统负载平均断路器行为取决于操作系统,并且可能在某些操作系统(如 Microsoft Windows)上不起作用。有关更多信息,请参阅 JavaDoc

高级示例

在此示例中,我们将阻止 CPU 负载高于 80% 的更新请求,并阻止 CPU 负载高于 95% 的查询请求。支持的请求类型为 queryupdate。这将防止昂贵的批量更新影响搜索。还要注意对简短类名的支持。

solrconfig.xml 中的每个集合
<config>
  <circuitBreaker class="solr.CPUCircuitBreaker">
   <double  name="threshold">80</double>
   <arr name="requestTypes">
     <str>update</str>
   </arr>
  </circuitBreaker>

  <circuitBreaker class="solr.CPUCircuitBreaker">
   <double  name="threshold">95</double>
   <arr name="requestTypes">
     <str>query</str>
   </arr>
  </circuitBreaker>
</config>
solr.in.sh 中的全局
SOLR_CIRCUITBREAKER_UPDATE_CPU=80
SOLR_CIRCUITBREAKER_QUERY_CPU=95

性能注意事项

虽然 JVM 或 CPU 断路器不会为每个请求增加任何明显的开销,但为单个请求检查过多的断路器可能会导致性能开销。

此外,在繁忙节点上重试请求时,最好采用指数退避。请参阅 维基百科指数退避页面