当前位置: 首页 > 知识库问答 >
问题:

Spring和Redis的"无法将资源返回到池"错误

井轶
2023-03-14

我试图用基于XML的配置用Spring实现Redis。我的配置文件如下所示:

<!-- declare Redis Cache Manager -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
      c:template-ref="redisTemplate" />

<bean id="jedisConnectionFactory"
      class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
      p:host-name="172.17.0.2" p:use-pool="true" />

<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
      p:connection-factory-ref="jedisConnectionFactory" />

我的缓存定义如下:

@Cacheable(value = "my-cache-key", key = "{#argSomeObj, #argSomeString, #argSomeInt}")
public MyAwesomeDTO getSomeResult(SomeObject argSomeObj, String argSomeString, int argSomeInt, Request argRequest)
{
    // this part calculates and returns some values regarding to given parameters
    return awesomeDTO;
}

当我第一次点击这个函数时,我得到了如下所述的错误。当我第二次尝试时,它工作正常并存储在Redis中。

redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
    at redis.clients.util.Pool.returnBrokenResourceObject(Pool.java:103)
    at redis.clients.jedis.JedisPool.returnBrokenResource(JedisPool.java:239)
    at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:255)
    at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:16)
    at org.springframework.data.redis.connection.jedis.JedisConnection.close(JedisConnection.java:257)
    at org.springframework.data.redis.core.RedisConnectionUtils.releaseConnection(RedisConnectionUtils.java:206)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:205)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:153)
    at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:140)
    at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:125)
    at org.springframework.cache.interceptor.AbstractCacheInvoker.doPut(AbstractCacheInvoker.java:82)
    at org.springframework.cache.interceptor.CacheAspectSupport$CachePutRequest.apply(CacheAspectSupport.java:651)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:358)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:299)
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)

有人知道我该如何修复这个错误吗?

以下是完整的堆栈跟踪:

01-30 12:34:35 [Thread@12:34:35.259:https://www.vtokmak.office.com:8443/some-url] ERROR com.tokmak.frontend.MyApplication - A 500 error (redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool) occured on URL [https://www.vtokmak.office.com:8443/some-url], userAgent [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36]
redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool
    at redis.clients.util.Pool.returnBrokenResourceObject(Pool.java:103)
    at redis.clients.jedis.JedisPool.returnBrokenResource(JedisPool.java:239)
    at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:255)
    at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:16)
    at org.springframework.data.redis.connection.jedis.JedisConnection.close(JedisConnection.java:257)
    at org.springframework.data.redis.core.RedisConnectionUtils.releaseConnection(RedisConnectionUtils.java:206)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:205)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:153)
    at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:140)
    at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:125)
    at org.springframework.cache.interceptor.AbstractCacheInvoker.doPut(AbstractCacheInvoker.java:82)
    at org.springframework.cache.interceptor.CacheAspectSupport$CachePutRequest.apply(CacheAspectSupport.java:651)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:358)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:299)
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
    at com.tokmak.frontend2.service.misc.world.WorldService$$EnhancerBySpringCGLIB$$8a70244e.getWorld(<generated>)
    at com.tokmak.frontend2.controller.world.AbstractWorldController.handle(AbstractWorldController.java:69)
    at com.tokmak.frontend.Router.getView(Router.java:1069)
    at com.tokmak.frontend.Router.routeRequest(Router.java:320)
    at com.tokmak.webframework.RouterServlet.doRequestProcessingUnchecked(RouterServlet.java:145)
    at com.tokmak.webframework.RouterServlet.doRequestProcessing(RouterServlet.java:93)
    at com.tokmak.webframework.RouterServlet.doGet(RouterServlet.java:68)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Invalidated object not currently part of this pool
    at org.apache.commons.pool2.impl.GenericObjectPool.invalidateObject(GenericObjectPool.java:640)
    at redis.clients.util.Pool.returnBrokenResourceObject(Pool.java:101)
    ... 44 more

// 01-30 12:34:35 [Thread@12:34:35.259:https://www.vtokmak.office.com:8443/some-url] WARN  com.tokmak.webframework.RouterServlet - Exception [/some-url], message: "Could not return the resource to the pool"]
01-30 12:34:35 [Thread@12:34:35.259:https://www.vtokmak.office.com:8443/some-url] WARN  com.tokmak.frontend.Router - I have to make use of static fail over [http://192.168.3.14/]...
01-30 12:34:35 [Thread@12:34:35.259:https://www.vtokmak.office.com:8443/some-url] WARN  com.tokmak.frontend.Router - ... but since there is a static fail-over URL present in config, I try to load the data from [http://192.168.3.14/www.vtokmak.office.com:8443/some-url]
01-30 12:34:35 [Thread@12:34:35.259:https://www.vtokmak.office.com:8443/some-url] WARN  com.tokmak.frontend.Router - fuck, even though I have a static fail-over URL, I failed!
Jan 30, 2018 12:34:36 PM org.apache.jasper.compiler.TldLocationsCache tldScanJar
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

共有3个答案

曹兴贤
2023-03-14

这是基于java的配置。尝试并分享结果。

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import redis.clients.jedis.JedisPoolConfig;

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {



    @Override
    @Bean
    public CacheManager cacheManager() {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate());
        cacheManager.setUsePrefix(true);
        //cacheManager.setCacheNames(getCacheNames());
        return cacheManager;
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate() {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        redisTemplate.setExposeConnection(true);
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
                Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        om.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        om.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
        om.setSerializationInclusion(Include.NON_NULL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setEnableDefaultSerializer(true);
        return redisTemplate;
    }

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setTestOnBorrow(false);
        config.setTestOnCreate(false);
        config.setTestOnReturn(false);
        config.setTestWhileIdle(false);
        config.setMaxTotal(1000);
        config.setMaxIdle(1000);
        config.setMinIdle(0);
        config.setMaxWaitMillis(10000);
        JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
        connectionFactory.setHostName("172.17.0.2");
        //connectionFactory.setPort(6379);
        connectionFactory.setUsePool(true);
        connectionFactory.setPoolConfig(config);
        return connectionFactory;
    }

    @Override
    @Bean
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

}
邹星火
2023-03-14

正如@mp911de在这里提到的,这个问题与Spring Data Redis版本有关。当我升级时,问题解决了。

姬烨磊
2023-03-14

虽然我看不到你的代码,但我看到过当你两次试图关闭绝地实例时会发生这种情况,而没有注意到。例如:绝地实现了可关闭,当使用资源进行尝试时,它将自动关闭。

try(Jedis jedis = getJedis()){

}catch{...}

所以如果你也叫绝地武士。close()它将抛出该错误。

任何一个

try{
    Jedis jedis = getJedis();
}catch(){
}finally{
    jedis.close()
}

或者查看是否多次调用close()

 类似资料: