Spring Integration Java DSL中的Nio Locker用法用于文件轮询

时间:2018-07-23 21:19:30

标签: java spring-integration spring-integration-dsl

我正在尝试实施spring集成文件轮询,其中多个服务器独立地从一个公共目录读取并处理该文件。处理文件后,每个文件都将其重命名为.DONE,以便其他人不选择它。在观察到两个文件都被选中后,我使用了nioLocker,如下例所示。但是看起来这是行不通的。让我知道使nioLocker在多服务器环境中可靠的必要步骤。出于其他原因,不能选择单独的调解人(例如zookeepr / mongo等)。

谢谢。

 @Bean
    public TransactionSynchronizationFactory transactionSynchronizationFactory() {
        ExpressionParser parser = new SpelExpressionParser();
        ExpressionEvaluatingTransactionSynchronizationProcessor syncProcessor =
                new ExpressionEvaluatingTransactionSynchronizationProcessor();
        syncProcessor.setAfterCommitExpression(parser.parseExpression("payload.renameTo(new java.io.File(payload.path+'.DONE'))"));
        syncProcessor.setAfterRollbackExpression(parser.parseExpression("payload.renameTo(new java.io.File(payload.path+'.DONE'))"));
        return new DefaultTransactionSynchronizationFactory(syncProcessor);
    }

@Bean
public IntegrationFlow receiveInputFile(@Value("/opt/tomcat/in/test") File in,
                                            @Value(".txt") String pattern,
                                            @Value("${edi.poll.delay.all.edi}") int delay,
                                            @Value("${edi.messages.per.poll.new.order}") int messagesPerPoll) {

    //Logging required config for debugging
    LOGGER.debug("EDI File pattern :"+pattern);
    LOGGER.debug("EDI Delay Seconds :"+delay);
    LOGGER.debug("EDI Messages Per Poll :"+messagesPerPoll);


    return IntegrationFlows
            .from(s -> s.file(in).patternFilter(ServicesConstant.PATTERN_PREFIX + pattern).scanEachPoll(true).nioLocker(),
                    e -> e.poller(Pollers.fixedDelay(delay).maxMessagesPerPoll(messagesPerPoll)
                            .transactionSynchronizationFactory(transactionSynchronizationFactory())
                            .transactional(new PseudoTransactionManager())))
            .handle(m -> {
                LOGGER.info("Received test file " + m);
                LOGGER.info("File path: " +m.getPayload());
                LOGGER.info(""+ m.getHeaders().toString());
            })
            .get();
}

1 个答案:

答案 0 :(得分:0)

查看其JavaDocs:

/**
 * File locking strategy that uses java.nio. The locks taken by FileChannel are shared with all the threads in a single
 * JVM, so this locking strategy <b>does not</b> prevent files being picked up multiple times within the same JVM.
 * {@link FileReadingMessageSource}s sharing a Locker will not pick up the same files.
 * <p>
 * This implementation will acquire or create a {@link FileLock} for the given file. Caching locks might be expensive,
 * so this locking strategy is not recommended for scenarios where many files are accessed in parallel.
 *
 * @author Iwein Fuld
 * @author Mark Fisher
 * @since 2.0
 */
public class NioFileLocker extends AbstractFileLockerFilter {

在我的实践中,我们确实只有在Windows上才拥有良好的排他文件锁定。

如果我们仅处理单个本地文件系统,那么我不确定“多服务器环境”对您意味着什么。我非常确定,此NIO锁定对共享的网络目录无效。

如果您不能使用任何共享的持久性存储进行文件过滤,建议您使用真正的共享FileSystemPersistentAcceptOnceFileListFilter实现来研究MetadataStore,让所有服务器协商并确保该文件尚未被其他服务器处理。