2014-02-27 54 views
0

嗨,我想要設置使用java的redis服務器。 我的Redis服務器是帶有ulimit無限制的linux服務器。無法從池中獲取資源JedisConnectionException

這裏是我的Spring bean它創建連接

公共類JedisService實現IJedisService,的InitializingBean,DisposableBean的{ 私人JedisPool jedisPool;

public JedisService() { 

} 

public JedisPool getJedisPool() { 
    return jedisPool; 
} 

@Override 
public void destroy() throws Exception { 
    if(jedisPool != null){ 
     jedisPool.destroy(); 
    } 

} 

@Override 
public void afterPropertiesSet() throws Exception { 
    JedisPoolConfig poolConfig = new JedisPoolConfig(); 
    poolConfig.setMaxActive(1000); 
    poolConfig.setMaxIdle(10); 
    poolConfig.setMinIdle(1); 
    poolConfig.setMaxWait(30000); 
    poolConfig.setNumTestsPerEvictionRun(10); 
    poolConfig.setTestOnBorrow(true); 
    poolConfig.setTestOnReturn(true); 
    poolConfig.setTestWhileIdle(true); 
    poolConfig.setTimeBetweenEvictionRunsMillis(30000); 

    jedisPool = new JedisPool(poolConfig,Config.REDIS_HOST, 
      RestrictionUtils.REDIS_PORT,RestrictionUtils.REDIS_CONNECTION_TIMEOUT); 

} 

public boolean validateHitsCount(String hostKey,String urlKey,int hostHitsCount, int urlHitsCount, long timeKey,Map<String, Object> overLimit){ 
    int retryCount = 0; 
    return recursiveRedisConnection(retryCount,hostKey,urlKey,hostHitsCount,urlHitsCount,timeKey,overLimit); 
} 

private boolean recursiveRedisConnection(int retryCount,String hostKey,String urlKey,int hostHitsCount, int urlHitsCount, long timeKey,Map<String, Object> overLimit){ 
    Jedis jedis = null; 
    boolean returnObj = true; 
    try { 
     //Connection 
     jedis = getJedisPool().getResource(); 
     jedis.connect(); 

     //Delete previous keys 
     try { 
      deletePreviouskeys(jedis, urlKey, hostKey, timeKey); 
     } catch (Exception e) { 
     } 

     //Validation 
     String value = jedis.get(hostKey+timeKey); 
     if(value != null){ 
      try { 
       int count = Integer.parseInt(value); 
       System.out.println("HostCount: "+hostKey+ " "+count); 
       if(count < hostHitsCount){ 
        jedis.incr(hostKey+timeKey); 
        returnObj = validateURLHits(jedis, urlKey, urlHitsCount, timeKey, overLimit); 
       }else{ 
        returnObj = false; 
        overLimit.put("Data", "You have reached maximum limit for hits---"+hostKey); 
       } 
      } catch (Exception e) { 
      } 

     }else{ 
      value = 1+""; 
      jedis.set(hostKey+timeKey, value); 
      jedis.expire(hostKey+timeKey, 60); 
      returnObj = validateURLHits(jedis, urlKey, urlHitsCount, timeKey, overLimit); 
     } 

    } catch (Exception e) { 
     retryCount ++; 
     if(retryCount < 3){ 
      recursiveRedisConnection(retryCount,hostKey,urlKey,hostHitsCount,urlHitsCount,timeKey,overLimit); 
     }else{ 
      e.printStackTrace(); 
      returnObj = false; 
     } 
    }finally{ 
     if(jedis != null && jedis.isConnected()){ 
      getJedisPool().returnResource(jedis); 
     } 
    } 
    return returnObj; 
} 

private boolean validateURLHits(Jedis jedis,String urlKey, int urlHitsCount, long timeKey,Map<String, Object> overLimit){ 
    boolean returnObj = true; 
    String value = jedis.get(urlKey+timeKey); 
    if(value != null){ 
     try { 
      int count = Integer.parseInt(value); 
      System.out.println("URLCount: "+urlKey+ " "+count); 
      if(count < urlHitsCount){ 
       jedis.incr(urlKey+timeKey); 
      }else{ 
       returnObj = false; 
       overLimit.put("Data", "Reached maximum limit of hits for this URL"); 
      } 
     }catch(Exception e){ 
     } 
    }else{ 
     jedis.set(urlKey+timeKey, 1+""); 
     jedis.expire(urlKey+timeKey, 60); 
    } 
    return returnObj; 
} 

private void deletePreviouskeys(Jedis jedis,String urlKey, String hostKey, long timeKey){ 
    /*Set<String> keys = jedis.keys("*"); 
    for(String key : keys){ 
     if(!key.equalsIgnoreCase(urlKey+timeKey)){ 
      if(!key.equalsIgnoreCase(hostKey+timeKey)){ 
       jedis.del(key); 
      } 
     } 

    }*/ 
} 

}

方法validateURLHits被稱爲在控制器。 但是當我運行在多線程的代碼我得到這個錯誤

redis.clients.jedis.exceptions.JedisConnectionException:從池中 在redis.clients.util.Pool.getResource無法獲得的資源(池。 java:22) at com.til.ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:60) at com.til.ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:95) at com.til。 ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:95) at com.til.ibeat.service.JedisService.validateHitsCount(JedisService.java:52) at com.til.ibeat.controller.MashupController.handleRequest(MashupController。 java:66) at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:763) at org.springframework.web。 servlet.DispatcherServlet.doService(DispatcherServlet.java:709) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:613) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java: 525) at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain。 internalDoFilter(ApplicationFilterChain.java:305) at org.apache。 catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) 在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve。 (org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache。 catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) 在org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936) 在org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve。 java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.j ava:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) at org.apache.coyote.AbstractProtocol $ AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache。 tomcat.util.net.JIoEndpoint $ SocketProcessor.run(JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor $ Worker.runTask(Unknown Source) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(Unknown源) 在java.lang.Thread.run(未知源) 引起:java.util。NoSuchElementException:無法創建經過驗證的對象,原因:ValidateObject失敗

回答

1

您是否檢查過您的JedisPool是僅實例化一次而不是更多?

由於您的Spring bean通過多線程訪問,並且Jedis不是線程安全的,因此您可以有多個JedisPool返回奇怪的Jedis實例或不同線程同時使用的jedis實例。每個線程都可以擁有JedisPool和/或Jedis實例的本地副本,然後從中獲取錯誤。你有兩種選擇:你可以聲明JedisPool爲靜態final(每個類加載器只有一個值),或者使用雙重檢查加鎖(使用volatile)來確保只有一個JedisPool在沒有本地拷貝的情況下被所有線程訪問,根據線程使用的每個Jed都不會被另一個線程訪問。