美文网首页
redis 连接池 引起的线上服务 假死

redis 连接池 引起的线上服务 假死

作者: NazgulSun | 来源:发表于2019-03-25 17:11 被阅读0次

    今天遇到 rancher上的服务无法相应。

    1、使用 jstack -l pid 查看当前线程的状态

    发现大量线程处于Waiting 状态。

    "DubboServerHandler-192.168.213.250:20889-thread-198" daemon prio=10 tid=0x00007f3a3b794800 nid=0x83b waiting on condition [0x00007f3a1ed86000]

      java.lang.Thread.State: WAITING (parking)

        at sun.misc.Unsafe.park(Native Method)

        - parking to wait for  <0x0000000700c6c208> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)

        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)

        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)

        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)

    从log 可以看出是由于 线程无法获取redis连接。

    这样的线程大概有几百个。由于我们的Http请求,一开始时候是先从缓存取数据,如果没有才去数据库取,

    所以所有的请求基本上都被waiting到获取redis连接上,而无法相应服务。

    通过代码排查,发现是在建立 redis pool 的时候,使用的都是默认配置,

    在默认配置中,最大的连接数为8个,并且获取连接时会持续等待,造成了程序在某个时候无法获取redis连接,后面的线程持续等待。

    于是加上 pool的配置

    JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();

    jedisPoolConfig.setMaxIdle(maxIdle);

    jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);

    jedisPoolConfig.setMaxTotal(maxTotal);

    配置后,设置了超时时间,不至于所有线程都等待,而耗光app的资源。

    现在还有一个问题, 就是正常情况下, 获取redis 连接用完就应该会释放资源,到底是什么原因导致最开始的

    8个连接打满,等待,后续有没有线程唤醒他们?

    查看springboot 的redisTemplate 发现每个方法都是用完之后释放的连接。

    现在想到的:可能是某个时刻,redis 无法获取连接,导致所有的线程都是处于连接等待状态,那么就没有线程去唤醒等待的线程了。

    相关文章

      网友评论

          本文标题:redis 连接池 引起的线上服务 假死

          本文链接:https://www.haomeiwen.com/subject/udybvqtx.html