Elasticsearch线上问题
WangScaler: 一个用心创作的作者。
声明:才疏学浅,如有错误,恳请指正。
一、429拒绝访问
1、错误信息
1 ERROR:root:TransportError(429, 'circuit_breaking_exception', '[parent] Data too large, data for [] would be [2042405264/1.9gb], which is larger than the limit of [2040109465/1.8gb], real usage: [2042404224/1.9gb], new bytes reserved: [1040/1kb], usages [request=0/0b, fielddata=0/0b, in_flight_requests=1040/1kb, model_inference=0/0b, eql_sequence=0/0b, accounting=113390388/108.1mb]')
我们ES的内存设置的是2G。从图上可以看出,内存已经不够用了。我们在Elasticsearch集群降级为单节点已经介绍了内存的设置范围以及原因,有兴趣的可以看看。
2、429状态码的含义
我们知道我们对ES的访问是通过HTTP请求,所以首先要知道429状态码在HTTP请求中代表的含义。429状态码表示Too Many Requests即当前客户端已经在给定的时间内发送了太多的请求。通俗的理解就是在单位时间内,我们发送了大量的请求到ES,ES处理不了这么多请求,就发生了熔断,来保护ES。
3、根本原因
ES的请求处理不了那么多,也就是性能上低于我们的正常业务。从第一步我们也可以看出我们内存不够用了,其次很可能是用于处理请求的线程池资源数受限。
4、解决方案
-
①增大单个节点的内存,或者增大节点数量。道理很简单,增大单个节点的内存,即增大了单个节点的处理能力。而增大节点的数量,就会将请求分散到更多的节点,减少了每个节点的压力。不过这种方案往往在现实中不好实现,为什么?因为增大配置就需要钱,哈哈,为公司节省才能给老板买新车,能省就省。
-
②增加线程池线程数量。可以通过
GET /_nodes/节点/settings/
查看thread_pool线程池的配置,但是增加配置,势必需要更多的内存,我们如果面临内存不足的痛楚,可能单纯的增大会带来相反的效果。 -
③从根本上不好解决的问题,那么只能从业务上想办法,首先找到业务上大批量请求的原因。比如我的是设备数据入库,而数据都是同一时间点上传,而我入库之前是先查看索引是否存在,不在的话,手动创建索引并指定mapping,因为指定了mapping才方便后续的聚合分析,所以必须保证索引是我们手动创建的,而不是自动生成的。
- 减少批量请求。假设有1000设备数据上来,就需要1000个查看索引的请求,1000个写入数据的请求。负载量确实很大,向我们的索引其实只需要查看一次就已经确定索引是否存在了,可以将已经存在的索引缓存到redis,减少一半的请求。
- 以时间换安全。假设数据每个设备每分钟上传一条,我们如果对数据实时性要求不高的话,可以延长调度数据的时间,假如每小时调度一把,这样一个小时一个设备只有一个bulk请求,每个请求60条数据。假设10000个设备,每调度100个设备休眠5s。只需要500s即不到9分钟。也就是每一小时拿出9分钟调度所有设备的数据,且中间有休眠,来缓解ES的压力
5、其他
之前查阅资料,有说field data
的缓存不够用,应该设置为JVM内存的40%或更小
PUT /_cluster/settings" -H 'Content-Type: application/json' -d '{ "persistent" : { "indices.breaker.fielddata.limit" : "40%" } }'
或者修改配置文件config/elasticsearch.yml
indices.fielddata.cache.size: 40%
第二种需要重启生效
不过text类型的字段在聚合、排序或者脚本访问时才会使用fielddata作为查询时内存数据结构,我的数据都是double类型的,显然于此无关。如果你的是text类型的数据,则需要避免text类型的字段上使用firlddata,默认情况下,es是禁用的。
如果你必须开启的话,可以清除下缓存
POST _cache/clear?fielddata=true
二、分片不够
1、错误信息
Failed: 1: this action would add [1] total shards, but this cluster currently has [1000]/[1000] maximum shards open;
2、根本原因
从上一步,很明显可以看出1000个分片已经达到最大了,也就是ES默认的最大分片数是1000个,我们按照一个节点3个分片算,也就是1000/3=333个索引。那么我们只能创建333个索引,然而在现实中这远远不够的,所以需要增大这个配置。
3、解决方案
-
临时生效
curl -XPUT -H "Content-Type:application/json" http://127.0.0.1:9200/_cluster/settings -d '{ "transient": { "cluster": { "max_shards_per_node": 10000 } } }'
-
永久生效
curl -XPUT -H "Content-Type:application/json" http://127.0.0.1:9200/_cluster/settings -d '{ "persistent": { "cluster": { "max_shards_per_node": 10000 } } }'
-
配置文件永久生效。修改
elasticsearch.yml
cluster.max_shards_per_node: 10000
需要重启。
指定大小根据业务量自行调整。
三、参考资料
- 1、修复 Elasticsearch 集群的常见错误和问题
- 2、elasticsearch 7.4 出现circuit_breaking_exception异常
- 3、Elasticsearch集群降级为单节点
来都来了,点个赞再走呗!
关注WangScaler,祝你升职、加薪、不提桶!