美文网首页
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