내가 응용 프로그램을 사용하여 세션 시간 초과 후 SFTP하기 :가 어떻게 <code>SftpInboundFileSynchronizer</code>를 통해 파일을 SFTPs JSch와 Spring 통합
@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;
}
폴러는 복합 트리거로 설정됩니다. 그것은 하루에 한 번 예상 파일을 SFTP하려고하는 cron 트리거가 있습니다. 예상 된 파일을 찾을 수없는 경우 cron 트리거를 재정의하는주기적인 트리거가 있습니다. 파일을 SFTP로 15 분마다 시도합니다 (최대 5 번). 파일을 가져 오거나 파일을 가져 오기 위해 5 번 시도한 후 cron 트리거가 주기적 트리거보다 우선합니다. RetryCompoundTriggerAdvice
에는이 논리가 들어 있습니다.
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;
}
}
@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());
}
문제
응용 프로그램 15 분 SFTP를 재 시도 할 때, 서버의 세션 타임 아웃했다고한다. 그래서, 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를 시도하지 않습니다. 15 분을 기다린 후 SFTP 파일로 다시 시도하려면 어떻게해야합니까?
DefaultSftpSessionFactory
에 setServerAliveInterval
을 전화를 걸어 보았습니다. 참고 : 파일을 가져 오거나 5 회 시도한 후 다음 cron이 실행될 때까지 SFTP 서버와의 통신을 중단하고 싶습니다.
업데이트 마침내 테스트를 실행할 수있었습니다. 요청 된대로 디버그 로그를 추가합니다. 참고 : 디버그 로그 소품 파일에 다음과 같이 설정합니다
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 스레드는 파일 시스템 동기화를위한 다른 폴러의 결과로 분 단위로 폴링합니다.
응답 해 주셔서 감사합니다. 문제를 재현 할 테스트 환경을 설정하기 위해 노력하고 있습니다. 완료되면 디버그 코드를 게시합니다. 또한 세션 팩토리를 직접 사용하여 문제가 해결되었는지 확인합니다. – James
마침내 테스트를 실행할 수있었습니다. 아쉽게도 디버그 로그는 유용한 정보를 제공하지 않습니다. 추적 해볼까요? 또한 캐시 세션에서 평범한 이전 세션 팩토리를 사용하여 문제를 해결하지 못했습니다. – James
캐시가 없으면 클라이언트 문제가 발생하지 않습니다. 서버 로그를 보셨습니까? –