You are creating too many HashedWheelTimer instances.

米斯特程序猿 2021年07月23日 483次浏览

在Spring boot (2.3.11) 项目中批量初始化 redis 遇到如下警告信息,大致意思就是创建了过多的 HashedWheelTimer ,由于该类需要跨JVM共享,所以建议只创建一个实例,其实这个提示个人觉得有点矛盾,因为这里有一个最大实例64的判断,也就是说可以创建多个实例,所以这个提示更多的是提示资源浪费问题,超过之后就打印该信息,但是不影响实例创建,当然处于资源浪费考虑还是少创建比较好,目前对项目没有影响

io.netty.util.HashedWheelTimer | You are creating too many HashedWheelTimer instances. HashedWheelTimer is a shared resource that must be reused across the JVM,so that only a few instances are created.

查看io.netty.util.HashedWheelTimer 源码找到以下代码块

// 这里是创建上限值(警告阈值)
private static final int INSTANCE_COUNT_LIMIT = 64;

public HashedWheelTimer(
            ThreadFactory threadFactory,
            long tickDuration, TimeUnit unit, int ticksPerWheel, boolean leakDetection,
            long maxPendingTimeouts) {

        ObjectUtil.checkNotNull(threadFactory, "threadFactory");
        ObjectUtil.checkNotNull(unit, "unit");
        ObjectUtil.checkPositive(tickDuration, "tickDuration");
        ObjectUtil.checkPositive(ticksPerWheel, "ticksPerWheel");

        // Normalize ticksPerWheel to power of two and initialize the wheel.
        wheel = createWheel(ticksPerWheel);
        mask = wheel.length - 1;

        // Convert tickDuration to nanos.
        long duration = unit.toNanos(tickDuration);

        // Prevent overflow.
        if (duration >= Long.MAX_VALUE / wheel.length) {
            throw new IllegalArgumentException(String.format(
                    "tickDuration: %d (expected: 0 < tickDuration in nanos < %d",
                    tickDuration, Long.MAX_VALUE / wheel.length));
        }

        if (duration < MILLISECOND_NANOS) {
            logger.warn("Configured tickDuration {} smaller then {}, using 1ms.",
                        tickDuration, MILLISECOND_NANOS);
            this.tickDuration = MILLISECOND_NANOS;
        } else {
            this.tickDuration = duration;
        }

        workerThread = threadFactory.newThread(worker);

        leak = leakDetection || !workerThread.isDaemon() ? leakDetector.track(this) : null;

        this.maxPendingTimeouts = maxPendingTimeouts;
	//  这里判断创建了多少实例
        if (INSTANCE_COUNTER.incrementAndGet() > INSTANCE_COUNT_LIMIT &&
            WARNED_TOO_MANY_INSTANCES.compareAndSet(false, true)) {
            // 打印警告日志
            reportTooManyInstances();
        }
    }

// 这是打印警告日志的方法(实际打印的是error日志)
    private static void reportTooManyInstances() {
        if (logger.isErrorEnabled()) {
            String resourceType = simpleClassName(HashedWheelTimer.class);
            logger.error("You are creating too many " + resourceType + " instances. " +
                    resourceType + " is a shared resource that must be reused across the JVM," +
                    "so that only a few instances are created.");
        }
    }