某天打开 Jaeger UI 后,发现里面没有任何数据了,这是个奇怪的问题。html
而后立立刻服务器检查了 jaeger-collector, jaeger-agent, jaeger-query 和 Elasticsearch 的服务进程、端口及网络通讯。全部一切都正常。node
而后进一步排查数据流向问题,经过排查 jaeger-collector 日志,发现 jaeger-agent -> jaeger-collector 之间的数据传输没有问题。git
而 jaeger-collector -> ES 之间数据传输时报错了。错误以下:github
{"level":"error","ts":1576483292.2617185,"caller":"config/config.go:130","msg":"Elasticsearch part of bulk request failed","map-key":"index","response":{"_index":"jaeger-span-2019-12-16","_type":"_doc","status":400,"error":{"type":"validation_exception","reason":"Validation Failed: 1: this action would add [10] total shards, but this cluster currently has [992]/[1000] maximum shards open;"}},"stacktrace":"github.com/jaegertracing/jaeger/pkg/es/config.(*Configuration).NewClient.func2\n\t/home/travis/gopath/src/github.com/jaegertracing/jaeger/pkg/es/config/config.go:130\ngithub.com/jaegertracing/jaeger/vendor/github.com/olivere/elastic.(*bulkWorker).commit\n\t/home/travis/gopath/src/github.com/jaegertracing/jaeger/vendor/github.com/olivere/elastic/bulk_processor.go:588\ngithub.com/jaegertracing/jaeger/vendor/github.com/olivere/elastic.(*bulkWorker).work\n\t/home/travis/gopath/src/github.com/jaegertracing/jaeger/vendor/github.com/olivere/elastic/bulk_processor.go:501"}
提取关键错误信息json
this action would add [10] total shards, but this cluster currently has [992]/[1000] maximum shards open
根据报错,能够看出,目前集群的shard数量已是992个,集群最大索引为1000个,将要添加的shard 数量超越了集群管理的最大值,因此数据没法写入。vim
1000 个shards的限制是怎么来的?服务器
根据官方解释,从Elasticsearch v7.0.0 开始,集群中的每一个节点默认限制 1000 个shard,若是你的es集群有3个数据节点,那么最多 3000 shards。这里咱们是开发环境,只有一台es。因此只有1000。网络
若是您是Elasticsearch的新手,那么了解基本术语并掌握基本概念很是重要。架构
Elasticsearch集群的简单图app
群集– Elasticsearch群集由一个或多个节点组成,而且能够经过其群集名称进行标识。
节点–一个Elasticsearch实例。在大多数环境中,每一个节点都在单独的盒子或虚拟机上运行。
index–在Elasticsearch中,索引是文档的集合。
分片–因为Elasticsearch是分布式搜索引擎,所以索引一般会分为多个元素,这些元素称为分片,分布在多个节点上。Elasticsearch自动管理这些分片的排列。它还会根据须要从新平衡分片,所以用户无需担忧细节。
副本–默认状况下,Elasticsearch为每一个索引建立五个主要分片和一个副本。这意味着每一个索引将包含五个主要分片,而且每一个分片将具备一个副本。
分配多个分片和副本是分布式搜索功能设计的本质,它提供了高可用性并能够快速访问索引中的文档。主分片和副本分片之间的主要区别在于,只有主分片才能接受索引请求。副本和主分片均可以知足查询请求。
在上图中,咱们有一个Elasticsearch集群,该集群由默认分片配置中的两个节点组成。Elasticsearch会自动在两个节点之间排列五个主要分片。每一个主碎片都有一个副本碎片,可是这些副本碎片的排列与主要碎片的排列彻底不一样。
请记住,number_of_shards
值与索引有关,而不与整个集群有关。此值指定每一个索引的分片数量(而不是集群中的总主分片)。
副本主要是为了提升搜索性能,用户能够随时添加或删除它们。它们为您提供了额外的容量,更高的吞吐量和更强的故障转移。咱们始终建议生产集群具备2个副本以进行故障转移。
找到了问题缘由,那么如何解决这个问题?
解决这个问题须要回答两个问题:
Index
多少个 Shard
合适?配置 Elasticsearch 集群后,对于分片数,是比较难肯定的。由于一个索引分片数一旦肯定,之后就没法修改,因此咱们在建立索引前,要充分的考虑到,之后咱们建立的索引所存储的数据量,不然建立了不合适的分片数,会对咱们的性能形成很大的影响。
若是之后发现有必要更改分片的数量,则须要从新索引全部源文档。(尽管从新编制索引是一个漫长的过程,但能够在不停机的状况下完成)。
主分片配置与硬盘分区很是类似,在硬盘分区中,原始磁盘空间的从新分区要求用户备份,配置新分区并将数据重写到新分区上。
稍微过分分配是好的。可是若是你给每一个 Index 分配 1000 个Shard 那就是很差的。
请记住,您分配的每一个分片都须要支付额外费用:
咱们的客户指望他们的业务增加,而且其数据集会相应地扩展。所以,始终须要应急计划。许多用户说服本身,他们将遇到爆炸性增加(尽管大多数用户从未真正看到没法控制的增加)。此外,咱们全部人都但愿最大程度地减小停机时间并避免从新分片。
若是您担忧数据的快速增加,那么咱们建议您关注一个简单的约束:Elasticsearch的最大JVM堆大小建议约为30-32GB。这是对绝对最大分片大小限制的可靠估计。例如,若是您确实认为能够达到200GB(但在不更改其余基础架构的状况下没法达到更大容量),那么咱们建议分配7个分片,或最多8个分片。
绝对不要为从如今起三年后达到的过高的10 TB目标分配资源。
若是如今你的场景是分片数不合适了,可是又不知道如何调整,那么有一个好的解决方法就是按照时间建立索引,而后进行通配查询。若是天天的数据量很大,则能够按天建立索引,若是是一个月积累起来致使数据量很大,则能够一个月建立一个索引。若是要对现有索引进行从新分片,则须要重建索引.
这是正确的改变配置文件中的index.number_of_shards
默认值将涉及更改全部节点上的设置,而后理想地按照rolling restarts的指导方针从新启动实例。
可是,若是这不是一个选项,若是在建立新索引时在设置中明确指定number_of_shards
并不理想,那么解决方法将使用index templates
能够建立index_defaults
默认值,以下所示
PUT /_template/index_defaults { "template": "*", "settings": { "number_of_shards": 4 } }
这会将index_defaults
模板中指定的设置应用于全部新索引。
maximum shards open
设置为多大合适?对于分片数的大小,业界一致认为分片数的多少与内存挂钩,认为 1GB 堆内存对应 20-25 个分片。所以,具备30GB堆的节点最多应有600个分片,可是越低于此限制,您可使其越好。而一个分片的大小不要超过50G,一般,这将有助于群集保持良好的运行情况。
个人观点是开发、测试环境,若是数据不那么重要的话,能够清空全部 index
DELETE /_all
而后,从新设置默认值,下降number_of_shards
数量,同时提升max_shards_per_node
的数量。
vim elasticsearch.yml # Set the number of shards (splits) of an index (5 by default): # index.number_of_shards: 2 # Set the number of replicas (additional copies) of an index (1 by default): # index.number_of_replicas: 1 cluster.max_shards_per_node: 3000
对于生产环境
vim elasticsearch.yml # Set the number of shards (splits) of an index (5 by default): # index.number_of_shards: 5 # Set the number of replicas (additional copies) of an index (1 by default): # index.number_of_replicas: 2 cluster.max_shards_per_node: 3000
Index 的配置参数在es配置文件里直接配置,会报错。不过能够用Kibana来设置。
打开 console
DELETE /_all PUT _template/default { "index_patterns" : ["jaeger*"], "order" : 1, "settings": { "number_of_shards": "2", "number_of_replicas": "1" } } PUT _template/default1 { "index_patterns" : ["*"], "order" : 0, "settings": { "number_of_shards": "5", "number_of_replicas": "2" } } PUT /_cluster/settings { "transient": { "cluster": { "max_shards_per_node":10000 } } }
order
(Optional,integer) Order in which Elasticsearch applies this template if index matches multiple templates.
order
values are merged first.order
values are merged later, overriding templates with lower values.能够发现生效了
$ curl -X GET 'http://127.0.0.1:9200/\_cat/indices?v' health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open jaeger-span-2019-12-17 2DHx3EaGTnKlVC4mefsUJw 2 1 27 0 22kb 22kb yellow open .kibana SeD9KqnhR7aKpzc2\_AcIDw 2 1 1 0 4.3kb 4.3kb
最重要的是,要按期删除无用数据,好比对于jaeger
的数据,能够每月初删除一个月前的全部数据,即只保留最近1个月的Index
数据。
仅保存近30天的数据任务分解为
delete_by_query
设置检索近30天数据;forcemerge
操做,手动释放磁盘空间。#!/bin/sh curl -XPOST "http://127.0.0.1:9200/jaeger-*/_delete_by_query?conflicts=proceed" -H'Content-Type:application/json' -d'{ "query": { "range": { "pt": { "lt": "now-100d", "format": "epoch_millis" } } } } '
force merge API
这里有3个参数能够用
forcemerge
脚本以下:
#!/bin/sh curl -XPOST 'http://127.0.0.1:9200/_forcemerge?only_expunge_deletes=true&max_num_segments=1'
有没有更简便的方法?
有,使用ES官网工具——curator工具。
curator 简介
主要目的:规划和管理ES的索引。支持常见操做:建立、删除、合并、reindex、快照等操做。curator 官网地址
curator 适用场景
最重要的是:
仅以删除操做为例:curator能够很是简单地删除x天后的索引。不过前提是:索引命名要遵循特定的命名模式——如:以天为命名的索引:
jaeger-span-2019-09-20 jaeger-span-2019-10-07 jaeger-service-2019-10-11
action.yml
中的delete_indices
下的timestring
对应。经过ES API
零时修改
curl -X PUT "dev-jaeger-es01.bj:9200/_cluster/settings" -H 'Content-Type: application/json' -d' { "persistent" : { "cluster.max_shards_per_node" : "5000" } } '
也可在kibana
的tools
中改变设置
PUT /_cluster/settings { "transient": { "cluster": { "max_shards_per_node":10000 } } }
Optimizing Elasticsearch: How Many Shards per Index?
How many shards should I have in my Elasticsearch cluster?
从 10 秒到 2 秒!ElasticSearch 性能调优
Elasticsearch调优实践
索引设置