2017-01-30 16 views
0

У меня есть приложение, которое SFTPs файл через SftpInboundFileSynchronizer:Как SFTP после тайм-аута сеанса с использованием JSch и Spring Integration

@Bean 
public SftpInboundFileSynchronizer sftpInboundFileSynchronizer() { 
    SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory()); 
    fileSynchronizer.setDeleteRemoteFiles(false); 
    fileSynchronizer.setRemoteDirectory(applicationProperties.getSftpDirectory()); 
    CompositeFileListFilter<ChannelSftp.LsEntry> compositeFileListFilter = new CompositeFileListFilter<ChannelSftp.LsEntry>(); 
    compositeFileListFilter.addFilter(new SftpPersistentAcceptOnceFileListFilter(store, "sftp")); 
    compositeFileListFilter.addFilter(new SftpSimplePatternFileListFilter(applicationProperties.getLoadFileNamePattern())); 
    fileSynchronizer.setFilter(compositeFileListFilter); 
    fileSynchronizer.setPreserveTimestamp(true); 
    return fileSynchronizer; 
} 

сессии завода:

@Bean 
public SessionFactory<LsEntry> sftpSessionFactory() { 
    DefaultSftpSessionFactory sftpSessionFactory = new DefaultSftpSessionFactory(); 
    sftpSessionFactory.setHost(applicationProperties.getSftpHost()); 
    sftpSessionFactory.setPort(applicationProperties.getSftpPort()); 
    sftpSessionFactory.setUser(applicationProperties.getSftpUser()); 
    sftpSessionFactory.setPassword(applicationProperties.getSftpPassword()); 
    sftpSessionFactory.setAllowUnknownKeys(true); 
    return new CachingSessionFactory<LsEntry>(sftpSessionFactory); 
} 

SftpInboundFileSynchronizingMessageSource установлен на опрос с использованием сложный триггер.

@Bean 
@InboundChannelAdapter(autoStartup="true", channel = "sftpChannel", poller = @Poller("pollerMetadata")) 
public SftpInboundFileSynchronizingMessageSource sftpMessageSource() { 
    SftpInboundFileSynchronizingMessageSource source = 
      new SftpInboundFileSynchronizingMessageSource(sftpInboundFileSynchronizer()); 
    source.setLocalDirectory(applicationProperties.getScheduledLoadDirectory()); 
    source.setAutoCreateLocalDirectory(true); 
    CompositeFileListFilter<File> compositeFileFilter = new CompositeFileListFilter<File>(); 
    compositeFileFilter.addFilter(new LastModifiedFileListFilter()); 
    compositeFileFilter.addFilter(new FileSystemPersistentAcceptOnceFileListFilter(store, "dailyfilesystem")); 
    source.setLocalFilter(compositeFileFilter); 
    source.setCountsEnabled(true); 
    return source; 
} 

Поллер создан с помощью сложного триггера. Он имеет триггер cron, чтобы попытаться SFTP ожидаемого файла один раз в день. Если ожидаемый файл не найден, у меня есть периодический триггер, который переопределяет триггер cron. Он каждые 15 минут пытается SFTP-файл (до 5 раз). После того, как он либо получит файл, либо попробовал 5 раз, чтобы получить файл, триггер cron переопределяет периодический триггер. Эта логика содержит RetryCompoundTriggerAdvice.

@Bean 
public PollerMetadata pollerMetadata(RetryCompoundTriggerAdvice retryCompoundTriggerAdvice) { 
    PollerMetadata pollerMetadata = new PollerMetadata(); 
    List<Advice> adviceChain = new ArrayList<Advice>(); 
    adviceChain.add(retryCompoundTriggerAdvice); 
    pollerMetadata.setAdviceChain(adviceChain); 
    pollerMetadata.setTrigger(compoundTrigger()); 
    pollerMetadata.setMaxMessagesPerPoll(1); 
    return pollerMetadata; 
} 

@Bean 
public CompoundTrigger compoundTrigger() { 
    CompoundTrigger compoundTrigger = new CompoundTrigger(primaryTrigger()); 
    return compoundTrigger; 
} 

@Bean 
public CronTrigger primaryTrigger() { 
    return new CronTrigger(applicationProperties.getSchedule()); 
} 

@Bean 
public PeriodicTrigger secondaryTrigger() { 
    return new PeriodicTrigger(applicationProperties.getRetryInterval()); 
} 

RetryCompoundTriggerAdvice

@Component 
public class RetryCompoundTriggerAdvice extends AbstractMessageSourceAdvice { 

    private final static Logger logger = LoggerFactory.getLogger(RetryCompoundTriggerAdvice.class); 

    private final CompoundTrigger compoundTrigger; 

    private final Trigger override; 

    private final ApplicationProperties applicationProperties; 

    private final Mail mail; 

    private int attempts = 0; 

    public RetryCompoundTriggerAdvice(CompoundTrigger compoundTrigger, 
      @Qualifier("secondaryTrigger") Trigger override, 
      ApplicationProperties applicationProperties, 
      Mail mail) { 
     this.compoundTrigger = compoundTrigger; 
     this.override = override; 
     this.applicationProperties = applicationProperties; 
     this.mail = mail; 
    } 

    @Override 
    public boolean beforeReceive(MessageSource<?> source) { 
     return true; 
    } 

    @Override 
    public Message<?> afterReceive(Message<?> result, MessageSource<?> source) { 
     final int maxOverrideAttempts = applicationProperties.getMaxFileRetry(); 
     attempts++; 
     if (result == null && attempts < maxOverrideAttempts) { 
      logger.info("Unable to find load file after " + attempts + " attempt(s). Will reattempt"); 
      this.compoundTrigger.setOverride(this.override); 
     } else if (result == null && attempts >= maxOverrideAttempts) { 
      mail.sendAdminsEmail("Missing File"); 
      attempts = 0; 
      this.compoundTrigger.setOverride(null); 
     } 
     else { 
      attempts = 0; 
      this.compoundTrigger.setOverride(null); 
      logger.info("Found load file"); 
     } 
     return result; 
    } 

    public void setOverrideTrigger() { 
     this.compoundTrigger.setOverride(this.override); 
    } 

    public CompoundTrigger getCompoundTrigger() { 
     return compoundTrigger; 
    } 
} 

Проблема заключается в том, что, когда приложение reattempts на SFTP через 15 минут, сеанс сервера истекло. Так, сообщает JSch:

2017-01-27 18:30:01.447 INFO 14248 --- [Connect thread my.sftp.com session] com.jcraft.jsch       : Caught an exception, leaving main loop due to End of IO Stream Read 
2017-01-27 18:30:01.448 INFO 14248 --- [Connect thread my.sftp.com session] com.jcraft.jsch       : Disconnecting from my.sftp.com port 22 

В результате, никакие дополнительные сообщения не принимаются, и приложение не будет пытаться не SFTP файла до времени следующих хрон (то есть на следующий день). Как я могу повторно загрузить SFTP-файл после ожидания 15 минут?

Я пробовал звонить setServerAliveInterval на DefaultSftpSessionFactory без какой-либо удачи. Примечание. После восстановления файла или 5 попыток я хочу прекратить связь с сервером SFTP до следующего запуска cron.

Обновление Наконец-то я смог выполнить тест. Добавление журнала отладки в соответствии с запросом. Примечание: ведение журнала отладки устанавливается следующим образом в файле пропеллера:

logging.level.org.springframework: DEBUG 
logging.level.com.jcraft.jsch: DEBUG 

Вот лог:

2017-02-15 18:15:56.206 DEBUG 26748 --- [task-scheduler-9] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:16:56.211 DEBUG 26748 --- [task-scheduler-9] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:17:56.213 DEBUG 26748 --- [task-scheduler-8] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:18:56.214 DEBUG 26748 --- [task-scheduler-8] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:19:56.215 DEBUG 26748 --- [task-scheduler-8] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:20:56.215 DEBUG 26748 --- [task-scheduler-8] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:21:56.217 DEBUG 26748 --- [task-scheduler-8] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:22:56.218 DEBUG 26748 --- [task-scheduler-8] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:23:56.219 DEBUG 26748 --- [task-scheduler-3] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:24:56.221 DEBUG 26748 --- [task-scheduler-2] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:25:56.222 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:26:56.223 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:27:56.224 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:28:56.225 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:29:56.226 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:30:03.884 INFO 26748 --- [Connect thread my.sftp.com session] com.jcraft.jsch       : Caught an exception, leaving main 
loop due to End of IO Stream Read 
2017-02-15 18:30:03.884 INFO 26748 --- [Connect thread my.sftp.com session] com.jcraft.jsch       : Disconnecting from my.sftp.com port 22 
2017-02-15 18:30:56.227 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:31:56.228 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:32:56.228 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 
2017-02-15 18:33:56.230 DEBUG 26748 --- [task-scheduler-6] o.s.i.e.SourcePollingChannelAdapter  : Received no Message during the poll, returning 'false' 

JSch не регистрирует отладочный, даже если у меня есть набор уровня отладки. Из журнала похоже, что соединение SFTP завершено. Примечание: поток task-scheduler-6 проводит опрос каждую минуту в результате использования другого poller для синхронизации файловой системы.

ответ

0

Кэш должен обнаруживать, что сеанс больше не действителен и выдает новый. Мне нужно увидеть журнал DEBUG (для весны и jsch), чтобы выяснить, что происходит.

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

+0

Спасибо за ответ. Я работаю над созданием тестовой среды для воспроизведения проблемы. Сделав это, я отправлю код отладки. Я также переключусь на использование фабрики сеансов напрямую и выясню, устранена ли проблема. – James

+0

Наконец-то я смог пройти тестовый прогон. К сожалению, журнал отладки, вероятно, не дает никакой полезной информации. Должен ли я попытаться отслеживать? Кроме того, переход от сеанса кэша к использованию простой старой фабрики сеансов не помог решить проблему. – James

+0

Без кеша вряд ли возникает проблема с клиентом. Вы посмотрели журналы сервера? –