Akka并发请求下出现Async write timed out错误的原因与解决
Akka Cluster Sharding 错误:"Remember entity store did not respond" 分析与解决
先贴出错误日志:
[ERROR] [09/14/2021 15:53:30.457] [test-akka.actor.default-dispatcher-22] [akka.cluster.sharding.Shard] - testserver: Remember entity store did not respond, restarting shard [ERROR] [09/14/2021 15:53:30.457] [test-akka.actor.default-dispatcher-22] [akka.cluster.sharding.Shard] - testserver: Remember entity store did not respond, restarting shard [ERROR] [09/14/2021 15:53:30.461] [test-akka.actor.default-dispatcher-22] [akka.actor.OneForOneStrategy] - Async write timed out after 5.000 s java.lang.RuntimeException: Async write timed out after 5.000 s at akka.cluster.sharding.Shard$$anonfun$waitingForRememberEntitiesStore$1.applyOrElse(Shard.scala:684) at akka.actor.Actor.aroundReceive(Actor.scala:537) at akka.actor.Actor.aroundReceive$(Actor.scala:535) at akka.cluster.sharding.Shard.akka$actor$Timers$$super$aroundReceive(Shard.scala:409) at akka.actor.Timers.aroundReceive(Timers.scala:52) at akka.actor.Timers.aroundReceive$(Timers.scala:41) at akka.cluster.sharding.Shard.aroundReceive(Shard.scala:409) at akka.actor.ActorCell.receiveMessage(ActorCell.scala:579) at akka.actor.ActorCell.invoke(ActorCell.scala:547) at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:270) at akka.dispatch.Mailbox.run(Mailbox.scala:231) at akka.dispatch.Mailbox.exec(Mailbox.scala:243) at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source) at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source) at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
出现场景
- 启用了Akka Cluster Sharding的Remember Entities功能:该功能用于shard重启、节点故障后自动恢复实体状态与位置,依赖底层存储(默认是Akka Persistence Journal)持久化实体信息。
- 存储层无法在默认5秒超时内响应shard的读写请求:常见于高并发场景下,存储介质(如数据库)IO过载、连接池耗尽,或网络延迟过高导致通信受阻。
- 自定义Remember Entities存储存在性能瓶颈:若替换了默认存储,自定义逻辑的阻塞、低效会直接引发超时。
- 集群网络分区:shard节点与存储所在节点间出现网络中断,导致请求无法送达或响应无法返回。
修复方案
1. 调整存储超时阈值
默认5秒超时可能无法应对高负载或慢存储场景,修改Akka配置增大超时时间:
akka.cluster.sharding { remember-entities-store { timeout = 10s # 根据实际情况调整,比如10s到30s } }
2. 优化存储层性能
- 若使用Akka Persistence Journal:
- 检查数据库连接池配置,增大连接数(如
akka.persistence.jdbc.journal.connection-pool.max-size),调整连接超时参数。 - 为Journal相关数据库表添加合适索引,优化读写查询速度。
- 考虑迁移到高并发友好的存储,比如将关系型数据库替换为Cassandra、Redis。
- 检查数据库连接池配置,增大连接数(如
- 清理存储中的过期数据:避免Journal积累过多历史数据拖慢读写速度。
3. 调整Sharding并发控制
- 限制shard的并发操作数,避免短时间内向存储发送大量请求,可通过调整
akka.cluster.sharding.shard-dispatcher线程池参数实现:
akka.cluster.sharding.shard-dispatcher { type = Dispatcher executor = "fork-join-executor" fork-join-executor { parallelism-min = 8 parallelism-factor = 3.0 parallelism-max = 32 } throughput = 100 }
- 合理设置shard数量,避免单个shard承载过多实体,分散存储请求压力。
4. 排查网络与集群状态
- 检查集群节点间的网络延迟,排查是否存在网络分区、丢包等问题。
- 监控节点CPU、内存、磁盘IO使用率,确保没有节点过载导致处理缓慢。
5. 优化自定义存储实现(若有)
- 确保自定义的Remember Entities存储逻辑为异步非阻塞,避免在存储操作中执行耗时同步任务。
- 添加本地缓存,减少对底层存储的重复读写请求,降低存储压力。
内容的提问来源于stack exchange,提问作者lazyakshay
相关产品推荐
相关产品推荐

