ElasticSearch批量写入时遇到EsRejectedExecutionException
阿里云ARMS控制台发现线上搜索服务的批量写入方法报大量异常:
[DUBBO] Got unchecked and undeclared exception which called by 192.168.x.x. service: xxx.IProductSearchService, method: saveProductEntitys,
exception: org.springframework.data.elasticsearch.ElasticsearchException: Bulk indexing has failures. Use ElasticsearchException.getFailedDocuments() for detailed messages
[{346833406144942081PY331010069=RemoteTransportException[[node-100][192.168.x.x:9300][indices:data/write/bulk[s]]]; nested: EsRejectedExecutionException[rejected
execution of org.elasticsearch.action.support.replication.TransportReplicationAction$PrimaryPhase$1@c1f6e62 on EsThreadPoolExecutor[bulk, queue capacity = 200,
org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@66f7b4ec[Running, pool size = 16, active threads = 16, queued tasks = 200, completed tasks = 332599]]];}], dubbo
version: search, current host: 192.168.x.x
推测跟上线前商品服务的改动有关,将更新商品增量索引的方法为了异步无返回的方式,该方法构建好数据后调搜索服务批量写入ES的接口。
<dubbo:reference id="productIdxService" interface="com.xxx.ProductIdxService" lazy="true" timeout="10000">
<!-- 异步调用无返回 -->
<dubbo:method name="buildIncrementalProductIndex" async="true" return="false" />
</dubbo:reference>
由于是异步调用,调用方很快返回,可能导致提供方并发数增加,最终批量写入ES接口的并发增加。
日志里的EsRejectedExecutionException
也提示了ES的线程池EsThreadPoolExecutor bulk queue capacity = 200,pool size = 16, active threads = 16, queued tasks = 200
,
跟JUC的固定线程池类似,任务数超过了队列大小,ES拒绝执行。
线上使用的ES版本很老,是2.2版本。
通过ES提供的HTTP接口:
-
查看线程池配置
GET /ES地址/_cat/thread_pool?v
// 注:?v表示显示表头(header),也可指定具体显示哪里列
// 例:/_cat/thread_pool?v&h=host,bulk.active,bulk.rejected,bulk.queue,bulk.queueSize,bulk.size,bulk.min,bulk.max,search.active,search.rejected,search.queue,search.queueSize -
查看各节点线程池配置
GET /ES地址/_nodes/thread_pool/ -
查看集群配置
GET /ES地址/_cat/_cluster/settings -
修改集群配置
PUT /ES地址/_cat/_cluster/settings
{
"transient": {
"threadpool.bulk.type": "fixed",
"threadpool.bulk.queue_size": 1000,
"threadpool.bulk.size": 16,
"threadpool.bulk.min": 16,
"threadpool.bulk.max": 16
}
}
// 将bulk的队列大小修改为1000,注意size、min、max也可修改,但实测发现查看集群配置参数确实改了,而查看线程池3个参数仍然没变,只是队列大小已修改。
由于是线上ES,且考虑到线程数16是ES的保护机制以及机器配置和负载情况,只修改了队列大小。
队列大小调整到1000后,发现报EsRejectedExecutionException
的数量少了很多,在并发量很大的时候还是会报该异常,
异常提示里的queue capacity已是1000了,说明参数生效。
该方案为临时处理方案,少量的写入异常从业务上看能接受,对业务影响不大基本上很难发现,且目前老版本ES的负载较高。
未来着手对ES版本进行升级,使用阿里云ES7.4的版本,并且升级老的搜索服务,应用新版本的spring-data-elasticseach
或者使用rest-high-level-client
。
参考:
es 查看线程池 https://blog.csdn.net/yun0000000/article/details/106327838/
es写入报错,EsRejectedExecutionException https://elasticsearch.cn/question/4647
使用 /_cat/thread_pool 查询线程池运行情况 https://www.letianbiji.com/elasticsearch/es7-cat-thread-pool.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2018-09-13 [学习]sentinel中的DatatSource(二) WritableDataSource
2018-09-13 dubbo服务provider方打印警告日志,getDeserializer - Hessian/Burla 'xxx' is an unknown class