4

Ich habe einen Tomcat - spring4.2 Anwendung, die mehrere Threads läuft. Jeder Thread wird aus nur einer Warteschlange entfernt, jedoch sind einer Warteschlange mehrere Threads zugewiesen.Thread in 'Parken zu warten' Zustand auf Redis aus der Warteschlange

Die Dinge beginnen gut, aber nach ein paar Stunden/~ 500k Dequeue-Operationen, finde ich Threads mit extrem langsamer Rate aus der Warteschlange.

In jvisualvm Ich sehe die Fäden in orange d.h. parken Die Thread-Dump ist wie folgt:

"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 

Die dequeue Methode ist:

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; 
     } 
    } 

Wird Eingänge schätzen. Die App funktioniert auch nach dem Neustart wieder gut. 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

Dachte, es war ein Verbindungsleck, aber versuchen mit Ressourcen sollte das nicht tun. –

+0

Nach der ganzen Forschung festgestellt, dass der Pool in einer weiteren Klasse injiziert wurde, lange schriftlich und vergessen und es hatte eine Verbindung Leck. dumm. –

Antwort

1

Es scheint Ihr jedis Pool ist aus Verbindungen läuft. Sie geben Ressourcen mit returnResourceObject oder returnResource zurück? (Ich weiß, beide sind veraltet, aber sie arbeiten immer noch mit der letzten Version von Jedis).

Denken Sie daran, dass ein Jedis-Pool nicht genau wie ein DBCP/Apache-Pool ist.

Ich hatte ein ähnliches Problem und es endete, als ich die Methoden oben anrief.

Auf der anderen Seite, da Redis ziemlich schnell ist, sollten Sie vielleicht Ihr Schema überdenken, und sehr wenige Threads blpop aufrufen (einen pro Warteschlange) und die Werte an die anderen Threads weiterleiten, damit diese nicht wissen über Redis, wenn sie nicht müssen.

+0

Auch ich dachte schon, aber wie kann ich das überprüfen? Ich mache nichts besonderes außer 'try (Jedis jedis = jedispool.getResource()) {' Muss ich diese Methoden explizit aufrufen? –

+0

Zumindest in meinem Fall musste ich, sonst würde es nicht funktionieren. –

+0

Denken Sie an Wechsel zu Salat. schließlich '{ \t \t \t if (jedis! = null) { \t \t \t \t jedispool.returnResourceObject (jedis); \t \t \t} \t \t} 'half nicht –

Verwandte Themen