Elasticsearch 常见的 8 种错误及最佳实践

标签: | 发表时间:2020-08-08 07:58 | 作者:
出处:https://mp.weixin.qq.com

题记

Elasticsearch 社区有大量关于 Elasticsearch 错误和异常的问题。

深挖这些错误背后的原因,把常见的错误积累为自己的实战经验甚至是工具,不仅可以节省我们的开发和运维时间,而且可以帮助确保 Elasticsearch 集群的长期健康运行。

常见的异常、原因和常规最佳实践拆解如下,这些最佳实践可以帮助我们更有效地识别、最小化定位和处理异常问题。

1、 Mapper_parsing_exception

Elasticsearch 依靠映射(Mapping)定义的数据类型处理数据。

映射定义了文档中的字段并指定了它们对应的数据类型,例如日期类型 Date、长整数类型 long 和  字符串类型 text。

如果索引文档包含没有定义数据类型的新字段,Elasticsearch将使用动态映射来估计字段的类型,并在必要时将其从一种类型转换为另一种类型。

如果Elasticsearch无法执行此转换,它将引发“ mapper_parsing_exception无法解析” 异常。

如果此类异常太多会降低索引吞吐量。

实战举例如下:

    DELETE mytest_0001      
PUT mytest_0001/_doc/1
{
  "name":"John"
}

PUT mytest_0001/_doc/2
{
  "name": {
    "firstname": "John",
    "lastname": "doe"
  }
}

为避免此问题,可以在创建索引时显示定义Mapping,明确敲定字段类型。或者可以使用 _mapping动态添加新字段映射。

动态更新索引实战:

    PUT mytest_0001/_mapping      
{
  "properties": {
    "title": {
      "type": "text"
    }
  }
}

请注意:虽然可以通过如上命令动态添加字段,但是不能更改现有字段映射。

若想做字段类型的修改,需要重新定义Mapping 结合 reindex 和 alias 别名 实现。

2、BulkIndexError

批量索引大型数据集通常更有效。

例如,您可以执行一个批量操作来索引 1,000 个文档,而不是使用 1,000 个索引操作。

批量操作可以通过 bulk API 完成。

批量操作实战:

    PUT my_index_0003/_bulk      
{"index":{"_id":1}}
{"myid":"c12345"}
{"index":{"_id":2}}
{"myid":"C12456"}
{"index":{"_id":3}}
{"myid":"C31268"}

但是,此过程容易出错。执行批量操作的过程中,你需要仔细检查:数据类型不匹配和空值匹配等问题。

对于批量 API ,你需要格外警惕,因为即使有数百个肯定的响应,批量中的某些索引请求也可能失败。

批量操作捕获错误实战:

     @Override      
  public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
 if (response.hasFailures()) {
  for (int i = 0; i < response.getItems().length; i++) {
   BulkItemResponse item = response.getItems()[i];
   if (item.isFailed()) {
      IndexRequest ireq = (IndexRequest) request.requests().get(i);
      logger.error("Failed while indexing to " + item.getIndex() + " type " + item.getType() + " " +
          "request: [" + ireq + "]: [" + item.getFailureMessage() + "]");
   }
  }
 }
  }

除了提前设置具有所有适当条件的批量 API 之外,还要浏览响应列表并检查每个响应,以确保所有数据均按预期索引。

3、搜索超时错误:ConnectionTimeout,ReadTimeoutError,RequestTimeout 等

如果在指定的搜索时间内未收到响应,则请求将失败并返回错误消息。这称为搜索超时。

搜索超时很常见,多种原因都可以导致搜索超时,例如:大型数据集或占用大量内存的查询。

要消除搜索超时,可以通过如下实现解决:

3.1 增加 elasticsearch.requestTimeout

设置注意:应该在 HTTP 客户端而不是 Elasticsearch 中指定 timeout 值,Elasticsearch 端没有请求超时参数。

kibana 请求显示超时,优化方案如下:

kibana 默认请求等待时间是 30 秒,可以在 kibana.yml 中调整该值。

    elasticsearch.requestTimeout: 90000      

3.2 减少每个请求返回的文档数量

不要将请求的 size 值设置太大,结合:from、size 深度翻页机制实现。

全量遍历借助 scroll 实现。

3.3 缩小时间范围

请求时间范围越长(比如 时间跨度周期 1  年以上的数据),请求数据量越大,超时的可能性越高。

3.4 调整内存设置

通过配置单个查询的内存断路器来限制单个查询的内存使用量。

如:将 index.breaker.request.limit 限制为 40%,默认是 60%。

集群层面设置请求熔断内存实战:

    PUT /_cluster/settings      
{
  "persistent": {
    "indices.breaker.request.limit": "40%"
  }
}

通过将search.max_buckets设置为 5000 (默认值:10000)来限制用于聚合的存储桶数。

    PUT _cluster/settings      
{
  "transient": {
    "search.max_buckets": 5000
  }
}

3.5 优化查询、索引和分片。

3.6 启用慢速搜索日志

监视搜索运行时间,扫描繁重的搜索等等。

慢日志开启实战:

    PUT /_settings      
{
  "index.search.slowlog.threshold.query.debug": "30s",
  "index.search.slowlog.threshold.fetch.debug": "30s",
  "index.indexing.slowlog.threshold.index.debug": "30s"
}

4、 All Shards Failed

在 Elasticsearch 搜索时,可能会遇到 “All Shards Failed” 的错误消息。

发生 All Shards Failed 的几种情况:

  • 当读取请求无法从分片获得响应时
  • 当由于集群或节点仍处于初始启动过程而无法搜索数据
  • 当分片丢失或处于恢复模式并且集群为红色时

造成 All Shards Failed 可能的原因:

  • 节点可能已断开连接或重新连接
  • 正在查询的分片可能正在恢复中,因此不可用
  • 磁盘可能已损坏
  • 搜索query 语句可能写的有问题。例如,引用字段类型错误的字段。
  • 配置错误可能导致操作失败。

问题排查实战举例:

    GET /_cat/health      
GET /_cat/indices?v
GET _cluster/health/?level=shards
GET _cluster/allocation/explain

5、进程内存锁定失败:“memory locking requested for elasticsearch process but memory is not locked”

为了使节点保持健康,必须确保没有将 JVM 内存换出到磁盘。

发生系统 swapping (交换)的时候 Elasticsearch 节点的性能会非常差,也会影响节点的稳定性。

所以要不惜一切代价来避免 swapping 。swapping会导致Java GC的周期延迟从毫秒级恶化到分钟,更严重的是会引起节点响应延迟甚至脱离集群。

限制 elasticsearch占用的内存情况,可选择少用swap。而:启用 bootstrap.memory_lock 就是限制交换的三种方案之一。

在 elasticsearch.yml 中 启动 memory_lock 实践:

    bootstrap.memory_lock: true      

报错复现如下:

    [,260][INFO ][o.e.n.Node               ] [node-1] starting ...      
[,529][INFO ][o.e.t.TransportService   ] [node-1] publish_address {172.17.0.5:9300}, bound_addresses {172.17.0.5:9300}
[,537][INFO ][o.e.b.BootstrapChecks    ] [node-1] bound or publishing to a non-loopback address, enforcing bootstrap checks
[,565][ERROR][o.e.b.Bootstrap          ] [node-1] node validation exception
[1] bootstrap checks failed
[1]: memory locking requested for elasticsearch process but memory is not locked
[,575][INFO ][o.e.n.Node               ] [node-1] stopping ...
[,596][INFO ][o.e.n.Node               ] [node-1] stopped
[,597][INFO ][o.e.n.Node               ] [node-1] closing ...
[,615][INFO ][o.e.n.Node               ] [node-1] closed

centos 7.x 解决方案:在 /etc/security/limits.conf 文件中添加如下内容,并保持,然后重启 elasticsearch 即可。

    elasticsearch soft memlock unlimited      
elasticsearch hard memlock unlimited

最佳实践之验证启动是否成功:

    GET _nodes?filter_path=**.mlockall      

正确返回结果如下:

    {      
  "nodes" : {
    "gJUT-E48u_nUw" : {
      "process" : {
        "mlockall" : true
      }
    }
  }
}

6、引导检查失败 Bootstrap Checks Failed

Bootstrap 检查会在 Elasticsearch 开始之前检查各种设置和配置,以确保其可以安全运行。

如果引导检查失败,则它们可以阻止 Elasticsearch 启动(如果处于生产模式)或在开发模式下发出警告日志。

建议你熟悉引导检查所强制执行的设置,并注意它们在开发和生产模式上是不同的。通过将系统属性

es.enforce.bootstrap.checks设置为true,可以强制执行引导检查。

主要检查内容包含但不限于:

  • 堆的大小检查
  • 文件描述符
  • 最大线程数
  • 文件大小限制
  • 最大虚拟内存
  • 最大映射数
  • 客户端jvm检查
  • 垃圾收集检查
  • OnError和OnOutOfMemoryError检查 ......

最佳实践:在jvm.option中添加如下配置后重启 Elasticsearch。

    -Des.enforce.bootstrap.checks=true      

7、TransportError

在Elasticsearch中,传输模块核心功能是:集群中节点之间的通信。

传输错误Transport errors 经常出现,失败可能是如下的原因引起的:

  • 分片丢失

  • 设置冲突

  • 数据建模不合理

  • 网络故障

  • .....

常见的 Transport errors 错误如下:
    TransportError(403, u'cluster_block_exception', u'blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];')      

原因分析:

当没有足够的可用磁盘空间供 Elasticsearch 在节点之间分配时,可能会发生这种情况。

解决方案:

  • 增加磁盘空间
  • 删除旧数据以释放空间
  • 更新索引只读模式。

注意:当磁盘使用率>=95%,index.blocks.read_only_allow_delete设置是防止节点用完磁盘空间的最后手段。不再允许写入,只能删除。

以下命令能重置索引上的只读索引块:

    PUT /_all/_settings      
{
  "index.blocks.read_only_allow_delete": null
}

在分配所有分片之前,尝试使用刚刚创建的索引时,可能会出现另一种传输错误。

在这种情况下,报错如下:

    TransportError(503, u”).       

传输错误也可能与  Mapping 问题相关。

例如,当您尝试索引具有与其映射不同的数据类型的字段时,可能报错如下:

    TransportError (400, u’mapper_pasing_exception’)       

8、初始化/启动失败 Initialization/Startup Failures

有时候,分片的问题可能会阻止 Elasticsearch 启动。

例如,当使用有冲突的 Elasticsearch 版本时,您可能报错如下:

    “ Elasticsearch java client initialization fails”       

     “\Common was unexpected at this time.”      

最佳实践:

做好版本核验,确保开发使用的 jar 包版本和部署版本一致。

9、如何最小化错误和异常?探究错误及解决方案的底层逻辑

如果你不想仅仅一次处理一条错误消息,当你处理的问题多了以后,你会发现:很多错误和异常与如下三个更深层次的问题相关:

  • 安装和配置问题
  • 索引新数据问题
  • 集群运行变慢问题

深究拆解如下:

9.1  安装和配置问题

快速安装 Elasticsearch 很容易,但是要确保其生产级别的运行,需要仔细核对配置。

这可以帮助避免各种错误和异常,例如:引导检查失败  bootstrap checks failure 问题。

9.2 索引新数据问题

在 Elasticsearch 中,你必须非常仔细的对字段命名、正确使用模板 template、数据建模规范化。

仔细核对这些参数配置,可以帮助你避免诸如:映射 mapping 异常和批量索引错误( bulk index errors)之类的问题。

9.3 集群速度变慢问题

随着数据规模的扩大,以及操作频繁度的扩展,Elasticsearch 有时会发生意外导致检索响应速度慢,并可能弹出超时报错。

因此,你必须持续监控集群的如下指标内容:

  • 借助 kibana 或者 cerebro 等可视化工具观察错误率及走势
  • 监控错误日志
  • 核对拒绝的指标

以提前将可能错误扼杀在摇篮阶段,并确保集群一切正常。

10、结论

Elasticsearch 运维或开发实战必定会遇到错误或异常。

尽管我们无法完全避免,但是可以采用一些最佳实践来帮助减少错误或异常的发生,并在出现问题时更有效地解决问题。

快速有效地解决集群缓慢等复杂问题离不开如下三点:

第一:密切关注各项设置和配置;

第二:索引新数据时要小心;

第三:确保集群各项指标可被监视与可视化查看。

简而言之,你应该将错误和异常视为优化 Elasticsearch 集群基础架构的机会,而不必过分担心它们的出现。


参考:

https://opster.com/blogs/common-elasticsearch-errors-and-exceptions/

Elasticsearch 官方文档 

https://discuss.elastic.co/t/how-to-identify-message-causing-error-in-bulk-request/42885/5

相关 [elasticsearch 常见 错误] 推荐:

Elasticsearch 常见的 8 种错误及最佳实践

- -
Elasticsearch 社区有大量关于 Elasticsearch 错误和异常的问题. 深挖这些错误背后的原因,把常见的错误积累为自己的实战经验甚至是工具,不仅可以节省我们的开发和运维时间,而且可以帮助确保 Elasticsearch 集群的长期健康运行. 常见的异常、原因和常规最佳实践拆解如下,这些最佳实践可以帮助我们更有效地识别、最小化定位和处理异常问题.

Spring MVC的常见错误

- - Java译站
10年前我开始自己的职业生涯的时候,Struts还是市场上的主流标准. 然而多年过后,我发现Spring MVC已经越来越流行了. 对我而言这并不意外,因为它能和Spring容器无缝集成,同时它还提供了灵活性及扩展性. 从我迄今为止对Spring的经验来看,我发现有不少人在配置Spring的时候经常会犯一些常见的错误.

Linux下的常见错误配置

- - FreeBuf.COM
    经过对大量客户的配置审计与渗透测试,我们总结出了一些Linux系统下的常见配置错误. 我们相信总结、回顾这些常见错误可以在以后为我们节省更多时间与资源,更重要的是可以帮助系统管理员,使其服务器更加安全可靠.     五个常见配置错误如下:. 1、用户/home目录的权限 2、系统中的getgid与setuid程序 3、全局可读/可写的文件/目录 4、使用包含漏洞的服务 5、默认的NFS挂载选项或不安全的导出选项.

varnish常见错误的解决方法

- - 开心平淡对待每一天。热爱生活
这是因为从2.0.6以后,obj.ttl 已经变更为beresp.ttl. 2. beresp.cacheable的含义是什么. 官方的解释:beresp.cacheable. A response is considered cacheable if HTTP status code is 200, 203, 300, 301, 302, 404 or 410 and pass wasn’t called in vcl_recv.

Mark Lutz:Python程序员的常见错误

- - 博客 - 伯乐在线
译注: Mark Lutz 是《Learning Python | 学习Python》的作者之一. 在这篇文章中,我将总结新老Python程序员常犯的一些错误,以帮助你们在自己的工作避免犯同样或类似错误. 首先我要说明一下的是,这些都是来源于第一手的经验. 我以讲授Python的知识为生. 在过去的7年里,我已经给上千名学生讲授上百堂Python的课程,同时看着这些学生们犯同样的错.

SEO中常见的七个错误

- - Java译站
SEO作为一个战略营销服务多年来它的效果一直都是非常不错的. 他们通过给网站进行深度优化从而使网站流量得到了质的提升. 品牌的曝光度和知名度的提升. 这些理由足以让营销人员将SEO作为主要的在线营销策略了. 然而,需要仔细调整SEO来适应客户企业以及目标用户的分布特征. 许多SEO服务提供商在替客户取得满意的效果前都经历了许多常见的错误的方法.

hadoop常见错误及解决办法!

- - 企业架构 - ITeye博客
转: http://p-x1984.iteye.com/blog/989577 1:Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out Answer: 程序里面需要打开多个文件,进行分析,系统一般默认数量是1024,(用ulimit -a可以看到)对于正常使用是够了,但是对于程序来讲,就太少了.

[译文]避免常见的六种HTML5错误用法

- Vingel - UED TEAM,用户体验设计,web前端开发
避免常见的六种HTML5错误用法. 原文链接请点击此处,作者为Richard Clark.. 本文为原创翻译,同时对原文做了一些简化处理. 本文遵循署名-非商业性使用协议. 一、不要使用section作为div的替代品. 人们在标签使用中最常见到的错误之一就是随意将HTML5的
等价于
——具体地说,就是直接用作替代品(用于样式).

避免常见的六种HTML5错误用法

- Amo - HTML5研究小组
原文链接请点击此处,作者为Richard Clark.. 本文为原创翻译,同时对原文做了一些简化处理. 本文遵循署名-非商业性使用协议. 一、不要使用section作为div的替代品. 人们在标签使用中最常见到的错误之一就是随意将HTML5的
等价于
——具体地说,就是直接用作替代品(用于样式).

五个常见的SEO错误(以及六个小建议!)

- - Google China Blog
发表者: Maile Ohye,开发者项目技术负责人. 原文: Five commen SEO mistakes (six good ideas). 转载自: 谷歌中文网站管理员博客. 发布时间:2012年6月21日 上午 10:49:00. 为了帮助您避免网站管理员常见的搜索引擎优化(SEO)错误,我录制了一段 视频,介绍了我在搜索引擎优化行业中注意到的五个常见错误.