使用Java连接SFTP时出现UnknownHostException

问题描述 投票:0回答:3

我正在尝试使用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)

任何人都可以解释一下,这个错误的根本原因是什么

java linux amazon-ec2 sftp jsch
3个回答
1
投票

尝试创建新会话时,所有线程都会抛出

UnknownHostException
,并且异常持续长达 5 到 10 分钟,一段时间后程序正常工作,我无法找到导致此异常的原因...

这是非常不言自明的。 阅读 UnknownHostException

javadocs:

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

查看

AbstractPlainSocketImpl
的代码,我明白了:

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

因此您的

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

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

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

    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
文件中。 如果您已经有了,那么这些文件有问题,您需要重新检查您的配置。


1
投票

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

我在这里看到的最可能的原因是名称解析在某些时候确实失败(内部 DNS 服务器不可用等)。 Java 有自己的 DNS 缓存,它独立于操作系统工作,因此即使您可以在命令行上解析名称,它在 Java 中仍然会被视为无法解析。您可以使用系统属性

networkaddress.cache.ttl
networkaddress.cache.negative.ttl
更改该内部缓存的 TTL 设置。将这些属性中的一个或两个设置为
0
会导致该特定缓存停用。

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


0
投票

我遇到了类似的问题,当我更改为在 jsch.getSession() 方法中提供相同的内联时,它起作用了,而不是从 application.properties 获取主机、用户名和端口。不知道为什么。

session = jSch.getSession("USERNAME", "URL", <PORT>);
© www.soinside.com 2019 - 2024. All rights reserved.