生产环境was线程数300,jedis连接池连接数100.
在业务高峰期,查看日志发现大量could not get a resource from a pool的异常,抓取javacore文件发现was线程大量进入parked状态,查看jedis源码发现连接池底层使用common-pool实现,而common-pool其中有这样一段代码:
if (p == null) { if (borrowMaxWaitMillis < 0) { p = idleObjects.takeFirst(); } else { p = idleObjects.pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS); }}新来的线程会从jedis自己实现的LinkedBlockingQueue中拿链接,如果连接池没有空闲链接并且已键连接数已达上限,那么
public E pollFirst(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); lock.lockInterruptibly(); try { E x; while ( (x = unlinkFirst()) == null) { if (nanos <= 0) { return null; } nanos = notEmpty.awaitNanos(nanos); } return x; } finally { lock.unlock(); }}当前线程也就是was线程就会parked等待notEmpty信号,导致大量请求进不来堵死,首先我们考虑参数配置不合理,业务高峰期热点数据在redis中,大量的redis访问,我们改成300was链接,200redis链接,情况明显好转,但是在高峰期仍有部分请求时间超长,was线程parked的现象出现,更改jedis连接池参数,把maxWaitMillis参数调小,从最初的2000毫秒调到500,在业务高峰期,服务器资源紧张,新来的请求如果获取不到资源,立即报错返回,保证现有业务的正常运行算是一种权衡的办法。
时间: 2024-08-02 02:40:25