尝试将文件放在 sftp 上的并行线程经常从 sftp 服务器获取连接重置错误

Getting Connection Reset error from sftp server frequently with parallel threads trying to put file on 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 连接 运行 的 "sessions" 的数量。您仅通过每个连接 运行 设置一个会话(SFTP 会话),因此 MaxSessions 限制与您不是特别相关。

您的问题可能出在 MaxStartups setting:

MaxStartups
Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection. The default is 10:30:100....

基本上,如果有太多客户端连接到服务器尚未通过身份验证,服务器将丢弃其中一些连接。如果您的应用程序同时打开太多与服务器的连接,服务器可能会丢弃其中一些连接。这里的解决办法是调整MaxStartups的值,或者改变你的应用程序不要一次打开那么多连接。

还有一个称为 listen backlog 的操作系统限制。基本上,操作系统只会保留一定数量的未决 TCP 连接。如果同时有足够多的连接尝试进入,而 ssh 服务器进程接受它们的速度不够快,那么 OS 将丢弃一些连接请求。 SSH 服务器请求 128 个连接的积压,但 OS 可能会将积压限制在较低的值。如果您的 SSH 服务器足够繁忙,您可能会 运行 达到此限制。