【问题标题】:UnknownHostException occures when connecting SFTP using Java使用 Java 连接 SFTP 时发生 UnknownHostException
【发布时间】:2018-02-11 07:27:44
【问题描述】:

我正在尝试使用 java 中的 5 个线程将文件连续上传到 SFTP 服务器, 在启动程序时正确上传文件,但一段时间后,

所有线程在尝试创建新会话时抛出 UnknownHostException 并且异常持续长达 5 到 10 分钟,经过一段时间程序正常工作后,我无法找到导致此异常的原因,

这是用于连接sftp的代码,

        JSch jsch = new JSch();
        jsch.setKnownHosts(host_file);
        session = jsch.getSession(SFTPUSER,SFTPHOST,SFTPPORT);
        session.setPassword(SFTPPASS);
        java.util.Properties config = new java.util.Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.connect();
        channel = session.openChannel("sftp");
        channel.connect();

例外:

 at td.bdops.clupload.CARUpload.uploadZip(CARUpload.java:398)
    at td.bdops.clupload.CARUpload.uploadZip(CARUpload.java:398)
Caused by: java.net.UnknownHostException: sftp.opsbank2-prod.tio.systems
    at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
    at java.net.PlainSocketImpl.connect(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at java.net.Socket.<init>(Unknown Source)
    at java.net.Socket.<init>(Unknown Source)
    at com.jcraft.jsch.Util.createSocket(Util.java:343)
    at com.jcraft.jsch.Session.connect(Session.java:215)
    at com.jcraft.jsch.Session.connect(Session.java:183)
    at td.bdops.util.FTPUtility.uploadAWSFTP(FTPUtility.java:227)
    at td.bdops.util.FTPUtility.uploadAWSFTP(FTPUtility.java:247)

谁能解释一下,这个错误的根本原因是什么

【问题讨论】:

  • 目标主机有没有可能宕机?
  • 我猜一些打开的套接字没有正确关闭。我建议您先查看/更改程序。如果错误仍然存​​在,也许您可​​以尝试stackoverflow.com/q/30207301中的解决方案
  • @Xvolks 不,发生此异常时我仍然可以通过 FileZilla 访问主机。
  • 如果有帮助,请确保接受答案。

标签: java linux amazon-ec2 sftp jsch


【解决方案1】:

所有线程在尝试创建新会话时抛出 UnknownHostException 并且异常持续长达 5 到 10 分钟,经过一段时间程序正常运行后,我无法找到导致此异常的原因...

这是不言自明的。阅读javadocs for UnknownHostException

抛出表示无法确定主机的IP地址。

查看AbstractPlainSocketImpl的代码我明白了:

if (addr.isUnresolved())
   throw new UnknownHostException(addr.getHostName());

所以您的sftp.opsbank2-prod.tio.systems 主机名无法解析。这意味着 Java 的名称解析代码无法确定该主机名的 IP 是什么。

这里有一些事情可以尝试:

  • 使用该主机名的 IP 而不是名称。
  • 使用dighost 命令在该系统上查找该主机名以查看它是否解析。
  • 尝试下面的代码行看看它是否有效。它也应该抛出:

    new java.net.Socket("unknown.host.should.throw.com", 80).close();
    
  • 现在试试你的主机名:

    new java.net.Socket("sftp.opsbank2-prod.tio.systems", 80).close();
    

如果您发现您的主机名未解析,则需要将其添加到 DNS 配置或 /etc/hosts 文件中。如果你已经有了,那么这些文件有问题,你需要重新检查你的配置。

【讨论】:

    【解决方案2】:

    问题不是 JSCH 特有的问题,正如您在堆栈跟踪中看到的那样,因为它发生在 java.net 包的一个类中,而不是在 jsch-classes 中。因此,使用 FileZilla 进行测试并没有多大帮助。

    我在这里看到的最可能的原因是名称的解析在某些时候确实失败了(内部 DNS 服务器不可用等)。 Java 有自己的 DNS 缓存,独立于操作系统工作,因此即使您可以在命令行上解析名称,它仍然会被视为在 Java 中无法解析。您可以使用系统属性 networkaddress.cache.ttlnetworkaddress.cache.negative.ttl 更改该内部缓存的 TTL 设置。将这些属性中的一个或两个设置为 0 会导致该特定缓存的停用。

    如果您停用后者,您可能会尝试情况是否会好转,但您应该尝试找出问题的根源,即为什么您在一天中的某个时间无法解析名称,因为停用了缓存是有代价的(即性能损失)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2010-09-22
      • 1970-01-01
      相关资源
      最近更新 更多