我们正在使用 Redisson 连接到 AWS elasticache 上具有 1 个主节点和 2 个副本节点的复制 Redis。
该应用程序使用多个RLocalCachedMap
s、Lock
s 和几千个Topics
来跟踪用户状态。(随着用户在线和离线,主题和订阅来来去去)。
但是我们经常会收到一系列的RedisTimeoutException
s,最初这些是在服务器运行了几天之后,并且会持续出现,直到服务器重新启动,或者会因内存不足错误而崩溃。这使我认为这是缺少可用的订阅,但是如果我正确理解它们,我们的设置(如下)应该支持超过 100,000 个订阅,而我们还没有接近。
还有一些会在热身的时候出现,此时服务器的负载比较轻,有几次异常后连接整理出来,几天都没有大问题,说明不是单纯的订阅问题。这些命令每次都是简单的锁定/发布/订阅,而不是复杂的批处理。
AWS Elasticache 节点上的负载始终很小,我们的服务器部署在 AWS EC2 实例上,因此应该具有相对良好的连接性!
我们在数量上获得的 2 个例外是锁定或订阅主题:
Caused by: org.redisson.client.RedisTimeoutException: Subscribe timeout: (7500ms)
at org.redisson.command.CommandAsyncService.syncSubscription(CommandAsyncService.java:142) ~[redisson-3.8.2.jar!/:na]
at org.redisson.RedissonLock.lockInterruptibly(RedissonLock.java:149) ~[redisson-3.8.2.jar!/:na]
at org.redisson.RedissonLock.lockInterruptibly(RedissonLock.java:136) ~[redisson-3.8.2.jar!/:na]
at org.redisson.RedissonLock.lock(RedissonLock.java:118) ~[redisson-3.8.2.jar!/:na]
和
java.util.concurrent.CompletionException: org.redisson.client.RedisTimeoutException
at org.redisson.misc.RedissonPromise.await(RedissonPromise.java:197) ~[redisson-3.8.2.jar!/:na]
at org.redisson.misc.RedissonPromise.await(RedissonPromise.java:206) ~[redisson-3.8.2.jar!/:na]
at org.redisson.command.CommandAsyncService.syncSubscription(CommandAsyncService.java:141) ~[redisson-3.8.2.jar!/:na]
at org.redisson.RedissonTopic.addListener(RedissonTopic.java:133) ~[redisson-3.8.2.jar!/:na]
at org.redisson.RedissonTopic.addListener(RedissonTopic.java:109) ~[redisson-3.8.2.jar!/:na]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_111]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_111]
at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_111]
Caused by: org.redisson.client.RedisTimeoutException: null
at org.redisson.pubsub.PublishSubscribeService$4.run(PublishSubscribeService.java:220) ~[redisson-3.8.2.jar!/:na]
at io.netty.util.HashedWheelTimer$HashedWheelTimeout.expire(HashedWheelTimer.java:670) ~[netty-common-4.1.30.Final.jar!/:4.1.30.Final]
at io.netty.util.HashedWheelTimer$HashedWheelBucket.expireTimeouts(HashedWheelTimer.java:745) ~[netty-common-4.1.30.Final.jar!/:4.1.30.Final]
at io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:473) ~[netty-common-4.1.30.Final.jar!/:4.1.30.Final]
我们的配置是:
"subscriptionConnectionMinimumIdleSize":32,
"subscriptionConnectionPoolSize":128,
"slaveConnectionMinimumIdleSize":32,
"slaveConnectionPoolSize":128,
"masterConnectionMinimumIdleSize":64,
"masterConnectionPoolSize":128,
"subscriptionsPerConnection": 1000,
"timeout": 3000,
"retryAttempts": 3,
"retryInterval": 1500,
"readMode": "SLAVE",
"subscriptionMode": MASTER
我已经阅读了关于超时的 Redisson 常见问题解答,我们的超时异常显然不是服务器或客户端,因此不确定哪个超时参数会更好地调整,进一步考虑到它们是 7.5 秒,对于用户请求来说等待的时间相当长。同样,我找不到有关连接池大小或每个连接订阅的推荐值以及生产部署的合理值的文档。