Solr部署:指标监控报告系统配置与最佳实践

概述

Solr包含一个开发者API和工具,用于在Solr服务及其各种组件的整个生命周期中收集详细的面向性能的指标。

内部使用 Dropwizard Metrics API,它使用以下类别的计量器来测量事件:

  • counters(计数器):简单地计算事件数量。提供单个长整型值,例如请求数量
  • meters(计量器):额外计算事件速率。提供计数(如上)和1分钟、5分钟、15分钟指数衰减率,类似于Unix系统负载平均值
  • histograms(直方图):根据事件值计算事件的近似分布。提供类似指数衰减的近似统计:平均值(算术平均)、中位数、最大值、最小值、标准差和75%、95%、98%、99%和99.9%百分位数
  • timers(计时器):测量事件数量和持续时间。提供计数和时间直方图
  • gauges(测量器):提供当前值的即时读数,例如当前队列深度、当前活动连接数、空闲堆大小

指标注册表

Solr包含多个指标注册表,用于分组相关指标。指标在组件的整个生命周期中维护和累积,从进程开始直到关闭。例如,特定SolrCore的指标通过多个加载、卸载和/或重命名操作进行跟踪,仅在核心被明确删除时才删除。但是,指标不会在进程重启后持续存在;重启Solr将丢弃所有收集的指标。

JVM注册表

此注册表在 solr.jvm 返回,包含以下信息。在使用Metrics API请求时,可以指定 &group=jvm 来限制仅获取这些指标。

包含的指标:

  • 直接和映射缓冲池
  • 类加载/卸载
  • 操作系统内存、CPU时间(纳秒)、文件描述符、交换、系统负载
  • GC计数和时间
  • 堆、非堆内存和GC池
  • 线程数量、状态和死锁
  • 系统属性,如Java信息、各种安装目录路径、端口和类似信息(可通过修改solr.xml控制显示内容)

Overseer注册表

此注册表在SolrCloud模式下运行时在 solr.overseer 返回,包含以下信息。使用Metrics API时,可以指定 &group=overseer 来限制仅获取这些指标。

包含的指标:

  • Overseer队列大小(集合工作队列和集群状态更新队列)

Node/CoreContainer注册表

此注册表在 solr.node 返回,包含以下信息。使用Metrics API时,可以指定 &group=node 来限制仅获取这些指标。

包含的指标:

  • 处理程序请求(计数、计时):集合、信息、管理、配置集等
  • 核心数量(已加载、延迟、未加载)

Core(SolrCore)注册表

Core注册表包括 solr.core.<collection>,每个核心一个。使用Metrics API时,可以指定 &group=core 来限制仅获取这些指标。

包含的指标:

  • 所有常见RequestHandler报告:请求计时器/计数器、超时、错误
  • 支持处理分布式分片请求的处理程序还报告每种分布式请求类型的 shardRequests 子计数器
  • 索引级事件:小型/大型合并的计量器、合并文档数量、删除文档数量、当前运行合并及其大小的测量器
  • 分片复制和副本上的事务日志重播
  • 分片处理程序和更新处理程序的打开/可用/挂起连接

节点级指标聚合

RequestHandler可以配置为将核心级指标汇总到节点级,除了按核心报告外。如果每个节点有大量核心且对每个节点的聚合指标感兴趣,这很有用。通过在solrconfig.xml的RequestHandler配置中添加 <bool name="aggregateNodeLevelMetricsEnabled">true</bool> 来配置:

1
2
3
4
5
6
7
8
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
</lst>

<bool name="aggregateNodeLevelMetricsEnabled">true</bool>
</requestHandler>

Jetty注册表

此注册表在 solr.jetty 返回,包含以下信息。使用Metrics API时,可以指定 &group=jetty 来限制仅获取这些指标。

包含的指标:

  • 线程和池
  • 连接和请求计时器
  • 按HTTP类别(1xx、2xx等)的响应计量器

指标配置

可以通过修改 solr.xml 中的 <metrics> 元素来自定义系统中可用的指标。

禁用指标收集

solr.xml 中的 <metrics> 元素支持一个属性 enabled,接受布尔值:

1
<metrics enabled="true">
  • 默认值true,表示正在收集、处理和报告指标
  • 禁用效果false 值关闭指标收集和处理,内部所有指标提供者被替换为单例无操作实现,有效移除几乎所有与指标收集相关的开销

隐藏系统属性配置

<hiddenSysProps> 部分允许定义被认为是系统敏感的系统属性,不应通过Metrics API公开。

如果此部分未定义,将使用以下默认配置来隐藏密码和认证信息:

1
2
3
4
5
6
7
8
9
<metrics>
<hiddenSysProps>
<str>javax.net.ssl.keyStorePassword</str>
<str>javax.net.ssl.trustStorePassword</str>
<str>basicauth</str>
<str>zkDigestPassword</str>
<str>zkDigestReadonlyPassword</str>
</hiddenSysProps>
</metrics>

指标供应商配置

<metrics><suppliers> 部分允许定义自己的指标实现并为其配置参数。

Counter供应商

1
2
3
<counter>
<!-- 默认实现不支持任何配置 -->
</counter>

Meter供应商

1
2
3
<meter>
<str name="clock">cpu</str> <!-- 默认: user -->
</meter>

clock参数

  • user:使用 System.nanoTime()
  • cpu:使用当前线程的CPU时间

Histogram供应商

1
2
3
4
5
6
7
<histogram>
<str name="clock">cpu</str>
<str name="reservoir">com.codahale.metrics.SlidingTimeWindowReservoir</str>
<int name="size">1028</int>
<double name="alpha">0.015</double>
<long name="window">300</long>
</histogram>

参数说明

  • reservoir:存储器实现的完全限定类名,默认为 com.codahale.metrics.ExponentiallyDecayingReservoir
  • size:存储器大小,默认1028
  • alpha:衰减参数,仅对 ExponentiallyDecayingReservoir 有效,默认0.015
  • window:窗口大小(秒),仅对 SlidingTimeWindowReservoir 有效,默认300秒

Timer供应商

1
2
3
4
5
<timer>
<str name="clock">cpu</str>
<str name="reservoir">com.codahale.metrics.SlidingTimeWindowReservoir</str>
<long name="window">600</long>
</timer>

缺失值处理配置

长期指标值在底层值不可用时仍被报告(例如,IndexReader关闭时的”INDEX.sizeInBytes”)。默认情况下,缺失值报告为null值,这可以通过 <missingValues> 元素配置:

1
2
3
4
5
6
7
8
<metrics>
<missingValues>
<null name="nullNumber"/>
<int name="notANumber">-1</int>
<str name="nullString"></str>
<str name="nullObject">{"value":"missing"}</str>
</missingValues>
</metrics>

配置选项

  • nullNumber:遇到缺失(null)数值时使用的值
  • notANumber:遇到无效数值时使用的值
  • nullString:遇到缺失(null)字符串时使用的值
  • nullObject:遇到缺失(null)复杂对象时使用的值

线程指标缓存

JVM组中的线程指标计算可能很昂贵,需要遍历所有线程。可以通过设置高缓存过期间隔(秒)来避免每次调用指标API(group=jvm)时都计算:

1
2
3
4
5
6
7
<solr>
<metrics>
<caching>
<int name="threadsIntervalSeconds">5</int>
</caching>
</metrics>
</solr>

报告器配置

报告器配置在 solr.xml 文件的 <metrics><reporter> 部分中指定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<solr>
<metrics>
<reporter name="graphite" group="node, jvm" class="org.apache.solr.metrics.reporters.SolrGraphiteReporter">
<str name="host">graphite-server</str>
<int name="port">9999</int>
<int name="period">60</int>
</reporter>
<reporter name="log_metrics" group="core" class="org.apache.solr.metrics.reporters.SolrSlf4jReporter">
<int name="period">60</int>
<str name="filter">QUERY./select.requestTimes</str>
<str name="filter">QUERY./get.requestTimes</str>
<str name="filter">UPDATE./update.requestTimes</str>
<str name="logger">org.apache.solr.metrics.reporters.SolrSlf4jReporter</str>
</reporter>
</metrics>
</solr>

报告器通用参数

name(必需):

  • 报告器插件的唯一名称

class(必需):

  • 插件的完全限定实现类,必须扩展 SolrMetricReporter

group(可选):

  • 一个或多个预定义组(如 jvmjettynodecore

registry(可选):

  • 一个或多个有效的完全限定注册表名称

period(可选,默认60秒):

  • 报告之间的时间间隔(秒)

prefix(可选,默认空字符串):

  • 添加到指标名称的前缀,可能有助于相关Solr实例的逻辑分组

filter(可选):

  • 如果不为空,只有以此值开头的指标名称将被报告

JMX报告器

使用 org.apache.solr.metrics.reporters.SolrJmxReporter 类。

1
2
3
4
<reporter name="jmx" group="jvm,jetty,node,core" class="org.apache.solr.metrics.reporters.SolrJmxReporter">
<str name="domain">solr</str>
<str name="serviceUrl">service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi</str>
</reporter>

特定参数

  • domain:JMX域名。如果未指定,将使用注册表名称
  • serviceUrl:JMX服务器的服务URL。如果未指定,Solr将尝试发现JVM是否有MBean服务器
  • agentId:JMX服务器的代理ID。注意 serviceUrlagentId 可以指定但不能同时指定

对象名称层次结构(从上到下):

  1. 注册表名称(如 solr.core.collection1.shard1.replica1
  2. 报告器名称
  3. 请求处理器的类别、范围和名称
  4. 或来自其他组件的附加名称元素

SLF4J报告器

使用 org.apache.solr.metrics.reporters.SolrSlf4jReporter 类。

1
2
3
4
5
<reporter name="slf4j" group="core" class="org.apache.solr.metrics.reporters.SolrSlf4jReporter">
<int name="period">60</int>
<str name="filter">QUERY./select.requestTimes</str>
<str name="logger">solr.metrics</str>
</reporter>

特定参数

  • logger:要使用的日志记录器名称。默认为空,这种情况下将使用组名(如果在插件配置中指定)

日志格式示例

1
2
3
4
5
type=COUNTER, name={}, count={}
type=GAUGE, name={}, value={}
type=TIMER, name={}, count={}, min={}, max={}, mean={}, stddev={}, median={}, p75={}, p95={}, p98={}, p99={}, p999={}, mean_rate={}, m1={}, m5={}, m15={}, rate_unit={}, duration_unit={}
type=METER, name={}, count={}, mean_rate={}, m1={}, m5={}, m15={}, rate_unit={}
type=HISTOGRAM, name={}, count={}, min={}, max={}, mean={}, stddev={}, median={}, p75={}, p95={}, p98={}, p99={}, p999={}

Log4j配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<Configuration>
<Appenders>
<RollingFile
name="MetricsFile"
fileName="${sys:solr.log.dir}/solr_metrics.log"
filePattern="${sys:solr.log.dir}/solr_metrics.log.%i">
<PatternLayout>
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{node_name} %X{collection} %X{shard} %X{replica} %X{core} %X{trace_id}] %m%n
</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="32 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>

<Loggers>
<Logger name="solr.metrics" level="info" additivity="false">
<AppenderRef ref="MetricsFile"/>
</Logger>
</Loggers>
</Configuration>

Graphite报告器

使用 org.apache.solr.metrics.reporters.SolrGraphiteReporter 类,与 Graphite 集成。

1
2
3
4
5
6
<reporter name="graphite" group="node,jvm" class="org.apache.solr.metrics.reporters.SolrGraphiteReporter">
<str name="host">graphite-server</str>
<int name="port">2003</int>
<int name="period">60</int>
<bool name="pickled">false</bool>
</reporter>

特定参数

  • host(必需):Graphite服务器运行的主机名
  • port(必需):服务器端口号
  • pickled(默认false):如果为true,使用可能更高效的”pickled” Graphite协议

输出格式(plain-text协议):

1
dot.separated.metric.name[.and.attribute] value epochTimestamp

示例输出

1
2
3
example.solr.node.cores.lazy 0 1482932097
example.solr.node.cores.loaded 1 1482932097
example.solr.jetty.org.eclipse.jetty.server.handler.DefaultHandler.2xx-responses.count 21 1482932097

核心级指标

索引合并指标

这些指标在每个核心的相应注册表中收集(如 solr.core.collection1....),在 INDEX 类别下。

基础配置

1
2
3
4
5
6
7
8
<config>
<indexConfig>
<metrics>
<long name="majorMergeDocs">524288</long>
<bool name="merge">true</bool>
</metrics>
</indexConfig>
</config>

详细配置

1
2
3
4
5
6
7
8
<config>
<indexConfig>
<metrics>
<long name="majorMergeDocs">524288</long>
<bool name="mergeDetails">true</bool>
</metrics>
</indexConfig>
</config>

收集的指标

  • INDEX.merge.major:包含至少”majorMergeDocs”(默认512k文档)的合并操作计时器
  • INDEX.merge.minor:包含少于”majorMergeDocs”的合并操作计时器
  • INDEX.merge.errors:合并错误计数器
  • INDEX.flush:索引刷新操作计量器

运行状态测量器

  • INDEX.merge.major.running:运行中的大型合并操作数量
  • INDEX.merge.minor.running:运行中的小型合并操作数量
  • INDEX.merge.major.running.docs:大型合并操作中当前合并的文档总数
  • INDEX.merge.minor.running.docs:小型合并操作中当前合并的文档总数
  • INDEX.merge.major.running.segments:大型合并操作中当前合并的段数量
  • INDEX.merge.minor.running.segments:小型合并操作中当前合并的段数量

详细指标(mergeDetails=true)

  • INDEX.merge.major.docs:大型合并操作中合并的文档数量计量器
  • INDEX.merge.major.deletedDocs:大型合并操作中删除的文档数量计量器

Metrics API

admin/metrics 端点提供对所有指标组的所有指标的访问。

查询参数

group

  • 默认值all
  • 说明:要检索的指标组。值 all 检索所有组的所有指标
  • 可选值jvmjettynodecore
  • 示例group=jvm,core

type

  • 默认值all
  • 说明:要检索的指标类型
  • 可选值countergaugehistogrammetertimer
  • 示例type=timer,counter

prefix

  • 默认值:无
  • 说明:指标名称的前缀字符,过滤返回以提供字符串开头的指标
  • 示例prefix=QUERY,UPDATE

regex

  • 默认值:无
  • 说明:匹配指标名称的正则表达式
  • 注意:指标名称中的点分隔符必须转义
  • 示例regex=QUERY\./select\..*

property

  • 默认值:无
  • 说明:允许从任何复合指标中只请求此指标
  • 示例property=p99_ms&property=p999_ms

key

  • 默认值:无
  • 说明:完全限定的指标名称,指定一个具体的指标实例
  • 格式registry_name:metric_name:property
  • 示例
    • key=solr.node:CONTAINER.fs.totalSpace
    • key=solr.core.collection1:QUERY./select.requestTimes:max_ms

expr

  • 默认值:无
  • 说明:key选择标准的扩展表示法,支持正则表达式
  • 格式registry_pattern:metric_pattern:property_pattern
  • 示例
    • expr=solr\.core\..*:QUERY\..*\.requestTimes:max_ms
    • expr=solr\.jvm:system\.properties:user\..*

compact

  • 默认值true
  • 说明:当为 false 时,返回更详细的响应格式

API使用示例

请求计数器类型指标

1
http://localhost:8983/solr/admin/metrics?type=counter&group=core

请求以”INDEX”开头的核心组指标

1
http://localhost:8983/solr/admin/metrics?wt=xml&prefix=INDEX&group=core

请求以”.requests”结尾的核心组指标

1
http://localhost:8983/solr/admin/metrics?regex=.*\.requests&group=core

请求特定系统属性

1
http://localhost:8983/solr/admin/metrics?key=solr.jvm:system.properties:user.name

请求查询速率(非直方图)

1
http://localhost:8983/solr/admin/metrics?expr=solr\.core\..*:QUERY\..*\.requestTimes:.*Rate

Prometheus格式输出

1
http://localhost:8983/solr/admin/metrics?wt=prometheus

监控最佳实践

指标选择策略

  1. 关键性能指标

    • 查询响应时间(QUERY.*.requestTimes
    • 更新响应时间(UPDATE.*.requestTimes
    • 错误率(*.errors
    • 吞吐量(*.requests
  2. 资源使用指标

    • JVM堆使用情况(jvm.memory.heap.*
    • GC指标(jvm.gc.*
    • 线程指标(jvm.threads.*
    • 磁盘使用情况(CORE.indexDir
  3. 集群健康指标

    • 核心状态(node.cores.*
    • 分片状态指标
    • 复制延迟指标

报告器配置建议

  1. 开发环境

    • 主要使用JMX报告器便于调试
    • 启用详细的SLF4J日志记录
  2. 生产环境

    • 使用Graphite或Prometheus进行长期存储
    • 配置适当的过滤器减少噪音
    • 设置合理的报告周期(通常60-300秒)
  3. 监控告警

    • 基于关键指标设置告警阈值
    • 配置多级告警(警告、严重、紧急)
    • 建立监控仪表板和可视化

性能优化

  1. 指标收集开销

    • 在资源受限环境中考虑禁用某些指标
    • 使用过滤器减少不必要的指标收集
    • 合理设置缓存间隔
  2. 报告效率

    • 避免过于频繁的报告周期
    • 使用prefix和filter减少传输数据量
    • 选择合适的报告器协议
  3. 存储优化

    • 定期清理历史指标数据
    • 使用数据聚合减少存储需求
    • 配置合适的数据保留策略

通过合理配置和使用Solr的指标监控系统,可以实现对SolrCloud集群的全面监控,及时发现性能问题并进行优化调整,确保系统的稳定性和高效性。

© 2025 Solr Community of China All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero