在java.net.URL类中为DNS查找提供自定义实现

在java.net.URL类中为DNS查找提供自定义实现,java,caching,dns,Java,Caching,Dns,我想知道是否有可能为java.net.URL上的DNS查找提供自定义实现-我的主机提供商的DNS在一天中的某些时间会出现问题,然后DNS查找会失败几分钟,但是如果我在主机文件中手动配置相关域,它们工作正常,因此,我想做的是在软件级别使用某种DNS缓存,如果DNS查找成功,更新缓存,如果失败,返回缓存的IP地址并打开该IP地址上的URLConnection 这是我的URL连接实现: URL endpoint = new URL(null, url, new URLStreamHandler

我想知道是否有可能为java.net.URL上的DNS查找提供自定义实现-我的主机提供商的DNS在一天中的某些时间会出现问题,然后DNS查找会失败几分钟,但是如果我在主机文件中手动配置相关域,它们工作正常,因此,我想做的是在软件级别使用某种DNS缓存,如果DNS查找成功,更新缓存,如果失败,返回缓存的IP地址并打开该IP地址上的URLConnection

这是我的URL连接实现:

    URL endpoint = new URL(null, url, new URLStreamHandler() {
        @Override
        protected URLConnection openConnection(URL url)
                throws IOException {
            URL target = new URL(url.toString());
            URLConnection connection = target.openConnection();
            // Connection settings
            connection.setConnectTimeout(connectionTimeout);
            connection.setReadTimeout(readTimeout);
            return (connection);
        }
    });
我正在查看上的代理,但看不到在软件级别进行自定义DNS查找的任何即时方法

限制

1:它需要在Java6中工作(可能是Java7,但客户端不会很快切换到Java8)

2:无法添加JVM参数

3:我不拥有这些端点,因此用IP地址替换主机名不是解决方案,因为负载平衡器将根据您来自主机名还是IP地址提供不同的内容/API。例如:mail.google.com解析为216.58.223.37,转到该IP地址将提供google.com内容,而不是mail.google.com内容,因为这两个服务都位于使用单个IP地址的同一负载平衡器后面

4:我不知道需要缓存多少URL的DNS解析,但我知道不会超过1000。理想的解决方案是将DNS解析放在静态哈希映射中,如果任何DNS解析成功,则更新哈希映射,如果失败,则使用哈希映射中的DNS解析


5:如果有一个本机java解决方案,我更喜欢使用JNI-

而不是构建另一个URL:

URL target = new URL(
    url.getProtocol(),
    customDns.resolve(url.getHost()),
    url.getFile());

您可以使用所需的任何策略实现
customDns.resolve(String)

您可以创建一个自定义方法来检查主机是否解析为IP。在打开连接之前,如果主机未解析,请执行查找并直接使用IP构建URL:

在班级层面:

private Map<String,InetAddress> cacheMap = new HashMap<String,InetAddress>();

如果需要更优雅的解决方案,您能否简单地将URL的主机部分替换为自定义DNS实现将返回的IP地址?我的意思是,使用简单的旧字符串操作。我需要维护大约500个URL,我希望找到一个解决方案,在这个解决方案中,我可以只使用一个静态哈希映射,并在内存中查找90秒的DNS,这可能是一天一次。@Janvladimirmoster你解决了这个问题吗?我的代码无法访问hackerrank上运行的AWS。任何id如何获取ip或更改dns?我已经发布了我的解决方案。如果没有帮助,请发布一个新的堆栈溢出问题,我会看一看。在我的情况下不起作用我无法访问/etc/hosts,如果您知道任何解决方案,请让我知道我连接的一些端点位于AWS和GCE上,如果您解析www.example.com的IP地址,您将获得一个IP地址,但是,如果有多个服务在某个IP地址上运行,则向该IP地址投递和向主机名投递将得到完全不同的结果。OK。我从你的问题中没有意识到这一点。那么,如果IP上运行多个服务,“如果失败,返回缓存的IP地址并打开该IP地址上的URLConnection”将如何工作呢?如果我们控制端点,用IP地址替换主机将是一个解决方案,不幸的是,我不是。让我们以mail.google.com为例,它解析为216.58.223.37,但访问它的是google.com,而不是mail.google.comNGINX/Apache/。。。负载平衡器根据您的主机名决定加载哪个服务,如果您是通过IP地址进入的,则实际上是通过不同的主机名进入的。OK。明白这一点。我可以建议你修改你原来的问题,把这些额外的信息包括进去吗?这个问题不包括任何这些细节!如果我们控制端点,用IP地址替换主机将是一个解决方案,不幸的是,我不是。让我们以mail.google.com为例,它解析为216.58.223.37,但访问它的是google.com而不是mail.google.com
private URL buildUrl (String host) throws MalformedURLException {
    InetAddress ia = resolveHostToIp(host);
    URL url = null;

    if (ia != null) {
        url = new URL(ia.getHostAddress());
    } else {
        // Does not resolve and is not in cache....dunno
    }
    return url;
}


 private InetAddress resolveHostToIp(String host) {
    InetAddress ia = null;
    try {
        ia = InetAddress.getByName(host);
        // Update your cache
        cacheMap.put(host, ia);
    } catch (UnknownHostException uhe) {
        System.out.println("\"" + host + "\" does not resolve to an IP! Looking for it in the cacheMap....");
        // Head off to your cache and return the InetAddress from there.....
        ia = cacheMap.get(host);
    }
    return ia;
}