admin管理员组

文章数量:1445106

Elasticsearch数据写入报错whose UTF8 encoding is longer than the max length 32766的解决方法

完整异常信息如下:

代码语言:txt复制
Document contains at least one immense term in field=\"output\"
 (whose UTF8 encoding is longer than the max length 32766), all of which were skipped. 
Please correct the analyzer to not produce such terms.  

报错原因:

在索引mapping中,该字段被动态推断为了keyword类型,而Elasticsearch限制了单个字段的最大UTF-8编码长度为32766字节,通过对比原始数据发现,output字段存储的数据为大段的日志文本内容。导致数据超过了该限制。

解决办法如下:

解决方案1:修改Filebeat配置,限制字段长度

方式1.1:使用truncate_fields进行字段截断

当前场景是通过Filebeat向Elasticsearch写入数据。在Filebeat中我们可以使用truncate_fields处理超长字段,可以在配置中添加以下内容:

代码语言:javascript代码运行次数:0运行复制
processors:
  - truncate_fields:
      fields: ["output"]
      max_bytes: 32000
      fail_on_error: false

参数解释:

参数

释义

fields: ["output"]

仅对output 字段生效。

max_bytes: 32000

限制output 的最大字节数。

fail_on_error: false

避免因截断失败导致日志丢失。

适用情况:如果业务允许接受截断数据,则可以采用该方案。

方式 1.2:使用drop_fields直接删除该字段

如果output不是必须存储的字段,可以选择舍弃该字段:

代码语言:javascript代码运行次数:0运行复制
processors:
  - drop_fields:
      fields: ["output"]

适用情况:如果业务可以丢弃output字段数据,可以选择删除来保障主要数据的正常写入。

解决方案2:调整Elasticsearch的Mapping

如果我们需要让这条超长的日志文本进入Elasticsearch,我们可以通过修改索引Mapping的方式,调整output字段的类型。

方式2.1:将output设为keyword并启用ignore_above

修改索引的 Mapping,将output 设置为keyword,并添加ignore_above:

代码语言:javascript代码运行次数:0运行复制
PUT indexname/_mapping
{
  "properties": {
    "output": {
      "type": "keyword",
      "ignore_above": 32000
    }
  }
}

解释:

参数

释义

type: "keyword"

字段类型,适用于日志类数据,防止分词导致过长。

ignore_above: 32000

让Elasticsearch自动忽略超过32000字节的值,避免写入报错。

适用情况:需要保存output字段,但可以接受超长数据被忽略。

方式 2.2:将output设为text并禁用indexing

如果只想存储output字段值,但不希望这个字段被Elasticsearch索引(避免超长字段问题),则可以按照一下方式修改mapping:

代码语言:javascript代码运行次数:0运行复制
PUT indename/_mapping
{
  "properties": {
    "output": {
      "type": "text",
      "index": false
    }
  }
}

适用情况:只需要存储该字段数据,不需要对该字段进行搜索。

解决方案 3:使用Logstash的过滤器对该字段进行处理(Filebeat → Logstash → Elasticsearch)

需要先将Filebeat将数据发送至Logstash,然后通过logstash的过滤器处理后,在通过Logstash将数据发送至Elasticsearch,在Logstash中添加mutate过滤器进行处理:

代码语言:javascript代码运行次数:0运行复制
filter {
  mutate {
    replace => { "output" => "[TRUNCATED]" }
  }
}

或者:

代码语言:javascript代码运行次数:0运行复制
filter {
  ruby {
    code => "
      if event.get('output') && event.get('output').bytesize > 32000
        event.set('output', event.get('output')[0..31999])
      end
    "
  }
}

适用情况:使用Logstash作为中间处理层,通过Logstash的filter阶段超长字段。

方案选择建议

方案

适用场景

配置难度

影响

Filebeat truncate_fields

需要保留output字段,但可接受截断

超长字段会被截断

Filebeat drop_fields

output字段不重要

该字段会被删除

Elasticsearch ignore_above

需要索引但可忽略超长值

⭐⭐

超长数据会被忽略

Elasticsearch index: false

只存储但不搜索该字段

⭐⭐

不能搜索output字段数据

Logstash filter处理

使用Logstash作为数据中间层

⭐⭐

需要引入新的组件来处理问题字段,并需要修改Logstash规则

本文标签: Elasticsearch数据写入报错whose UTF8 encoding is longer than the max length 32766的解决方法