我正在尝试使用java中的5个线程将文件连续上传到SFTP服务器, 在启动程序正确上传文件,但一段时间后,
在尝试创建新会话时,所有线程都会抛出UnknownHostException,并且Exception会持续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)
任何人都可以解释一下,这个错误的根本原因是什么
答案 0 :(得分:1)
问题不是特定于JSCH的问题,因为它可以在堆栈跟踪中看到,因为它发生在java.net包的一个类中,而不是在jsch-classes中。因此,使用FileZilla进行测试对此没什么帮助。
我在这里看到的最可能的原因是,名称的解析在某些时候确实失败了(内部DNS服务器不可用等)。 Java有自己的DNS缓存,它独立于操作系统工作,所以即使你可以在命令行上解析名称,它仍然会在Java中被视为无法解析。您可以使用系统属性networkaddress.cache.ttl
和networkaddress.cache.negative.ttl
更改该内部缓存的TTL设置。将这些属性中的一个或两个设置为0
会导致停用该特定缓存。
如果您停用后者,情况会好转,但您应该尝试找出问题的根源,例如为什么您无法在白天的某个时间解析名称,因为停用了缓存带有价格(即性能损失)。
答案 1 :(得分:0)
所有线程在尝试创建新会话时抛出
UnknownHostException
并且异常持续5到10分钟,在一段时间程序正常工作后,我无法找到导致此异常的原因...
这是非常自我解释的。阅读javadocs for UnknownHostException
:
抛出表示无法确定主机的IP地址。
查看AbstractPlainSocketImpl
的代码,我看到了:
if (addr.isUnresolved())
throw new UnknownHostException(addr.getHostName());
因此您的sftp.opsbank2-prod.tio.systems
主机名无法解析。这意味着Java的名称解析代码无法确定该主机名的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
文件中。如果您已经有,那么这些文件有问题,您需要重新检查配置。