RedisCache салата выбрасывает java.util.concurrent.RejectedExecutionException Превышено ограничение потока при замене заблокированного рабочего - PullRequest
0 голосов
/ 28 января 2019

Я использую Spring Boot с Redis-Cache с конфигурацией по умолчанию для Lettuce и получаю следующее исключение RejectedExecutionException после нескольких минут работы сервера:

org.springframework.data.redis.RedisSystemException: Unknown redis exception; nested exception is java.util.concurrent.RejectedExecutionException: Thread limit exceeded replacing blocked worker
        at org.springframework.data.redis.FallbackExceptionTranslationStrategy.getFallback(FallbackExceptionTranslationStrategy.java:53)
        at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:43)
        at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:257)
        at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.convertLettuceAccessException(LettuceStringCommands.java:718)
        at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.get(LettuceStringCommands.java:63)
        at org.springframework.data.redis.connection.DefaultedRedisConnection.get(DefaultedRedisConnection.java:210)
        at org.springframework.data.redis.cache.DefaultRedisCacheWriter.lambda$get$1(DefaultRedisCacheWriter.java:109)
        at org.springframework.data.redis.cache.DefaultRedisCacheWriter.execute(DefaultRedisCacheWriter.java:242)
        at org.springframework.data.redis.cache.DefaultRedisCacheWriter.get(DefaultRedisCacheWriter.java:109)
        at org.springframework.data.redis.cache.RedisCache.lookup(RedisCache.java:82)
        at org.springframework.cache.support.AbstractValueAdaptingCache.get(AbstractValueAdaptingCache.java:58)
        at org.springframework.cache.interceptor.AbstractCacheInvoker.doGet(AbstractCacheInvoker.java:73)
        at org.springframework.cache.interceptor.CacheAspectSupport.findInCaches(CacheAspectSupport.java:525)
        at org.springframework.cache.interceptor.CacheAspectSupport.findCachedItem(CacheAspectSupport.java:490)
        at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:372)
        at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:316)
        at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
        at my.controller.MyController.lambda$myFunc$0(MyController.java:60)
        at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.util.concurrent.RejectedExecutionException: Thread limit exceeded replacing blocked worker
        at java.util.concurrent.ForkJoinPool.tryCompensate(ForkJoinPool.java:2011)
        at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3310)
        at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1775)
        at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
        at io.lettuce.core.protocol.AsyncCommand.await(AsyncCommand.java:81)
        at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:112)
        at io.lettuce.core.FutureSyncInvocationHandler.handleInvocation(FutureSyncInvocationHandler.java:62)
        at io.lettuce.core.internal.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:80)
        at com.sun.proxy.$Proxy168.get(Unknown Source)
        at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.get(LettuceStringCommands.java:61)
        ... 21 common frames omitted

Похоже, что в Lettuce используются общиеForkJoinPool, который также использует DeferredResult, и все запросы и соединения душат пул (пожалуйста, исправьте меня, если я ошибаюсь).Какой рекомендуемый подход?Должен ли я переместить салат, чтобы использовать другой бассейн?Если так, то как?Пожалуйста, дайте мне знать, если есть какая-либо другая конфигурация или другая информация, которую я могу предоставить.

1 Ответ

0 голосов
/ 30 января 2019

Lettuce использует EventLoop от Netty в качестве своей многопоточной инфраструктуры.

Здесь происходит то, что ваша задача выполняется в пуле ForkJoin.Салат использует CompletableFuture s, чтобы вернуть дескриптор для асинхронной обработки результатов, и синхронные API-вызовы CompletableFuture.get(timeout, TimeUnit) ожидают завершения команды.Вызов метода блокировки в пуле ForkJoin включает ManagedBlocker, чтобы потенциально переключиться на другой поток, который может продолжить работу.

Если слишком много потоков ожидают завершения команды, вы в конечном итоге получите RejectedExecutionException.

Я предлагаю использовать другой пул выполнения для лямбда, который вы вызываете.

...