Получение ошибки сброса соединения с сервера sftp часто с параллельными потоками, пытающимися поместить файл на sftp - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть часть многопоточного кода, в котором 22 потока работают параллельно и пытаются поместить файлы на сервер sftp.

Но я периодически получаю сообщение об ошибке сброса подключения в моих журналах, и некоторые из записей терпят неудачу, потому чтоиз этого.

При первоначальном анализе я обнаружил, что размер sftp-сервера был t2.small, а загрузка ЦП приближалась к 92%.

Учитывая то, что я изменил сервер на c5n.xlarge, теперь ошибка появляется реже, но, тем не менее, я получаю ее время от времени, даже когда максимальная загрузка ЦП достигает 63%.

Я не могу найти что-то другое в журналах сервера sftp по адресу /var/log/secure.

Ниже приведен фрагмент кода, используемый для помещения файла, каждый поток создает новый сеанс и закрывает его.

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]

Если это продолжится, моя обработка данных будет непоследовательной.

1 Ответ

0 голосов
/ 13 апреля 2019
MaxSessions 50

Параметр SSH-сервера MaxSessions ограничивает количество «сеансов», которые могут выполняться через одно соединение SSH. Вы выполняете только один сеанс - сеанс SFTP - через каждое соединение, поэтому ограничение MaxSessions не особенно подходит для вас.

Ваша проблема может быть связана с настройкой MaxStartups :

MaxStartups
Задает максимальное количество одновременных неаутентифицированных подключений к демону SSH. Дополнительные соединения будут сброшены до тех пор, пока аутентификация не пройдет успешно или не истечет срок действия LoginGraceTime для соединения. По умолчанию 10: 30: 100 ....

В основном, если к серверу подключено слишком много клиентов , которые еще не аутентифицировались , сервер прервет некоторые из этих соединений. Если ваше приложение одновременно открывает слишком много соединений с сервером, возможно, сервер отбрасывает некоторые из этих соединений. Решение здесь состоит в том, чтобы скорректировать значение MaxStartups или изменить приложение, чтобы оно не открывало столько соединений одновременно.

Существует также ограничение операционной системы, называемое listen backlog . По сути, операционная система будет удерживать только определенное количество ожидающих TCP-соединений. Если одновременно происходит достаточное количество попыток подключения и процесс ssh-сервера недостаточно быстр для их принятия, то ОС отбросит некоторые запросы на подключение. Сервер SSH запрашивает резерв из 128 подключений, но операционная система может ограничить резерв более низким значением. Если ваш SSH-сервер достаточно занят, возможно, вы используете этот предел.

...