解决elasticsearch索引里面的值的类型冲突,导致新提交的值与预期的key 类型不一致.引发了日志会丢失的情况。
问题
最近在使用kibana时,发现管理索引那里,某个索引下面有字段冲突的提示,然后去查看fluentd客户端的运行情况,发现在fluent程序自己的日志里,偶尔会出现几条错误信息:’ElasticsearchError error=“400 - Rejected by Elasticsearch”’ , 这是怎么回事呢?下面是错误的日志:
2018-08-13 18:02:55 +0800 [warn]: #0 dump an error event: error_class=Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError error="400 - Rejected by Elasticsearch" location=nil tag="athena" time=2018-08-13 18:01:51.000000000 +0800 record={"method"=>"GET", "path"=>"/", "format"=>"html", "controller"=>"HomeController", "action"=>"home", "status"=>302, "duration"=>26.69, "view"=>0.0, "db"=>10.06, "location"=>"https://x.x.com/x/xxoo", "params"=>"{}", "referrer"=>"https://x.o.com/x/ooooo/166888", "user_id"=>101010101010, "session_id"=>"199000000000000"}
分析
在kibana 那里,对提示conflict 的location
字段进行编辑,发现页面最下方有些重要提示,如图1所示:
从上面提示可以看出,location 字段在不同索引里的类型发生了变化,之前是text
类型,后来变成了geo_point
. 为了确认这点,我们可以通过es客户端,或者直接用curl,对es的mapping进行查看。
验证
我这里使用curl方式,先查看为text类型的索引。
curl -X GET "localhost:9200/logs-app-athena-2018.08.10/_mapping/" -H 'Content-Type: application/json' | jq '.'
这是location字段的定义:
"location": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
然后再去看下提示location 为geo_point 类型的索引看下。还是用上面的命令,只是改下索引的名字。得到的结果如预期一样。
"location": {
"type": "geo_point"
},
但为什么从12号开始的索引里,这个值的类型就变成geo_ip
了呢?仔细想了想,我11号好像做了一点操作。就是在logs-app-nginx*
索引模版里都添加了一个_default_
,但为什么这个会影响到logs-app-athena 的索引呢?这个问题一直没想明白。这个是我当时做的操作:
curl -X GET "localhost:9200/_template/logs-app-nginx-* -d '{"order":0,"template":"*","settings":{},"mappings":{"_default_":{"properties":{"location":{"type":"geo_point"}}}}}'
解决方案
- 修改logs-app-athena系列索引的
_default_
值中的location类型为text
curl -X PUT "localhost:9200/logs-app-athena-*/_mappings/" -H 'Content-Type: application/json' -d'
{
"_default_": {
"properties": {
"location": {
"type": "text"
}
}
}
}
Note: 在elasticsearch 6.0以后默认不在使用_default_ mappings.
default mapping
总结
这次问题的出现,对es又多了一点点了解,还要多看看官方文档发布的更新日志,可能某些功能在相应的版本里就不推荐使用了。
另外做这次改动的根本原因是nginx日志都在logs-app-nginx-*
索引里,而location 字段没有被自动解析成geo_point
类型。后来不得已,换成了logstash-*
为前缀的索引后,类型才自动变成了geo_point
。不知道还有没有其它方法可以实现。
参考
change lat lon from float to geo_point