断路器
Solr 的断路器基础设施可以防止导致节点超出其容量或宕机的操作。断路器的前提是确保更高的服务质量,并且只接受在当前资源配置中可服务的请求负载。
何时使用断路器
当用户希望用请求吞吐量换取更高的 Solr 稳定性时,应使用断路器。如果启用了断路器,则可能会在节点压力较大的情况下拒绝请求,并显示 HTTP 错误代码 429“请求过多”。
客户端需要处理此错误,并可能构建重试逻辑,因为这应该是一个瞬态情况。
在对分片集合的请求中,断路器仅在处理初始请求的节点上进行检查,而不针对节点间请求进行检查。因此,建议在 Solr 节点之间对客户端请求进行负载平衡,以避免热点。
断路器配置
断路器可以针对整个节点全局配置,也可以针对每个集合单独配置,或进行组合配置。在全局断路器之前检查每个集合的断路器,并且如果存在冲突,则每个集合的断路器优先。通常,任何每个集合的断路器阈值都低于全局阈值。
断路器可以注册自身以针对查询请求和/或更新请求进行检查。用户可以针对每种请求类型注册具有不同阈值的相同类型的断路器。
全局断路器
可以使用环境变量(例如,在 solr.in.sh
中)或系统属性在全局范围内配置断路器。可用的变量为
名称 | 环境变量名称 | 系统属性名称 |
---|---|---|
JVM 堆使用情况 |
|
|
系统 CPU 使用情况 |
|
|
系统负载平均值 |
|
|
例如,您可以通过设置以下环境变量来启用一个全局 CPU 断路器,当 CPU 负载高于 95% 时拒绝更新请求:SOLR_CIRCUITBREAKER_UPDATE_CPU=95
。
当前支持的断路器
从 Solr 9.4 开始,使用 |
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% 的查询请求。支持的请求类型为 query
和 update
。这将防止昂贵的批量更新影响搜索。还要注意对简短类名的支持。
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 断路器不会为每个请求增加任何明显的开销,但为单个请求检查过多的断路器可能会导致性能开销。
此外,在繁忙节点上重试请求时,最好采用指数退避。请参阅 维基百科指数退避页面。