如何调试无响应的 Elasticsearch 集群(一)

272 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情

如何调试无响应的 Elasticsearch 集群(一)

Elasticsearch 是一个开源搜索引擎和分析商店,被各种应用程序使用,从电子商务商店的搜索到使用 ELK 堆栈(“Elasticsearch、Logstash、Kibana”的缩写)的内部日志管理工具。作为分布式数据库,数据被划分为“碎片”,然后分配给一个或多个服务器。

由于这种分片,对 Elasticsearch 集群的读取或写入请求需要在多个节点之间进行协调,因为在单个服务器上没有数据的“全局视图”。虽然这使得 Elasticsearch 具有高度可扩展性,但它也使得设置和调整比其他流行的数据库(如 MongoDB 或 PostgresSQL)更复杂,后者可以在单个服务器上运行。

当出现可靠性问题时,如果 Elasticsearch 设置有问题或不稳定,那么处理可能会很棘手。可能会影响客户业务。快速修复步骤很重要,但在事故或停机期间花费大量时间在线研究解决方案就不太现实了。这篇文章旨在作为工程师运行的常见问题的排障指南。

无响应的 Elasticsearch 集群问题

集群稳定性问题是最难调试的问题,尤其是在你的数据量或代码库没有任何变化的情况下。

检查集群状态的大小

它有什么作用?

  • Elasticsearch 集群状态跟踪我们集群的全局状态,是控制流量和集群的核心。集群状态包括集群中节点的元数据、分片的状态以及它们如何映射到节点、索引映射(即模式)等等。
  • 集群状态通常不会经常改变。但是,某些操作(例如将新字段添加到索引映射)可能会触发更新。
  • 因为集群更新广播到集群中的所有节点,所以它应该很小(<100MB)。
  • 一个大的集群状态会很快使集群变得不稳定。发生这种情况的常见方式是通过映射爆炸(索引中的键过多)或索引过多。

要找什么

  • 使用以下命令下载集群状态并查看返回的 JSON 的大小。
curl -XGET 'http://localhost:9200/_cluster/state'

怎么处理

  • 看看数据是如何被索引的。发生映射爆炸的常见方式是使用高基数标识符作为 JSON 键。每次看到一个新的键,比如“4”和“5”,集群状态就会更新。例如,下面的 JSON 将很快导致 Elasticsearch 出现稳定性问题,因为每个键都被添加到全局状态中。
  {
 "1": {
   "status": "ACTIVE"
 },
 "2": {
   "status": "ACTIVE"
 },
 "3": {
   "status": "DISABLED"
 }
  }

要解决此问题,请将您的数据扁平化为Elasticsearch 识别的内容:

{
  [    {      "id": "1",      "status": "ACTIVE"    },    {      "id": "2",      "status": "ACTIVE"    },    {      "id": "3",      "status": "DISABLED"    }  ]
}

检查 Elasticsearch 任务队列

它有什么作用?

  • 当对 Elasticsearch 发出请求(索引操作、查询操作等)时,它首先被插入到任务队列中,直到工作线程可以接收到它。
  • 一旦工作池有一个空闲线程,它就会从任务队列中取出一个任务并处理它。
  • 这些操作通常由您通过:9200:9300端口上的 HTTP 请求进行,但它们也可以在内部处理索引上的维护任务
  • 在给定时间,可能有成百上千个正在进行的操作,但应该很快完成(如微秒或毫秒)。

要找什么

  • 运行以下命令并查找长时间停滞运行的任务,例如几分钟或几小时。

  • 这意味着某些东西正在使集群空闲并阻止它向前发展。

  • 对于某些长时间运行的任务(例如移动索引)花费很长时间是可以的。但是,正常的查询和索引操作应该很快。

    curl -XGET 'http://localhost:9200/_cat/tasks?detailed'
    
  • 使用?detailed参数,您可以获得有关目标索引和查询的更多信息。

  • 寻找任务始终位于列表顶部的模式。是同一个索引吗?是同一个节点吗?

  • 如果是这样,则该索引的数据可能有问题或节点过载。

怎么处理

  • 如果请求量高于正常水平,则考虑优化请求的方法(例如使用批量 API 或更高效的查询/写入)
  • 如果体积没有变化并且看起来是随机的,这意味着其他东西正在减慢集群的速度。任务的备份只是一个更大问题的表象。
  • 如果您不知道请求来自何处,请将X-Opaque-Id标头添加到您的 Elasticsearch 客户端,以识别哪些客户端正在触发查询。

检查 Elasticsearch 挂起的任务

它有什么作用?

  • 待处理任务是对集群状态的待处理更新,例如创建新索引或更新其映射。
  • 与之前的任务队列不同,挂起的更新需要多步握手才能将更新广播到集群中的所有节点,这可能需要一些时间。
  • 在给定时间内,飞行中的任务应该几乎为零。请记住,快照还原等昂贵的操作可能会导致这种情况暂时飙升。

要找什么

  • 运行命令并确保没有或只有很少的任务在进行中。

    curl curl curl -XGET 'http://localhost:9200/_cat/pending_tasks'
    
  • 如果它看起来是一个快速完成的持续集群更新流,请查看可能触发它们的原因。是映射爆炸还是创建了太多索引?

  • 如果只是几个,但它们似乎卡住了,请查看主节点的日志和指标,看看是否有任何问题。例如,主节点是否遇到内存或网络问题,无法处理集群更新?

热线程

它有什么作用?

  • 热线程 API 是一个有价值的内置分析器,可以告诉您 Elasticseach 在哪里花费的时间最多。
  • 这可以提供洞察力,例如 Elasticsearch 是否在索引刷新上花费了太多时间或执行过多的查询。

要找什么

  • 调用热线程 API。为了提高准确性,建议使用?snapshots参数捕获许多快照。

    curl -XGET 'http://localhost:9200/_nodes/hot_threads?snapshots=1000'
    
  • 这将返回拍摄快照时看到的堆栈跟踪。

  • 在许多不同的快照中寻找相同的堆栈。例如,您可能会看到文本5/10 snapshots sharing following 20 elements。这意味着一个线程在 5 个快照期间在该代码区域花费时间。

  • 您还应该查看 CPU 百分比。如果一个代码区域同时具有高快照共享和高 CPU 百分比,则这是一个热代码路径。

  • 通过查看代码模块,反汇编 Elasticseach 正在做的事情。

  • 如果您看到等待或停放状态,这通常是可以的。

怎么处理

  • 如果大量 CPU 时间花费在索引刷新上,则尝试将刷新间隔增加到默认的 1 秒以上。
  • 如果您在缓存中看到大量缓存,则可能是您的默认缓存设置不是最理想的并导致大量未命中。

结论

解决稳定性和性能问题确实存在挑战。找到根本原因的最好方法是使用假设的方法并证明它的正确或错误。使用这些工具和 Elasticsearch 管理 API,可以深入了解 Elasticsearch 的执行情况以及问题所在,这是一个积累经验的过程,本篇文章先总结到这里,未完待续……