From 2d83ebdf64bde8793b8c3b24be81ad23e72119d5 Mon Sep 17 00:00:00 2001 From: Nikita Koksharov Date: Tue, 11 Oct 2022 08:56:00 +0300 Subject: [PATCH] Fixed - SearchDomainUnknownHostExceptionis thrown occasionally. #4576 --- .../main/java/org/redisson/config/Config.java | 2 +- .../SequentialDnsAddressResolverFactory.java | 102 ++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 redisson/src/main/java/org/redisson/connection/SequentialDnsAddressResolverFactory.java diff --git a/redisson/src/main/java/org/redisson/config/Config.java b/redisson/src/main/java/org/redisson/config/Config.java index f1be696ae..baa77b00d 100644 --- a/redisson/src/main/java/org/redisson/config/Config.java +++ b/redisson/src/main/java/org/redisson/config/Config.java @@ -90,7 +90,7 @@ public class Config { private boolean useThreadClassLoader = true; - private AddressResolverGroupFactory addressResolverGroupFactory = new DnsAddressResolverGroupFactory(); + private AddressResolverGroupFactory addressResolverGroupFactory = new SequentialDnsAddressResolverFactory(); public Config() { } diff --git a/redisson/src/main/java/org/redisson/connection/SequentialDnsAddressResolverFactory.java b/redisson/src/main/java/org/redisson/connection/SequentialDnsAddressResolverFactory.java new file mode 100644 index 000000000..1ab4a9b7e --- /dev/null +++ b/redisson/src/main/java/org/redisson/connection/SequentialDnsAddressResolverFactory.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2013-2021 Nikita Koksharov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.redisson.connection; + +import io.netty.channel.EventLoop; +import io.netty.channel.socket.DatagramChannel; +import io.netty.resolver.AddressResolver; +import io.netty.resolver.AddressResolverGroup; +import io.netty.resolver.InetSocketAddressResolver; +import io.netty.resolver.NameResolver; +import io.netty.resolver.dns.DnsAddressResolverGroup; +import io.netty.resolver.dns.DnsServerAddressStreamProvider; +import io.netty.util.concurrent.EventExecutor; +import io.netty.util.concurrent.Promise; +import org.redisson.pubsub.AsyncSemaphore; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.List; +import java.util.concurrent.Callable; + +/** + * Address resolver which allows to control concurrency level of requests to DNS servers. + * + * @author Nikita Koksharov + * + */ +public class SequentialDnsAddressResolverFactory implements AddressResolverGroupFactory { + + static class LimitedInetSocketAddressResolver extends InetSocketAddressResolver { + + final AsyncSemaphore semaphore; + + LimitedInetSocketAddressResolver(AsyncSemaphore semaphore, EventExecutor executor, NameResolver nameResolver) { + super(executor, nameResolver); + this.semaphore = semaphore; + } + + @Override + protected void doResolve(InetSocketAddress unresolvedAddress, Promise promise) throws Exception { + execute(() -> { + super.doResolve(unresolvedAddress, promise); + return null; + }, promise); + } + + @Override + protected void doResolveAll(InetSocketAddress unresolvedAddress, Promise> promise) throws Exception { + execute(() -> { + super.doResolveAll(unresolvedAddress, promise); + return null; + }, promise); + } + + private void execute(Callable callable, Promise promise) { + semaphore.acquire().thenAccept(s -> { + promise.addListener(r -> { + semaphore.release(); + }); + try { + callable.call(); + } catch (Exception e) { + promise.setFailure(e); + } + }); + } + } + + private final AsyncSemaphore asyncSemaphore; + + public SequentialDnsAddressResolverFactory() { + this(8); + } + + public SequentialDnsAddressResolverFactory(int concurrencyLevel) { + asyncSemaphore = new AsyncSemaphore(concurrencyLevel); + } + + @Override + public AddressResolverGroup create(Class channelType, DnsServerAddressStreamProvider nameServerProvider) { + DnsAddressResolverGroup group = new DnsAddressResolverGroup(channelType, nameServerProvider) { + @Override + protected AddressResolver newAddressResolver(EventLoop eventLoop, NameResolver resolver) throws Exception { + return new LimitedInetSocketAddressResolver(asyncSemaphore, eventLoop, resolver); + } + }; + return group; + } +}