持续创作,加速成长!这是我参与「掘金日新计划 · 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 的执行情况以及问题所在,这是一个积累经验的过程,本篇文章先总结到这里,未完待续……