java - 经常从 sftp 服务器获取连接重置错误,并行线程试图将文件放在 sftp 上
问题描述
我有一段多线程代码,它有 22 个线程并行运行并试图将文件放在 sftp 服务器上。
但是我的日志中不断出现连接重置错误,因此很少有记录失败。
在初步分析中,我发现 sftp 服务器的大小为 t2.small,CPU 利用率达到 92%。
考虑到这一点,因为我将服务器更改为 c5n.xlarge,现在错误出现的频率降低了,但即使最大 CPU 利用率达到 63%,我有时也会得到它。
我无法在 /var/log/secure 的 sftp 服务器日志中找到任何不同的内容。
下面是用于放置文件的一段代码,每个线程都会创建一个新会话并关闭它。
JSch ssh = new JSch();
// ssh.setKnownHosts("/path/of/known_hosts/file");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
// Use key authentication if it is set, else use password auth
if (mpServerDetails.get(SftpFile.SFTP_USERKEY) != null
&& mpServerDetails.get(SftpFile.SFTP_USERKEY) != "") {
File userKeyFile = new File(mpServerDetails.get(SftpFile.SFTP_USERKEY).toString());
if (userKeyFile == null || !userKeyFile.exists()) {
throw new NonRetriableException(
"Key file " + mpServerDetails.get(SftpFile.SFTP_USERKEY).toString() + "not found.");
}
ssh.addIdentity(userKeyFile.getAbsolutePath());
session = ssh.getSession(mpServerDetails.get(SftpFile.SFTP_USERNAME).toString(),
mpServerDetails.get(SftpFile.SFTP_HOSTNAME).toString());
} else if (mpServerDetails.get(SftpFile.SFTP_PASSWORD) != null) {
session = ssh.getSession(mpServerDetails.get(SftpFile.SFTP_USERNAME).toString(),
mpServerDetails.get(SftpFile.SFTP_HOSTNAME).toString());
session.setPassword(mpServerDetails.get(SftpFile.SFTP_PASSWORD).toString());
}
session.setConfig(config);
session.connect();
if (session != null && !session.isConnected()) {
logger.warn("**session is not connected going to connect the sftp session ** {} ", session.getHost());
session.connect();
}
channel = (ChannelSftp) session.openChannel("sftp");
if (channel != null && !channel.isConnected()) {
logger.warn("**channel is not connected going to connect the sftp channel ** {} ",
channel.getSession().isConnected());
channel.connect();
}
channel.put(file.getAbsolutePath(), dest.getConfig().get(TransporterFileConstants.SFTP_DIRECTORY).toString()
+ File.separatorChar + dest.getFileName(), new SystemOutProgressMonitor());
}
catch (NonRetriableException e) {
throw new NonRetriableException(e);
}
catch (Exception e) {
logger.error(
"Error occured while uploading file having name " + dest.getFileName() + " from remote directory:"
+ dest.getConfig().get(TransporterFileConstants.SFTP_DIRECTORY).toString(),
e);
logger.error("SFTP Exception : ", e);
throw new RetriableException(e);
}
finally {
if (null != channel && channel.isConnected()) {
try {
channel.disconnect();
}
catch (Throwable e) {
logger.error("Error while disconnecting channel : ", e);
}
}
if (null != session) {
try {
session.disconnect();
}
catch (Throwable e) {
logger.error("Error while returning object to sftp pool : ", e);
}
}
}
有人可以帮我理解为什么我可能会得到这个例外吗?
SFTP 服务器配置为
MaxSessions 50
Capacity - 25 GB
4 core server with 10 GB Ram
错误消息的片段
com.jcraft.jsch.JSchException: Session.connect: java.net.SocketException: Connection reset
at com.jcraft.jsch.Session.connect(Session.java:558) ~[honeybee-engine.jar:na]
如果这种情况继续发生,我的数据处理将不一致。
解决方案
MaxSessions 50
SSH 服务器MaxSessions
参数限制可以通过单个 SSH 连接运行的“会话”数量。您只通过每个连接运行一个会话(SFTP 会话),因此 MaxSessions 限制与您并不特别相关。
您的问题可能与MaxStartups
设置有关:
MaxStartups
指定与 SSH 守护程序的最大并发未验证连接数。其他连接将被丢弃,直到身份验证成功或连接的 LoginGraceTime 过期。默认为 10:30:100....
基本上,如果有太多的客户端连接到服务器尚未经过身份验证,服务器将丢弃其中一些连接。如果您的应用程序同时打开太多与服务器的连接,则服务器可能会丢弃其中一些连接。这里的解决方案是调整 MaxStartups 的值,或者更改您的应用程序不要一次打开这么多连接。
还有一个操作系统限制,称为listen backlog。基本上,操作系统只会保留一定数量的待处理 TCP 连接。如果同时有足够多的连接尝试,并且 ssh 服务器进程在接受它们时不够快,那么操作系统将丢弃一些连接请求。SSH 服务器请求积压 128 个连接,但操作系统可能会将积压限制在较低的值。如果您的 SSH 服务器足够繁忙,您可能会遇到此限制。
推荐阅读
- php - 无法在 cookie 中存储与变量相同的随机字符串
- android - 我是否需要为每个列表项 Recycleview 创建每次 Newactivity?
- jms - spring 如何在 DefaultMessageListenerContainer 中设置持久订阅者?
- android - 视频视图 VideoView.setVideoURI(android.net.Uri)' 在空对象引用上
- php - 无法通过 jquery 将变量传递到下一页
- typescript - 以编程方式为 Typescript 中的颜色添加不透明度
- python - 使用 python 和 TypeError 解析特定值:列表索引必须是整数或切片,而不是 str
- mysql - 使用 MySQL 查询删除重复项
- javascript - 初学者如何使用 yarn 为 ReactJS 启动服务器
- twilio - Twilio 功能 - 阻止垃圾邮件/800#s