Java 无法解析主机名

标签 java amazon-web-services

我正在尝试在 AWS ECS 容器中启动 Java 应用程序,但 Java 无法查找主机名。

ECS 设置主机名并正确设置/etc/hosts 和/etc/resolv.conf。如果我执行 nslookup `hostname`,我就能很好地解决问题。我还可以根据/etc/resolv.conf 中设置的名称服务器解决该问题

但是如果我启动尝试解析主机名的 Java 应用程序,我会收到一个异常,表明无法解析主机名。

java 版本输出:

bash# java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

所以我写了一个小测试程序:

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.PrintWriter;
import java.io.StringWriter;

public class DomainResolutionTest {

    public static void main(String[] args) {

        try {
            InetAddress ip = InetAddress.getLocalHost();
            System.out.println(ip.toString());
        }catch (UnknownHostException uhx) {
            System.out.println("ERROR: " + uhx.getMessage() + "\n" + getStackTrace(uhx));
            Throwable cause = uhx.getCause();
            if (cause != null) System.out.println("CAUSE: " + cause.getMessage());
        }

    }

    public static String getStackTrace(Throwable t)
    {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw, true);
        t.printStackTrace(pw);
        pw.flush();
        sw.flush();
        return sw.toString();
    }

}

当主机名为“f17a0bdca449”时会抛出以下错误:

ERROR: f17a0bdca449: f17a0bdca449: unknown error
java.net.UnknownHostException: f17a0bdca449: f17a0bdca449: unknown error
    at java.net.InetAddress.getLocalHost(InetAddress.java:1484)
    at DomainResolutionTest.main(DomainResolutionTest.java:11)
Caused by: java.net.UnknownHostException: f17a0bdca449: unknown error
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:907)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1302)
    at java.net.InetAddress.getLocalHost(InetAddress.java:1479)
    ... 1 more

CAUSE: f17a0bdca449: unknown error

如果我使用 -Djava.net.preferIPv4Stack=true 将 java 切换为使用 ipv4 堆栈,我得到:

$> java -Djava.net.preferIPv4Stack=true DomainResolutionTest
ERROR: f17a0bdca449: f17a0bdca449: unknown error
java.net.UnknownHostException: f17a0bdca449: f17a0bdca449: unknown error
    at java.net.InetAddress.getLocalHost(InetAddress.java:1484)
    at DomainResolutionTest.main(DomainResolutionTest.java:11)
Caused by: java.net.UnknownHostException: f17a0bdca449: unknown error
    at java.net.Inet4AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:907)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1302)
    at java.net.InetAddress.getLocalHost(InetAddress.java:1479)
    ... 1 more

CAUSE: f17a0bdca449: unknown error

如果我强制它使用 sun 实现并指定 NAMESERVER 和 SEARCH_DOMAIN,我仍然会得到同样的结果:

$> export NAMESERVER=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}')
$> export SEARCH_DOMAIN=$(cat /etc/resolv.conf | grep search | awk '{print $2}')
$> java -Dsun.net.spi.nameservice.provider.1=dns,sun -Dsun.net.spi.nameservice.nameservers=${NAMESERVER} -Dsun.net.spi.nameservice.domain=${SEARCH_DOMAIN} -Djava.net.preferIPv4Stack=true DomainResolutionTest
ERROR: f17a0bdca449: DNS name not found [response code 3]
java.net.UnknownHostException: f17a0bdca449: DNS name not found [response code 3]
    at java.net.InetAddress.getLocalHost(InetAddress.java:1484)
    at DomainResolutionTest.main(DomainResolutionTest.java:11)
Caused by: java.net.UnknownHostException: DNS name not found [response code 3]
    at sun.net.spi.nameservice.dns.DNSNameService.resolve(DNSNameService.java:180)
    at sun.net.spi.nameservice.dns.DNSNameService.lookupAllHostAddr(DNSNameService.java:351)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1302)
    at java.net.InetAddress.getLocalHost(InetAddress.java:1479)
    ... 1 more

CAUSE: DNS name not found [response code 3]

我已经无计可施了。有什么建议吗?

最佳答案

您获取的主机信息是 docker 容器的主机名。 这个问题不是 ecs 独有的,对于在 docker 容器中运行的任何 java 应用程序都是如此。

使用 ECS,您无法选择将主机名作为运行时配置注入(inject)。

在 AWS 环境中运行时,更好的解决方案是使用 AWS 元数据服务来获取主机名。

对 AWS 元数据服务的 http GET 请求,应该会为您提供主机的详细信息。

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

如果您的应用程序中包含 java aws sdk,您可以利用以下类 http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/util/EC2MetadataUtils.InstanceInfo.html

关于Java 无法解析主机名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35513909/

相关文章:

java - 如何使用feign客户端实现下载文件

amazon-web-services - Cloudformation 模板中 IAM 资源之间的循环依赖关系

r - 使用 Amazon s3 API GET 请求正确下载文件的参数

java - 在关闭未完成编辑的 JFrame 时保存 JTable 的内容

amazon-web-services - 如何在没有用户交互的情况下使用 AWS/Amplify CLI 部署现有 Amplify 应用程序的新版本?

amazon-web-services - AWS Glue - 条件触发器是否可以针对另一个工作流程中的作业进行条件触发?

amazon-web-services - "Everyone"委托(delegate)人在 Amazon SQS 权限中有什么范围?

java - 使用jsoup登录网站

java - DecimalFormat 和定点数的舍入

java - JNLP/Java Web Start 可以启动命令行应用程序吗