美文网首页DruidHiKariCPJava
druid的maxEvictableIdleTimeMillis

druid的maxEvictableIdleTimeMillis

作者: holysu | 来源:发表于2021-04-19 22:52 被阅读0次

    先看看 Druid 的 maxEvictableIdleTimeMillis 是啥?

    DestroyTask 线程销毁任务每隔 timeBetweenEvictionRunsMillis (默认一分钟)的时间会执行一次连接池瘦身检测 DruidDataSource#shrink(checkTime:true, keepAlive);

    if (idleMillis >= minEvictableIdleTimeMillis) {
        if (checkTime && i < checkCount) {  // checkCount = poolingCount - minIdle
            evictConnections[evictCount++] = connection;
            continue;
        } else if (idleMillis > maxEvictableIdleTimeMillis) {
            evictConnections[evictCount++] = connection;
            continue;
        }
    }
    

    checkTime = true 所以会再判断 i < checkCount 是否成立,而 checkCount = poolingCount - minIdle 也就是超过 minIdle 那部分连接(类似线程池的 maximumPoolSize - corePoolSize )

    所以,代码逻辑是 1~minIdle 的连接空闲超过 maxEvictableIdleTimeMillis(默认7小时) 则需要清除掉, minEvictableIdleTimeMillis(默认30分钟) 针对的是超过 minIdle 的那部分连接

    maxEvictableIdleTimeMillis 表示的是 minIdle 内连接能空闲的最大时长

    hikariCP 的 maxLifetime

    HikariPool#createPoolEntry 创建连接池条目

    final long maxLifetime = config.getMaxLifetime();
    if (maxLifetime > 0) {
       // variance up to 2.5% of the maxlifetime
       final long variance = maxLifetime > 10_000 ? ThreadLocalRandom.current().nextLong( maxLifetime / 40 ) : 0;
       final long lifetime = maxLifetime - variance;
       poolEntry.setFutureEol(houseKeepingExecutorService.schedule(
          () -> {
             if (softEvictConnection(poolEntry, "(connection has passed maxLifetime)", false /* not owner */)) {
                addBagItem(connectionBag.getWaitingThreadCount());
             }
          },
          lifetime, MILLISECONDS));
    }
    

    hikari在创建连接后,如果maxLifetime 大于0 ,则会起一个定时任务,在 maxLifetime(做了点时间随机) 之后会移除这个连接;不管这个连接是否最近还在用, 非常硬气;也就是说

    maxLifetime 表示的是连接在创建后最大能存活时间,与最近活跃/空闲与否无关

    但是在高并发服务里(ygc 频繁) maxLifetime 可能会导致被驱除的连接每隔7小时由于超龄进入到老年代, 如果连接池设置较大 可能会导致fullgc stw过久 (cms 的 final remak阶段 )

    为什么它们默认都是7小时?

    时下比较常用的 mysql 数据库默认的配置,如果物理连接空闲超过8小时会自动关闭

    所以为了保证 minIdle\minimumIdle 这些常驻在连接池的连接的活性,防止它们空闲过久,被数据库那边关了,特别是像晚上低峰期12点到早高峰8点刚好超过8小时后,刚进入业务高峰期拿到的连接都是不可用的, 定时检查,提前重建

    检查连接可用性的其他参数

    druid 检查连接活性的其他参数还有 testOnBorrow、testOnReturn、testWhileIdle

    • testOnBorrow 和 testOnReturn 分别是申请连接和归还连接的时候去 执行下 validationQuery 校验,对性能有影响 一般是关闭的
    • testWhileIdle 在申请连接的时候,如果连接空闲超过 timeBetweenEvictionRunsMillis 则 validationQuery 校验;对性能没什么影响

    hikariCP 没有暴露类似的参数,但是每次申请到连接的时候 都去检查连接是否超过500ms,如果是则检查连接的可用性

    testWhileIdle 这种机制不能取代 maxEvictableIdleTimeMillis 和 maxLifetime ,因为它是在申请连接的时候才做判断,比较被动;

    和dba确认,数据库服务配置的连接空闲超时时间

    相关文章

      网友评论

        本文标题:druid的maxEvictableIdleTimeMillis

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