📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 6.8-7.7+

1. 错误异常的基本描述 #

aborted 是 Elasticsearch 在操作执行过程中抛出的中止错误。当快照、恢复、分片分配或集群管理操作在执行过程中被强制中止时,就会触发此错误。这可能是用户手动取消、超时、资源不足或底层存储问题导致的。

常见现象 #

  • Elasticsearch 返回 HTTP 500 Internal Server Error409 Conflict 状态码。
  • 快照、恢复、分片重平衡等操作失败,状态为 ABORTEDFAILED
  • 在 Elasticsearch 服务端日志中会记录 IndexShardSnapshotFailedExceptionElasticsearchException: Aborted
  • 如果是通过定时任务(SLM)或自动化脚本执行操作,会导致后续操作失败或阻塞。
  • 可能导致集群状态不一致,影响后续的运维操作。

典型报错与异常栈 #

该异常的典型日志形态如下:

IndexShardSnapshotFailedException: [shard_id] aborted
    at org.elasticsearch.snapshots.SnapshotsService.updateIndexShardSnapshotStatus(SnapshotsService.java:...)
    at org.elasticsearch.snapshots.SnapshotsService.snapshotShardFailed(SnapshotsService.java:...)
    at org.elasticsearch.snapshots.SnapshotShardsService.processAborted(SnapshotShardsService.java:...)

通过 API 请求的响应通常如下:

{
  "error": {
    "root_cause": [
      {
        "type": "snapshot_creation_exception",
        "reason": "[shard_id] aborted"
      }
    ],
    "type": "snapshot_creation_exception",
    "reason": "[shard_id] aborted",
    "status": 500
  }
}

另一种常见形态(恢复操作被中止):

ElasticsearchException: Aborted
    at org.elasticsearch.indices.recovery.RecoverySourceHandler.abortRecovery(RecoverySourceHandler.java:...)
    at org.elasticsearch.indices.recovery.RecoveryTargetHandler.lambda$handlAttention$15(RecoveryTargetHandler.java:...)

2. 为什么会发生这个错误 #

Elasticsearch 的许多长时间运行的操作(如快照、恢复、分片重平衡等)都支持中止机制。源码中的逻辑是:

if (snapshotStatus.isAborted()) {
    logger.debug("[{}] [{}] Aborted on the file [{}]; exiting", shardId, snapshotId, fileName);
    throw new IndexShardSnapshotFailedException(shardId, "Aborted");
}

常见原因包括:

  • 用户手动取消:通过 API 或管理界面手动取消了正在执行的操作。
  • 超时中止:操作执行时间超过预设的超时时间。
  • 资源不足:磁盘空间不足、内存压力、CPU 饱和导致操作被强制中止。
  • 存储问题:仓库不可写、文件系统错误、网络存储访问失败。
  • 主节点变更:在操作执行期间发生主节点切换,导致操作被中止。
  • 并发冲突:同一资源的多个操作相互冲突,后一个操作导致前一个被中止。

3. 如何排查和解决这个异常和解决这个异常 #

排查步骤 #

建议按以下顺序进行排查:

第一步:查看操作状态和详细错误 #

# 查看快照状态(如果是快照操作)
curl -X GET "localhost:9200/_snapshot/my_repo/_all?pretty" | jq '.snapshots[] | select(.state == "ABORTED")'

# 查看恢复状态(如果是恢复操作)
curl -X GET "localhost:9200/_recovery?active_only=true&pretty"

# 查看操作失败原因
curl -X GET "localhost:9200/_snapshot/my_repo/snapshot_name?pretty" | jq '.snapshots[0].reason'

第二步:检查集群和节点状态 #

# 查看集群健康状态
curl -X GET "localhost:9200/_cluster/health?pretty"

# 查看分片分配状态
curl -X GET "localhost:9200/_cat/shards?v"

# 使用 allocation explain 查看分片未分配原因
curl -X GET "localhost:9200/_cluster/allocation/explain?pretty"

第三步:查看日志和监控 #

# 查看 Elasticsearch 日志中的详细错误
tail -n 500 /var/log/elasticsearch/elasticsearch.log | grep -A 30 "Aborted"

# 检查是否有主节点变更
grep "master_change" /var/log/elasticsearch/elasticsearch.log

# 检查资源使用情况
curl -X GET "localhost:9200/_nodes/stats?pretty" | jq '.nodes[] | .os.cpu.percent, .jvm.mem.heap_used_percent'

第四步:在测试环境验证 #

# 在测试环境重新执行相同操作,观察是否复现
curl -X PUT "localhost:9200/_snapshot/test_repo/test_snapshot" -H 'Content-Type: application/json' -d '
{
  "indices": "test_index",
  "ignore_unavailable": true
}'

排查时需要注意的问题_ #

  • 区分中止原因:确认是用户手动取消、超时、还是系统强制中止。
  • 检查时间线:确认操作失败时是否有主节点变更、节点重启等操作。
  • 查看资源瓶颈:磁盘、内存、CPU 等是否成为操作执行的障碍。
  • 检查并发操作:确认是否有多个操作同时操作同一资源。

4. 如何解决这个错误 #

常用修复思路 #

方案一:删除中止的操作并重新执行(推荐) #

# 如果是快照被中止,先删除
curl -X DELETE "localhost:9200/_snapshot/my_repo/aborted_snapshot"

# 确认删除成功
curl -X GET "localhost:9200/_snapshot/my_repo/aborted_snapshot?pretty"
# 应该返回 404 Not Found

# 重新执行操作
curl -X PUT "localhost:9200/_snapshot/my_repo/new_snapshot" -H 'Content-Type: application/json' -d '
{
  "indices": "my_index*",
  "ignore_unavailable": true
}'

方案二:检查并修复资源问题 #

# 检查磁盘空间
df -h /path/to/elasticsearch/data
df -h /path/to/snapshot/repo/

# 检查内存使用
curl -X GET "localhost:9200/_nodes/stats/jvm?pretty" | jq '.nodes[] | .jvm.mem'

# 必要时扩容节点或清理空间

方案三:调整超时设置 #

// 如果是因为超时导致中止,增加超时时间
{
  "indices": "my_index*",
  "ignore_unavailable": true,
  "include_global_state": false
}
// 或者通过集群设置调整全局超时
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d '
{
  "persistent": {
    "index.snapshot.interval": "120s"
  }
}'

方案四:使用 API 取消并重新执行 #

# 如果操作卡住,可以手动取消(某些操作支持)
# 然后重新执行
curl -X PUT "localhost:9200/_snapshot/my_repo/new_snapshot" -H 'Content-Type: application/json' -d @snapshot.json

后续注意事项与推荐建议_ #

  • 建立操作监控:监控长时间运行的操作(快照、恢复、重平衡)的状态和耗时。
  • 避免并发冲突:对于同一资源(如同一索引、同一仓库)的操作,错开执行时间。
  • 检查资源充足:确保磁盘、内存、CPU 等资源充足,避免操作被强制中止。
  • 设置合理的超时:根据操作复杂度设置合理的超时时间,避免过早超时。
  • 定期清理中止的操作:对于已经中止的操作,及时清理,避免影响后续操作。

借助 INFINI 产品提升排障效率_ #

  • INFINI Console 提供集群操作的可视化监控界面,可以直观地查看、管理和调试快照、恢复等操作。通过 Console 的操作管理功能,可以快速发现中止的操作、查看失败原因,并直接删除后重建。

  • INFINI Gateway 可以作为 Elasticsearch API 的代理层,在操作请求到达 Elasticsearch 之前进行拦截和检查。Gateway 可以自动检测长时间运行的操作,并根据预定义的策略(如自动取消、重新排队、转发到备用集群等)进行处理。

  • 对于依赖 Elasticsearch 运维操作的团队,建议结合 INFINI Console 的操作监控功能和 INFINI Gateway 的请求治理能力,建立从操作执行、监控、到故障恢复的完整自动化流程,减少因操作中止导致的运维中断。

5. 小结_ #

aborted 是一个典型的操作中止错误,根源在于长时间运行的操作被强制中断。虽然报错信息比较底层,但解决思路需要根据具体情况来决定:是删除后重建、修复资源问题,还是调整超时设置。

在实际工作中,为避免此类问题,建议建立操作监控体系、错开并发操作时间、并确保资源充足。更重要的是,考虑使用 INFINI Console 来实现可视化的操作管理,使用 INFINI Gateway 来拦截和预处理操作请求,从源头减少操作中止的发生。

相关错误_ #

参考文档_ #

附:日志上下文_ #

下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:

for (String fileName : fileNames) {
    if (snapshotStatus.isAborted()) {
        logger.debug("[{}] [{}] Aborted on the file [{}]; exiting", shardId, snapshotId, fileName);
        throw new IndexShardSnapshotFailedException(shardId, "Aborted");
    }  
    
    logger.trace("[{}] [{}] Processing [{}]", shardId, snapshotId, fileName);
    final StoreFileMetaData md = metadataFromStore.get(fileName);
    BlobStoreIndexShardSnapshot.FileInfo existingFileInfo = null;