修复常见集群问题
edit修复常见集群问题
edit本指南描述了如何修复Elasticsearch集群的常见错误和问题。
- Watermark errors
- 修复当数据节点磁盘空间严重不足并达到洪水位磁盘使用水印时发生的水印错误。
- Circuit breaker errors
- Elasticsearch 使用断路器来防止节点耗尽 JVM 堆内存。 如果 Elasticsearch 估计某个操作会超过断路器限制,它会停止该操作并返回一个错误。
- High CPU usage
- 高CPU使用率的最常见原因及其解决方案。
- High JVM memory pressure
- 高JVM内存使用率可能会降低集群性能并触发断路器错误。
- Red or yellow cluster status
- 红色或黄色集群状态表示一个或多个分片缺失或未分配。这些未分配的分片增加了数据丢失的风险,并可能降低集群性能。
- Rejected requests
-
当 Elasticsearch 拒绝请求时,它会停止操作并返回一个带有
429响应码的错误。 - Task queue backlog
- 积压的任务队列可能会阻止任务完成,并将集群置于不健康的状态。
- Diagnose unassigned shards
- 分片可能未分配的原因有多种,从配置错误的分配设置到磁盘空间不足。
- Troubleshooting an unstable cluster
- 一个节点意外离开的集群是不稳定的,可能会引发多个问题。
- Mapping explosion
- 一个索引或索引模式在其中爆炸的集群,具有高数量的映射字段,导致Elasticsearch和Kibana的性能查找问题。
- Hot spotting
- 热点问题可能会在Elasticsearch中发生,当资源利用率在节点之间分布不均匀时。
修复水印错误
edit当一个数据节点磁盘空间严重不足并达到
洪水阶段磁盘使用水位线时,会记录以下错误:错误:磁盘使用量超过洪水阶段水位线,索引已被设置为只读-允许删除块。
为了防止磁盘写满,当一个节点达到这个水位线时,Elasticsearch 阻止对任何在该节点上有分片的索引进行写操作。如果该阻止操作影响到相关的系统索引,Kibana和其他Elastic Stack功能可能会变得不可用。例如,这可能会导致Kibana的Kibana Server is not Ready yet
错误信息。
当受影响节点的磁盘使用率低于高磁盘水位线时,Elasticsearch 将自动移除写入块。为了实现这一点,Elasticsearch 尝试将受影响节点的一些分片重新平衡到同一数据层中的其他节点。
监控重新平衡
edit要验证分片是否正在从受影响的节点移动,直到其低于高水位线,请使用cat shards API和cat recovery API:
GET _cat/shards?v=true GET _cat/recovery?v=true&active_only=true
如果分片仍然保留在节点上,使其保持在高水位线附近,请使用 集群分配解释API 来获取其分配状态的解释。
GET _cluster/allocation/explain
{
"index": "my-index",
"shard": 0,
"primary": false
}
临时缓解
editPUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.disk.watermark.low": "90%",
"cluster.routing.allocation.disk.watermark.low.max_headroom": "100GB",
"cluster.routing.allocation.disk.watermark.high": "95%",
"cluster.routing.allocation.disk.watermark.high.max_headroom": "20GB",
"cluster.routing.allocation.disk.watermark.flood_stage": "97%",
"cluster.routing.allocation.disk.watermark.flood_stage.max_headroom": "5GB",
"cluster.routing.allocation.disk.watermark.flood_stage.frozen": "97%",
"cluster.routing.allocation.disk.watermark.flood_stage.frozen.max_headroom": "5GB"
}
}
PUT */_settings?expand_wildcards=all
{
"index.blocks.read_only_allow_delete": null
}
当长期解决方案到位时,重置或重新配置磁盘水位线:
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.disk.watermark.low": null,
"cluster.routing.allocation.disk.watermark.low.max_headroom": null,
"cluster.routing.allocation.disk.watermark.high": null,
"cluster.routing.allocation.disk.watermark.high.max_headroom": null,
"cluster.routing.allocation.disk.watermark.flood_stage": null,
"cluster.routing.allocation.disk.watermark.flood_stage.max_headroom": null,
"cluster.routing.allocation.disk.watermark.flood_stage.frozen": null,
"cluster.routing.allocation.disk.watermark.flood_stage.frozen.max_headroom": null
}
}
断路器错误
editElasticsearch 使用 断路器 来防止节点耗尽 JVM 堆内存。如果 Elasticsearch 估计某个操作会超过断路器,它会停止该操作并返回一个错误。
默认情况下,父断路器在JVM内存使用率达到95%时触发。为了防止错误,我们建议采取措施减少内存压力,如果使用率持续超过85%。
诊断断路器错误
edit错误信息
如果请求触发了断路器,Elasticsearch 将返回一个带有 429 HTTP 状态码的错误。
{
'error': {
'type': 'circuit_breaking_exception',
'reason': '[parent] Data too large, data for [<http_request>] would be [123848638/118.1mb], which is larger than the limit of [123273216/117.5mb], real usage: [120182112/114.6mb], new bytes reserved: [3666526/3.4mb]',
'bytes_wanted': 123848638,
'bytes_limit': 123273216,
'durability': 'TRANSIENT'
},
'status': 429
}
Elasticsearch 还会将断路器错误写入 elasticsearch.log。这在自动化过程(如分配)触发断路器时非常有用。
Caused by: org.elasticsearch.common.breaker.CircuitBreakingException: [parent] Data too large, data for [<transport_request>] would be [num/numGB], which is larger than the limit of [num/numGB], usages [request=0/0b, fielddata=num/numKB, in_flight_requests=num/numGB, accounting=num/numGB]
检查JVM内存使用情况
如果您已启用堆栈监控,您可以在 Kibana 中查看 JVM 内存使用情况。在主菜单中,点击 堆栈监控。在堆栈监控 概览 页面,点击 节点。JVM 堆 列列出了每个节点的当前内存使用情况。
您还可以使用cat nodes API来获取每个节点的当前heap.percent。
GET _cat/nodes?v=true&h=name,node*,heap*
要获取每个断路器的JVM内存使用情况,请使用节点统计信息API。
GET _nodes/stats/breaker
防止断路器错误
edit减少JVM内存压力
高JVM内存压力通常会导致断路器错误。请参阅 高JVM内存压力。
避免在text字段上使用fielddata
对于高基数的text字段,fielddata可能会使用大量的JVM内存。为了避免这种情况,Elasticsearch默认禁用了text字段上的fielddata。如果你已经启用了fielddata并触发了fielddata断路器,请考虑禁用它并改用keyword字段。请参阅fielddata映射参数。
清除字段数据缓存
如果你触发了fielddata断路器并且无法禁用fielddata, 使用清除缓存API来清除fielddata缓存。 这可能会中断任何使用fielddata的正在进行的搜索。
POST _cache/clear?fielddata=true
高CPU使用率
editElasticsearch 使用 线程池 来管理并发操作的 CPU 资源。高 CPU 使用率通常意味着一个或多个线程池运行不足。
如果线程池耗尽,Elasticsearch将拒绝请求
与线程池相关的请求。例如,如果search线程池耗尽,Elasticsearch将拒绝搜索请求,直到有更多线程可用。
如果一个数据层,以及因此分配给该层的节点,比其他层接收到更多的流量,您可能会遇到高CPU使用率。这种资源利用的不平衡也被称为热点问题。
诊断高CPU使用率
edit检查CPU使用情况
您可以使用cat nodes API检查每个节点的CPU使用情况:
GET _cat/nodes?v=true&s=cpu:desc
响应的 cpu 列包含当前 CPU 使用率的百分比。
name 列包含节点的名称。CPU 使用率升高但短暂是正常的。然而,如果 CPU 使用率长时间升高,则应进行调查。
要跟踪CPU使用情况随时间的变化,我们建议启用监控:
-
(推荐) 启用 日志和指标。当日志和指标启用时,监控信息将在 Kibana 的 Stack Monitoring 页面中可见。
您还可以启用CPU使用率阈值警报,通过电子邮件接收潜在问题的通知。
-
从您的部署菜单中,查看性能页面。在此页面上,您可以查看两个关键指标:
- CPU 使用率: 您的部署的 CPU 使用率,以百分比表示。
- CPU 信用: 您剩余的 CPU 信用,以 CPU 时间的秒数衡量。
Elasticsearch Service 为每个部署提供 CPU 信用,以便在需要时为较小的集群提供性能提升。高 CPU 使用率可能会耗尽这些信用,这可能导致 性能下降 和 集群响应时间增加。
-
启用Elasticsearch监控。当启用日志和指标时,监控信息将在Kibana的堆栈监控页面上可见。
您还可以启用CPU使用率阈值警报,通过电子邮件接收潜在问题的通知。
检查热点线程
如果一个节点的CPU使用率很高,请使用nodes hot threads API来检查节点上运行的资源密集型线程。
GET _nodes/hot_threads
此API以纯文本形式返回任何热点线程的详细信息。高CPU使用率通常与长时间运行的任务或任务积压相关。
降低 CPU 使用率
edit以下提示概述了高CPU使用率的最常见原因及其解决方案。
扩展您的集群
沉重的索引和搜索负载可能会耗尽较小的线程池。为了更好地处理繁重的工作负载,请向集群中添加更多节点或升级现有节点以增加容量。
分散批量请求
虽然比单独的请求更高效,但大型的批量索引 或 多搜索请求仍然需要CPU资源。如果可能,提交较小的请求并在它们之间留出更多时间。
取消长时间运行的搜索
长时间运行的搜索可能会阻塞search线程池中的线程。要检查这些搜索,请使用任务管理 API。
GET _tasks?actions=*search&detailed
响应的 description 包含了搜索请求及其查询。
running_time_in_nanos 显示了搜索已经运行了多长时间。
{
"nodes" : {
"oTUltX4IQMOUUVeiohTt8A" : {
"name" : "my-node",
"transport_address" : "127.0.0.1:9300",
"host" : "127.0.0.1",
"ip" : "127.0.0.1:9300",
"tasks" : {
"oTUltX4IQMOUUVeiohTt8A:464" : {
"node" : "oTUltX4IQMOUUVeiohTt8A",
"id" : 464,
"type" : "transport",
"action" : "indices:data/read/search",
"description" : "indices[my-index], search_type[QUERY_THEN_FETCH], source[{\"query\":...}]",
"start_time_in_millis" : 4081771730000,
"running_time_in_nanos" : 13991383,
"cancellable" : true
}
}
}
}
}
要取消搜索并释放资源,请使用API的_cancel端点。
POST _tasks/oTUltX4IQMOUUVeiohTt8A:464/_cancel
有关如何跟踪和避免资源密集型搜索的更多提示,请参阅 避免昂贵的搜索。
高JVM内存压力
edit高JVM内存使用率可能会降低集群性能并触发 断路器错误。为了防止这种情况,我们建议 采取措施减少内存压力,如果节点的JVM内存使用率持续超过85%。
诊断高JVM内存压力
edit检查JVM内存压力
从您的部署菜单中,点击Elasticsearch。在实例下,每个实例显示一个JVM内存压力指示器。当JVM内存压力达到75%时,指示器变为红色。
您还可以使用节点统计信息 API来计算每个节点的当前 JVM 内存压力。
GET _nodes/stats?filter_path=nodes.*.jvm.mem.pools.old
使用响应来计算内存压力如下:
JVM 内存压力 = used_in_bytes / max_in_bytes
要计算每个节点的当前JVM内存压力,请使用节点统计信息API。
GET _nodes/stats?filter_path=nodes.*.jvm.mem.pools.old
使用响应来计算内存压力如下:
JVM 内存压力 = used_in_bytes / max_in_bytes
检查垃圾回收日志
随着内存使用量的增加,垃圾回收变得更加频繁且耗时更长。您可以在elasticsearch.log中跟踪垃圾回收事件的频率和持续时间。例如,以下事件表明Elasticsearch在过去40秒内花费了超过50%(21秒)的时间进行垃圾回收。
[timestamp_short_interval_from_last][INFO ][o.e.m.j.JvmGcMonitorService] [node_id] [gc][number] overhead, spent [21s] collecting in the last [40s]
捕获JVM堆转储
要确定JVM内存压力高的确切原因,请在JVM内存使用率高时捕获其堆转储,并捕获覆盖同一时间段的垃圾收集器日志。
减少JVM内存压力
edit本节包含一些减少JVM内存压力的常见建议。
减少分片数量
每个分片都会使用内存。在大多数情况下,少量大分片比许多小分片使用的资源更少。有关减少分片数量的建议,请参阅调整分片大小。
昂贵的搜索可能会消耗大量内存。为了更好地跟踪集群中的昂贵搜索,请启用慢日志。
昂贵的搜索可能会有一个较大的size参数,
使用具有大量桶的聚合,或者包含
昂贵的查询。为了防止昂贵的搜索,请考虑以下设置更改:
-
使用
index.max_result_window索引设置降低size限制。 - 使用search.max_buckets集群设置减少允许的最大聚合桶数。
-
使用
search.allow_expensive_queries集群设置禁用昂贵的查询。 -
使用
search.default_search_timeout集群设置设置默认搜索超时。
PUT _settings
{
"index.max_result_window": 5000
}
PUT _cluster/settings
{
"persistent": {
"search.max_buckets": 20000,
"search.allow_expensive_queries": false
}
}
防止映射爆炸
定义过多的字段或过度嵌套字段可能会导致使用大量内存的映射爆炸。 为了防止映射爆炸,请使用映射限制设置来限制字段映射的数量。
分散批量请求
虽然比单独的请求更高效,但大型的批量索引 或多搜索请求仍然可能产生高JVM内存压力。如果可能,提交较小的请求并在它们之间留出更多时间。
升级节点内存
大量的索引和搜索负载可能会导致高JVM内存压力。为了更好地处理繁重的工作负载,请升级您的节点以增加其内存容量。
红色或黄色集群健康状态
edit红色或黄色集群健康状态表示一个或多个分片未分配给节点。
- 红色健康状态: 集群中有一些未分配的主分片,这意味着某些操作(如搜索和索引)可能会失败。
- 黄色健康状态: 集群中没有未分配的主分片,但有一些未分配的副本分片。这增加了数据丢失的风险,并可能降低集群性能。
当您的集群处于红色或黄色健康状态时,它将继续尽可能地处理搜索和索引,但在集群恢复到绿色健康状态之前,可能会延迟某些管理和清理活动。例如,某些ILM操作要求它们所操作的索引处于绿色健康状态。
在许多情况下,您的集群将自动恢复到绿色健康状态。如果集群没有自动恢复,那么您必须手动解决剩余的问题,以便管理和清理活动可以继续进行。
诊断您的集群状态
edit检查您的集群状态
使用集群健康状态 API。
GET _cluster/health?filter_path=status,*_shards
一个健康的集群有一个绿色的状态和零个未分配的分片。黄色状态意味着只有副本未分配。红色状态意味着一个或多个主分片未分配。
查看未分配的分片
要查看未分配的分片,请使用cat shards API。
GET _cat/shards?v=true&h=index,shard,prirep,state,node,unassigned.reason&s=state
未分配的分片具有state为UNASSIGNED。prirep值对于主分片是p,对于副本是r。
要了解为什么未分配的分片没有被分配以及您必须采取什么行动才能让 Elasticsearch 分配它,请使用 集群分配解释 API。
GET _cluster/allocation/explain?filter_path=index,node_allocation_decisions.node_name,node_allocation_decisions.deciders.*
{
"index": "my-index",
"shard": 0,
"primary": false
}
修复红色或黄色集群状态
edit分片可能由于多种原因变为未分配状态。以下提示概述了最常见的原因及其解决方案。
重新启用分片分配
edit通常在重启或其他集群维护期间禁用分配。如果您忘记在之后重新启用分配,Elasticsearch将无法分配分片。要重新启用分配,请重置cluster.routing.allocation.enable集群设置。
PUT _cluster/settings
{
"persistent" : {
"cluster.routing.allocation.enable" : null
}
}
恢复丢失的节点
edit当数据节点离开集群时,分片通常会变为未分配状态。这可能由多种原因引起,从连接问题到硬件故障。在您解决问题并恢复节点后,它将重新加入集群。Elasticsearch 随后会自动分配任何未分配的分片。
为了避免在临时问题上浪费资源,Elasticsearch 默认会 延迟一分钟进行分配。如果你已经恢复了一个节点并且不想等待延迟期,你可以调用 集群重新路由 API 而不带参数来启动分配过程。该过程会在后台异步运行。
POST _cluster/reroute
修复分配设置
edit配置错误的分配设置可能导致主分片未分配。 这些设置包括:
要查看您的分配设置,请使用获取索引设置和集群获取设置 API。
GET my-index/_settings?flat_settings=true&include_defaults=true GET _cluster/settings?flat_settings=true&include_defaults=true
分配或减少副本
edit为了防止硬件故障,Elasticsearch 不会将副本分配到与其主分片相同的节点上。如果没有其他数据节点可以托管副本,它将保持未分配状态。要解决这个问题,您可以:
- 向同一层级添加一个数据节点以托管副本。
-
更改
index.number_of_replicas索引设置以减少每个主分片的副本数量。我们建议每个主分片至少保留一个副本。
PUT _settings
{
"index.number_of_replicas": 1
}
释放或增加磁盘空间
editElasticsearch 使用 低磁盘水位线 来确保数据节点有足够的磁盘空间用于接收新的分片。默认情况下,Elasticsearch 不会将分片分配给使用超过 85% 磁盘空间的节点。
要检查节点的当前磁盘空间,请使用cat allocation API。
GET _cat/allocation?v=true&h=node,shards,disk.*
如果您的节点磁盘空间不足,您有几个选择:
- 升级你的节点以增加磁盘空间。
- 删除不需要的索引以释放空间。如果你使用 ILM,你可以更新你的生命周期策略以使用 可搜索快照 或添加删除阶段。如果你不再需要搜索数据,你可以使用 快照 将其存储在集群外。
-
如果你不再向索引写入数据,使用强制合并 API或 ILM 的强制合并操作将其段合并为更大的段。
POST my-index/_forcemerge
-
如果索引是只读的,请使用收缩索引 API或 ILM 的收缩操作来减少其主分片数量。
POST my-index/_shrink/my-shrunken-index
-
如果你的节点具有较大的磁盘容量,你可以提高低磁盘水位线或将其设置为明确的字节值。
PUT _cluster/settings { "persistent": { "cluster.routing.allocation.disk.watermark.low": "30gb" } }
减少JVM内存压力
edit分片分配需要JVM堆内存。高JVM内存压力可能会触发 断路器,停止分配并导致分片未分配。请参阅高JVM内存压力。
恢复丢失的主分片的数据
edit如果包含主分片的节点丢失,Elasticsearch 通常可以使用另一个节点上的副本来替换它。如果你无法恢复该节点,并且副本不存在或无法恢复,Allocation
Explain 将报告 no_valid_shard_copy,你需要执行以下操作之一:
- 从 快照 恢复丢失的数据
- 从其原始数据源索引丢失的数据
- 通过运行 删除索引 接受索引级别的数据丢失
-
通过执行 集群重新路由 的 allocate_stale_primary 或 allocate_empty_primary 命令并设置
accept_data_loss: true来接受分片级别的数据丢失仅在节点恢复不再可能时使用此选项。此过程分配一个空的主分片。如果节点稍后重新加入集群,Elasticsearch将使用这个较新的空分片覆盖其主分片,从而导致数据丢失。
POST _cluster/reroute { "commands": [ { "allocate_empty_primary": { "index": "my-index", "shard": 0, "node": "my-node", "accept_data_loss": "true" } } ] }
被拒绝的请求
edit当Elasticsearch拒绝一个请求时,它会停止操作并返回一个带有429响应码的错误。被拒绝的请求通常由以下原因引起:
-
一个耗尽的线程池。一个耗尽的
search或write线程池会返回一个TOO_MANY_REQUESTS错误信息。 - 一个断路器错误。
-
高索引压力超过了
indexing_pressure.memory.limit。
检查被拒绝的任务
edit要检查每个线程池的拒绝任务数量,请使用cat thread pool API。rejected任务与completed任务的高比率,特别是在search和write线程池中,意味着Elasticsearch经常拒绝请求。
GET /_cat/thread_pool?v=true&h=id,name,queue,active,rejected,completed
write 线程池拒绝频繁出现在错误的API和相关日志中,显示为EsRejectedExecutionException,并带有QueueResizingEsThreadPoolExecutor或队列容量。
这些错误通常与积压的任务有关。
检查断路器
edit要检查跳闸的断路器数量,请使用节点统计信息 API。
GET /_nodes/stats/breaker
这些统计数据是从节点启动时开始累积的。更多信息,请参阅 断路器错误。
检查索引压力
edit要检查索引压力拒绝的数量,请使用节点统计信息 API。
GET _nodes/stats?human&filter_path=nodes.*.indexing_pressure
这些统计数据是从节点启动时开始累积的。
索引压力拒绝显示为
EsRejectedExecutionException,并表明它们因
coordinating_and_primary_bytes、coordinating、primary 或 replica 而被拒绝。
这些错误通常与积压的任务、
批量索引大小或摄取目标的
refresh_interval设置有关。
防止请求被拒绝
edit修复高CPU和内存使用率
如果 Elasticsearch 经常拒绝请求和其他任务,您的集群可能存在高 CPU 使用率或高 JVM 内存压力。有关提示,请参阅 高 CPU 使用率 和 高 JVM 内存压力。
任务队列积压
edit积压的任务队列可能会阻止任务完成,并将集群置于不健康状态。资源限制、一次性触发大量任务以及长时间运行的任务都可能导致任务队列积压。
诊断任务队列积压
edit检查线程池状态
线程池耗尽可能仅限于特定的数据层。如果热点问题正在发生,一个节点可能会比其他节点更快地耗尽,导致性能问题和不断增长的任务积压。
您可以使用cat thread pool API来查看每个线程池中的活动线程数量,以及有多少任务在队列中,有多少任务被拒绝,以及有多少任务已完成。
GET /_cat/thread_pool?v&s=t,n&h=type,name,node_name,active,queue,rejected,completed
The active 和 queue 统计数据是即时的,而 rejected 和
completed 统计数据是从节点启动以来的累积数据。
检查每个节点上的热线程
如果某个线程池队列积压,您可以定期轮询 Nodes hot threads API 以确定线程是否拥有足够的资源来推进,并评估其推进的速度。
GET /_nodes/hot_threads
查找长时间运行的节点任务
长时间运行的任务也可能导致积压。您可以使用任务管理 API 来获取有关正在运行的节点任务的信息。检查 running_time_in_nanos 以识别完成时间过长的任务。
GET /_tasks?pretty=true&human=true&detailed=true
如果怀疑某个特定的action,您可以进一步过滤任务。最常见的长时间运行的任务是批量索引或搜索相关的任务。
-
过滤 批量索引 操作:
GET /_tasks?human&detailed&actions=indices:data/write/bulk
-
搜索操作的过滤器:
GET /_tasks?human&detailed&actions=indices:data/write/search
API响应可能包含额外的任务列,包括description和header,这些列提供了任务参数、目标和请求者。您可以使用此信息进行进一步的诊断。
查找长时间运行的集群任务
任务积压也可能表现为同步集群状态的延迟。您可以使用待处理的集群任务 API来获取有关正在运行的待处理集群状态同步任务的信息。
GET /_cluster/pending_tasks
检查 timeInQueue 以识别那些完成时间过长的任务。
解决任务队列积压
edit增加可用资源
如果任务进展缓慢且队列积压,您可能需要采取措施来减少CPU使用率。
在某些情况下,增加线程池的大小可能会有所帮助。
例如,force_merge 线程池默认使用单个线程。
将其大小增加到 2 可能有助于减少强制合并请求的积压。
取消卡住的任务
如果你发现活跃任务的热线程没有进展并且有积压,考虑取消任务。
映射爆炸
editElasticsearch 的搜索和 Kibana 的发现 JavaScript 渲染依赖于搜索支持索引的总 映射字段 数量,包括所有映射深度。当这个总数过高或呈指数级增长时,我们称之为遭遇映射爆炸。字段数量达到如此高的水平并不常见,通常表明上游文档格式存在问题,如 此博客所示。
映射爆炸可能会表现为以下性能症状:
- CAT nodes 报告主节点和/或托管索引分片的节点上的高堆内存或CPU使用率。这可能会潜在地升级为临时节点无响应和/或主节点过载。
- CAT tasks 报告仅与此索引或索引相关的长时间搜索持续时间,即使在简单的搜索中也是如此。
- CAT tasks 报告仅与此索引或索引相关的长时间索引持续时间。这通常与待处理任务相关,报告协调节点正在等待所有其他节点确认它们在映射更新请求上。
- Discover的通配符字段页面加载API命令或Dev Tools页面刷新自动完成API命令需要很长时间(超过10秒)或在浏览器的开发者工具网络选项卡中超时。更多信息,请参阅我们的Discover故障排除指南。
- Discover的可用字段在浏览器的开发者工具性能选项卡中编译Javascript需要很长时间。这可能会潜在地升级为临时浏览器页面无响应。
-
Kibana的警报或安全规则可能会错误
内容长度(X)大于允许的最大字符串(Y),其中X是尝试的有效载荷,Y是Kibana的server-maxPayload。 - 长时间Elasticsearch启动持续时间。
预防或准备
edit映射一旦初始化后,不能进行字段缩减。
Elasticsearch 索引默认使用 动态映射,
这通常不会引起问题,除非与覆盖
index.mapping.total_fields.limit 结合使用。
默认的 1000 限制被认为是慷慨的,尽管将其覆盖为 10000
在不同的使用场景下不会引起明显的性能影响。然而,举一个不好的例子,将其覆盖为 100000 并且达到这个限制
通常会对性能产生强烈的影响。
如果你的索引映射字段期望包含一个大的、任意的键集合,你可以考虑以下方法:
-
将
index.mapping.total_fields.ignore_dynamic_beyond_limit设置为true。 这样,一旦达到字段限制,将忽略动态字段,而不是拒绝超过字段限制的文档。 -
使用扁平化数据类型。但请注意,
扁平化对象在Kibana中尚未完全支持。例如,这可能适用于子映射,如{
host.name,host.os,host.version}。所需字段仍通过 运行时字段访问。 - 禁用动态映射。 这不会影响当前索引映射,但可以通过索引模板向前应用。
修改为嵌套数据类型并不能解决核心问题。
检查问题
edit要确认索引的字段总数以检查映射爆炸:
-
检查Elasticsearch集群日志中的错误
Limit of total fields [X] in index [Y] has been exceeded,其中X是index.mapping.total_fields.limit的值,Y是你的索引。相关的摄取源日志错误将是Limit of total fields [X] has been exceeded while adding new fields [Z],其中Z是尝试添加的新字段。 -
对于顶级字段,轮询 字段功能 以获取
fields=*。 -
在 获取映射 的输出中搜索
"type"。 -
如果你倾向于使用第三方工具JQ,你可以处理获取映射的
mapping.json输出。$ cat mapping.json | jq -c 'to_entries[]| .key as $index| [.value.mappings| to_entries[]|select(.key=="properties") | {(.key):([.value|..|.type?|select(.!=null)]|length)}]| map(to_entries)| flatten| from_entries| ([to_entries[].value]|add)| {index: $index, field_count: .}'
您可以使用分析索引磁盘使用情况来查找从未或很少填充的字段,作为轻松的优化点。
复杂的爆炸
edit映射爆炸也涵盖了个别索引字段总数在限制范围内但组合索引字段总数非常高的情况。症状通常首先在数据视图上被注意到,并通过解析索引API追溯到单个索引或索引子集。
然而,尽管较为少见,但也有可能只在备份索引的组合上遇到映射爆炸。例如,如果一个数据流的备份索引都达到了字段总数限制,但每个索引包含的独特字段彼此不同。
这种情况最简单的方法是通过添加一个数据视图并检查其字段选项卡中的总字段数来体现。这个统计数据确实告诉您总体字段数,而不仅仅是index:true的字段,但它作为一个良好的基准。
如果你的问题仅通过数据视图出现,如果你没有使用多字段,你可以考虑此菜单的字段过滤器。或者,你可以考虑使用更精确的索引模式,或者使用负模式来过滤掉有问题的索引。例如,如果logs-*由于有问题的后备索引logs-lotsOfFields-*而导致字段数量过多,那么你可以更新为logs-*,-logs-lotsOfFields-*或logs-iMeantThisAnyway-*。
解析
edit映射爆炸不容易解决,因此最好通过上述方法预防。遇到这种情况通常表明上游数据发生了意外变化或规划失败。如果遇到这种情况,我们建议审查您的数据架构。以下选项是本页前面讨论的选项之外的补充;它们应根据最佳适用情况应用:
拆分索引 不会解决核心问题。
热点定位
edit计算机热点 可能在Elasticsearch中发生,当资源利用率在 节点之间分布不均时。临时峰值通常不被认为是问题,但 持续的显著独特利用可能导致集群瓶颈 并应进行审查。
请参阅此视频以了解解决热点问题故障排除的演练。
检测热点
edit热点问题最常见的表现为某些节点上的资源利用率(如disk.percent、heap.percent或cpu)显著升高,这些信息可以通过cat nodes报告。个别的高峰并不一定是有问题的,但如果利用率反复出现高峰或长时间(例如超过30秒)持续保持高位,则可能存在资源热点问题。
例如,让我们展示使用cat节点来处理两个独立的可能问题:
GET _cat/nodes?v&s=master,name&h=name,master,node.role,heap.percent,disk.used_percent,cpu
假装在五分钟内拉取了两次相同的输出:
name master node.role heap.percent disk.used_percent cpu node_1 * hirstm 24 20 95 node_2 - hirstm 23 18 18 node_3 - hirstmv 25 90 10
这里我们看到两种显著不同的利用方式:主节点在
cpu: 95,而一个热点节点在 disk.used_percent: 90%。这表明在这两个节点上发生了热点定位,但不一定来自相同的根本原因。
原因
edit历史上,集群主要由于硬件、分片分布和/或任务负载的影响而经历热点问题。我们将按其可能影响的范围顺序逐一审查这些因素。
硬件
edit以下是一些可能导致热点问题的常见不正确硬件设置:
分片分布
editElasticsearch 索引被划分为一个或多个 分片,这些分片有时可能分布不均。Elasticsearch 通过在数据节点之间平衡分片数量来解决这个问题。正如在8.6 版本中引入的那样,Elasticsearch 默认还启用了期望的平衡来应对摄取负载。一个节点可能仍然会遇到热点问题,这可能是由于写入密集型的索引或其托管的总体分片数量造成的。
节点级别
edit您可以通过cat allocation检查分片平衡情况,尽管从版本8.6开始,期望的平衡可能不再完全期望平衡分片。请注意,这两种方法在集群稳定性问题期间可能会暂时显示有问题的失衡。
例如,让我们展示两个使用猫分配的独立合理问题:
GET _cat/allocation?v&s=node&h=node,shards,disk.percent,disk.indices,disk.used
返回的结果可能是:
node shards disk.percent disk.indices disk.used node_1 446 19 154.8gb 173.1gb node_2 31 52 44.6gb 372.7gb node_3 445 43 271.5gb 289.4gb
这里我们看到两种显著不同的情况。node_2 最近重新启动,因此它的分片数量远低于所有其他节点。这也与 disk.indices 远小于 disk.used 有关,因为分片正在恢复,如通过 cat recovery 所见。虽然 node_2 的分片数量较低,但由于正在进行 ILM 滚动,它可能会成为一个写热点。这是下一节中讨论的写热点的常见根本原因。
第二种情况是node_3的disk.percent比node_1高,尽管它们持有的分片数量大致相同。这种情况发生在分片大小不均匀(参见目标是分片最多包含200M文档,或者大小在10GB到50GB之间)或者存在大量空索引时。
基于期望平衡的集群重新平衡可以很大程度上避免节点过热。它可以通过节点达到水位线(参考修复磁盘水位线错误)或写入量大的索引的总分片数远低于写入节点数来限制。
您可以通过节点统计信息API确认热点节点, 可能通过时间上的两次轮询来仅检查它们之间的统计信息差异, 而不是一次轮询为您提供节点整个节点运行时间的统计信息。例如,要检查所有节点的索引统计信息:
GET _nodes/stats?human&filter_path=nodes.*.name,nodes.*.indices.indexing
索引级别
edit热点节点经常通过cat thread pool的
write和search队列备份显现出来。例如:
GET _cat/thread_pool/write,search?v=true&s=n,nn&h=n,nn,q,a,r,c
返回的结果可能是:
n nn q a r c search node_1 3 1 0 1287 search node_2 0 2 0 1159 search node_3 0 1 0 1302 write node_1 100 3 0 4259 write node_2 0 4 0 980 write node_3 1 5 0 8714
这里你可以看到两种显著不同的情况。首先,node_1 的写队列严重积压,与其他节点相比。其次,node_3 显示的历史完成的写入量是其他节点的两倍。这两种情况可能都是由于写密集型索引分布不均,或者是多个写密集型索引分配到同一个节点。由于主分片和副本分片的写入量在集群工作中大致相同,我们通常建议设置 index.routing.allocation.total_shards_per_node 以在调整索引分片数量与总节点数后强制分散索引。
我们通常建议重写索引具有足够的number_of_shards和副本number_of_replicas,以均匀分布在索引节点上。或者,您可以重新路由分片到更安静的节点,以减轻具有写热点问题的节点。
如果哪些索引存在问题不明显,你可以通过运行以下命令进一步内省:
GET _stats?level=shards&human&expand_wildcards=all&filter_path=indices.*.total.indexing.index_total
对于更高级的分析,您可以轮询分片级别的统计信息, 这使您可以比较联合索引级别和节点级别的统计信息。这种分析 不会考虑节点重启和/或分片重新路由,但可以作为概览:
GET _stats/indexing,search?level=shards&human&expand_wildcards=all
例如,您可以使用第三方JQ工具,
来处理保存为indices_stats.json的输出:
cat indices_stats.json | jq -rc ['.indices|to_entries[]|.key as $i|.value.shards|to_entries[]|.key as $s|.value[]|{node:.routing.node[:4], index:$i, shard:$s, primary:.routing.primary, size:.store.size, total_indexing:.indexing.index_total, time_indexing:.indexing.index_time_in_millis, total_query:.search.query_total, time_query:.search.query_time_in_millis } | .+{ avg_indexing: (if .total_indexing>0 then (.time_indexing/.total_indexing|round) else 0 end), avg_search: (if .total_search>0 then (.time_search/.total_search|round) else 0 end) }'] > shard_stats.json
# show top written-to shard simplified stats which contain their index and node references
cat shard_stats.json | jq -rc 'sort_by(-.avg_indexing)[]' | head
任务负载
edit分片分布问题很可能会表现为任务负载,如上文在cat thread pool示例中所见。由于单个任务的昂贵性或整体流量负载,任务也可能使某个节点过热。
例如,如果cat线程池报告了warmer 线程池上的高队列,您将查找受影响节点的热线程。假设它报告了与GlobalOrdinalsBuilder相关的warmer线程在100% cpu上。这将让您知道要检查字段数据的全球序号。
或者,假设 cat nodes 显示一个热点主节点,
并且 cat thread pool 显示节点间的普遍排队情况。
这表明主节点已经过载。要解决这个问题,首先确保 硬件高可用性
设置,然后查找临时原因。在这个例子中,
节点热点线程 API 报告了多个线程在
其他 中,这表明它们正在等待或被垃圾收集或 I/O 阻塞。
对于这些示例情况中的任何一种,确认有问题的任务的一个好方法是查看通过cat 任务管理的最长运行非连续(指定为[c])任务。这可以通过检查通过cat 待处理任务的最长运行集群同步任务来补充。以第三个示例为例,
GET _cat/tasks?v&s=time:desc&h=type,action,running_time,node,cancellable
这可能返回:
type action running_time node cancellable direct indices:data/read/eql 10m node_1 true ...
这暴露了一个有问题的EQL查询。我们可以通过任务管理API进一步了解它。
GET _tasks?human&detailed
它的响应包含一个描述,报告了这个查询:
indices[winlogbeat-*,logs-window*], sequence by winlog.computer_name with maxspan=1m\n\n[authentication where host.os.type == "windows" and event.action:"logged-in" and\n event.outcome == "success" and process.name == "svchost.exe" ] by winlog.event_data.TargetLogonId
这让你知道要检查哪些索引(winlogbeat-*,logs-window*),以及EQL搜索请求体。最有可能这是SIEM相关的。你可以根据需要将此与审计日志记录结合使用,以追踪请求的来源。