4

我有一個運行多線程的tomcat - spring4.2應用程序。每個線程僅從一個隊列中出隊,但是有多個線程分配給一個隊列。Redis隊列中的'停車等待'狀態線程

事情開始很好,但經過幾個小時/〜500k的出列操作,我發現線程以極低的速度出隊。

在jvisualvm我看到橙色即螺紋停放 的線程轉儲如下:

"EMLT_2" - Thread [email protected] 
    java.lang.Thread.State: WAITING 
    at sun.misc.Unsafe.park(Native Method) 
    - parking to wait for <2cf42d7> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) 
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) 
    at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:583) 
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:442) 
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363) 
    at redis.clients.util.Pool.getResource(Pool.java:48) 
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:86) 
    at com.mycomp.sam.processors.SimpleDequeuer.dequeue(SimpleDequeuer.java:25) 
    at com.mycomp.sam.processors.EMLT.run(EMLT.java:29) 
    at java.lang.Thread.run(Thread.java:745) 

    Locked ownable synchronizers: 
    - None 

"EMLT_1" - Thread [email protected] 
    java.lang.Thread.State: WAITING 
    at sun.misc.Unsafe.park(Native Method) 
    - parking to wait for <2cf42d7> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) 
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) 
    at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:583) 
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:442) 
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363) 
    at redis.clients.util.Pool.getResource(Pool.java:48) 
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:86) 
    at com.mycomp.sam.processors.SimpleDequeuer.dequeue(SimpleDequeuer.java:25) 
    at com.mycomp.sam.processors.EMLT.run(EMLT.java:29) 
    at java.lang.Thread.run(Thread.java:745) 

    Locked ownable synchronizers: 
    - None 

出隊方法是:

public String dequeue(String queue) { 
     try (Jedis jedis = jedispool.getResource()) { 
      List<String> str = jedis.blpop(10, queue); 
      if(str!=null){ 
       return str.get(1); 
      } 
      else 
       return null; 
     } 
    } 

將理解輸入。該應用程序在重新啓動後再次運行良好。 Pool conf:

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> 
    <property name="maxIdle" value="10" /> 
    <property name="maxTotal" value="70" /> 
    <property name="minIdle" value="10" /> 
</bean> 
<bean id="jedispool" class="redis.clients.jedis.JedisPool"> 
    <constructor-arg name="poolConfig" ref="poolConfig" /> 
    <constructor-arg name="host" value="${REDIS_HOST}" /> 
    <constructor-arg name="port" value="6379" /> 
</bean> 
+0

認爲這是一個連接泄漏,但嘗試資源不應該這樣做。 –

+0

經過所有的研究發現,游泳池被注入一個班級,長時間書寫和遺忘,並有連接泄漏。愚蠢。 –

回答

1

看起來您的jedis池已經沒有連接了。 您是否正在使用returnResourceObject或returnResource返回資源? (我知道兩者都被棄用,但他們仍然使用jedis的版本)。

請記住,jedis池並不完全像DBCP/Apache Pool。

我有一個類似的問題,它結束了,當我調用上述方法。另一方面,由於Redis速度非常快,也許你應該重新思考你的模式,並且很少有線程調用blpop(每個隊列一個)並將值轉發給其他線程,所以那些不知道關於redis如果他們不需要。

+0

即使我這麼認爲,但我該如何驗證?我沒有做任何特別的事情,除了嘗試(Jedis jedis = jedispool.getResource()){'我需要明確調用這些方法嗎? –

+0

至少在我的情況下,我不得不,但它不會工作。 –

+0

想轉向生菜。 '最後{ \t \t \t如果(jedis!= NULL){ \t \t \t \t jedispool.returnResourceObject(jedis); \t \t \t} \t \t}'沒有幫助 –