【发布时间】:2019-12-17 11:16:28
【问题描述】:
我的应用程序基于 spring-boot 2.1.6,配备了 spring-batch(块方法)和 spring-integration 来处理 SFTP。
高级功能是从数据库中获取数据,生成文本文件,然后通过 SFTP 发送,此任务每 30 分钟运行一次。
此应用程序已经在生产环境中运行了一段时间,但如果我看到日志,则会出现关于 ssh_msg_disconnect 11 idle connection 的错误。它会一直保持这种状态,直到我重新启动应用程序。
以下是我的应用程序代码:
SftpConfig.java
@Configuration
public class SftpConfig {
@Autowired
ApplicationProperties applicationProperties;
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
final DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(applicationProperties.getSftp().getHost());
factory.setUser(applicationProperties.getSftp().getUser());
factory.setPassword(applicationProperties.getSftp().getPass());
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<>(factory);
}
@Bean
@ServiceActivator(inputChannel = "toSftpChannel", adviceChain = "retryAdvice")
public MessageHandler handler() {
final SftpMessageHandler handler = new SftpMessageHandler(this.sftpSessionFactory());
handler.setRemoteDirectoryExpression(new LiteralExpression(applicationProperties.getSftp().getPath()));
handler.setFileNameGenerator((final Message<?> message) -> {
if (message.getPayload() instanceof File) {
return ((File) message.getPayload()).getName();
} else {
throw new IllegalArgumentException("File expected as payload.");
}
});
return handler;
}
@Bean
public RequestHandlerRetryAdvice retryAdvice() {
final RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
final RetryTemplate retryTemplate = new RetryTemplate();
final SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(NumberConstants.FIVE);
retryTemplate.setRetryPolicy(retryPolicy);
advice.setRetryTemplate(retryTemplate);
return advice;
}
@MessagingGateway
public interface UploadGateway {
@Gateway(requestChannel = "toSftpChannel")
void upload(File file);
}
}
发送文件到 sftp 的步骤
@Autowired
UploadGateway uploadGateway;
private boolean uploadToSharedFolderSuccess(final PaymentStatus paymentStatus, final String strLocalTmpPath) {
try {
final File fileLocalTmpFullPath = new File(strLocalTmpPath);
uploadGateway.upload(fileLocalTmpFullPath);
} catch (final Exception e) {
paymentStatus.setStatus(ProcessStatus.ERROR.toString());
paymentStatus.setRemark(StringUtil.appendIfNotEmpty(paymentStatus.getRemark(),
"Error during upload to shared folder - " + e.getMessage()));
}
return !StringUtils.equalsIgnoreCase(ProcessStatus.ERROR.toString(), paymentStatus.getStatus());
}
从错误中,我知道似乎我打开了太多连接。但我不确定如何检查连接是否在 spring-batch 的每一端都关闭。
【问题讨论】:
-
基本上@ServiceActivator 是一个被动组件,它按需从SessionFactory 获取会话。无论如何,下一次通话都应该带来一个新的会话,因为您不使用 isSharedSession 标志。我建议将此标志设置为真。如需参考,请查看属性文档docs.spring.io/spring-integration/docs/5.2.0.M3/reference/html/…
-
如果您希望会话在使用后物理关闭,请不要使用
CachingSessionFactory。 -
@Dhiren,isSharedSession 标志在那里,并在初始化会话工厂期间设置为 true .. 关于按需的事情,是否有任何文章可以支持该声明?
-
@Gary Russell,那我应该用什么?有什么建议吗?
-
如果你想为每个调用分开会话然后使用 DefaultSessionFactory 否则 CachingSessionFactory。取决于您的用例。
标签: java spring spring-boot spring-integration spring-batch