简体   繁体   English

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

[英]Provide custom implementation for DNS lookup in java.net.URL class

I was wondering if it's possible to provide a custom implementation for DNS lookups on java.net.URL - my hosting provider's DNS gets flaky at certain times of day and then DNS lookups fail for a few minutes, but if I manually configure the relevant domains in my hosts file, they work fine, so what I want to do is have some sort of DNS cache at a software level, if DNS lookup succeed, update the cache, if it fails, fall back to the cached IP address and open the URLConnection on that IP address. 我想知道是否有可能在java.net.URL上为DNS查找提供自定义实现 - 我的托管服务提供商的DNS在一天的某些时间变得不稳定,然后DNS查找失败几分钟,但如果我手动配置相关域在我的hosts文件中,它们工作正常,所以我想做的是在软件级别有一些DNS缓存,如果DNS查找成功,更新缓存,如果失败,则回退到缓存的IP地址并打开对该IP地址进行URLConnection。

This is my URL connection implementation: 这是我的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);
        }
    });

I was looking at proxies on Oracle , but can't see any immediate way to do custom DNS lookups at the software level. 我正在查看Oracle上的代理,但看不到任何直接的方法在软件级别进行自定义DNS查找。

Limitations : 限制

1: It needs to work in Java6 (maybe Java7, but the client won't be switching to Java8 anytime soon) 1:它需要在Java6中工作(可能是Java7,但客户端不会很快切换到Java8)

2: Can't add JVM args 2:无法添加JVM args

3: I don't own these endpoints, so substituting the hostname with an IP address is not a solution since load balancers will serve different content / APIs depending on whether you come from a hostname or an IP address. 3:我没有这些端点,因此用IP地址替换主机名不是解决方案,因为负载均衡器将根据您是来自主机名还是IP地址来提供不同的内容/ API。 As an example: mail.google.com resolves to 216.58.223.37, going to that IP address will serve google.com content and not mail.google.com content, since both services are sitting behind the same load balancer using a single IP address. 例如:mail.google.com解析为216.58.223.37,转到该IP地址将提供google.com内容而不是mail.google.com内容,因为两个服务都使用单个IP地址位于同一负载均衡器后面。

4: I don't know how many URLs' DNS resolutions I'll need to cache, but I do know it won't be more than a 1000. Ideal solution would be to have the DNS resolutions in a static hashmap, if any DNS resolution succeed, update the hashmap, if it fails, use the DNS resolution in the hashmap. 4:我不知道我需要缓存多少URL的DNS解析,但我知道它不会超过1000.理想的解决方案是将DNS解析在静态hashmap中,如果有的话DNS解析成功,更新hashmap,如果失败,则使用hashmap中的DNS解析。

5: If there's a native java solution, I'd prefer that over using JNI - Understanding host name resolution and DNS behavior in Java 5:如果有本机java解决方案,我宁愿过度使用JNI - 了解Java中的主机名解析和DNS行为

You could simply construct another URL: 您可以简单地构建另一个URL:

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

You can implement customDns.resolve(String) using whatever strategy you need. 您可以使用您需要的任何策略实现customDns.resolve(String)

You could create a custom method to check whether the host resolves to an IP. 您可以创建自定义方法来检查主机是否解析为IP。 Prior to opening the connection if the host does not resolve then do your lookup and use the IP directly to build the URL instead: 在主机无法解析之前打开连接之前,请执行查找并直接使用IP来构建URL:

At class level: 在班级:

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

....then a couple of methods to build your URL: ....然后有几种方法来构建你的URL:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM