【问题标题】:Thread in 'parking to wait' state on Redis dequeueRedis dequeue 上处于“停车等待”状态的线程
【发布时间】:2016-05-18 12:18:06
【问题描述】:

我有一个运行多个线程的 tomcat - spring4.2 应用程序。每个线程仅从一个队列中出列,但是分配给一个队列的线程不止一个。

开始一切正常,但经过几个小时/约 500k 出队操作后,我发现线程出队的速度极慢。

在 jvisualvm 中,我看到橙色的线程,即 park 线程转储如下:

"EMLT_2" - Thread t@64
   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 t@63
   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; 
        }
    }

将不胜感激投入。该应用程序在重新启动后再次运行良好一段时间。 池配置:

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

【问题讨论】:

  • 以为是连接泄漏,但尝试使用资源不应该这样做。
  • 在所有的研究中发现池被注入了一个更多的类,写得很长,被遗忘了,它有一个连接泄漏。傻。

标签: concurrency locking java.util.concurrent jedis apache-commons-pool


【解决方案1】:

您的绝地武士池似乎连接不足。 您是使用 returnResourceObject 还是 returnResource 返回资源? (我知道两者都已弃用,但它们仍然适用于最新版本的 jedis)。

请记住,jedis 池与 DBCP/Apache 池并不完全相同。

我有一个类似的问题,当我调用上面的方法时它就结束了。

另一方面,由于 Redis 非常快,也许您应该重新考虑您的架构,并且很少有线程调用 blpop(每个队列一个)并将值转发给其他线程,所以那些不知道redis 如果他们不需要的话。

【讨论】:

  • 即使我也这么认为,但我该如何验证呢?除了try (Jedis jedis = jedispool.getResource()) {,我没有做任何特别的事情,我需要显式调用这些方法吗?
  • 至少在我的情况下我必须这样做,否则它将无法工作。
  • 考虑改吃生菜。 finally { if (jedis != null) { jedispool.returnResourceObject(jedis); } } 没有帮助
  • 你可以尝试一些额外的想法,直接调用 jedis.close()。并将此设置添加到您的池配置 maxWaitMillis: 100。最后一个应该可以缓解问题,但它仍然存在。因此,也许您对池大小有很多请求,而您却被淹没了。
猜你喜欢
  • 2018-01-17
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 2018-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
相关资源
最近更新 更多