diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/netty/SeparatePoolInetNameResolver.java b/proxy/src/main/java/com/velocitypowered/proxy/network/netty/SeparatePoolInetNameResolver.java index 5fc309ae9a..fe5e8b29dd 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/netty/SeparatePoolInetNameResolver.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/netty/SeparatePoolInetNameResolver.java @@ -32,17 +32,20 @@ import java.net.InetSocketAddress; import java.util.List; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * An implementation of {@code InetNameResolver} that performs blocking DNS name lookups - * in a separate thread, avoiding blocking the Netty threads for an extended period of time - * and without the downsides of Netty's native DNS resolver. + * on a small bounded pool of separate threads, avoiding blocking the Netty threads for an + * extended period of time and without the downsides of Netty's native DNS resolver. */ public final class SeparatePoolInetNameResolver extends InetNameResolver { + private static final int MAX_RESOLVE_THREADS = 8; + private final ExecutorService resolveExecutor; private final InetNameResolver delegate; private final Cache> cache; @@ -56,11 +59,15 @@ public final class SeparatePoolInetNameResolver extends InetNameResolver { */ public SeparatePoolInetNameResolver(EventExecutor executor) { super(executor); - this.resolveExecutor = Executors.newSingleThreadExecutor( + ThreadPoolExecutor resolveExecutor = new ThreadPoolExecutor( + MAX_RESOLVE_THREADS, MAX_RESOLVE_THREADS, + 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new ThreadFactoryBuilder() - .setNameFormat("Velocity DNS Resolver") + .setNameFormat("Velocity DNS Resolver #%d") .setDaemon(true) .build()); + resolveExecutor.allowCoreThreadTimeOut(true); + this.resolveExecutor = resolveExecutor; this.delegate = new DefaultNameResolver(executor); this.cache = Caffeine.newBuilder() .expireAfterWrite(30, TimeUnit.SECONDS)