spring integration idempotent metadatastore message to go store

时间:2016-02-17 20:21:19

标签: spring-integration

我正在使用s3模块从s3轮询文件。它将文件下载到本地系统并开始处理它。我在3节点集群上运行它,模块计数为1.现在假设文件已下载到本地系统从s3和xd处理它。如果xd节点发生故障,它将处理一半的消息。当服务器启动时,它将再次开始处理文件,因此我将获得重复的消息。我正在尝试使用消息存储库更改为幂等模式将模块计数更改为3,但仍然存在重复的消息问题。

这个配置对我有用,感谢您的帮助

 <int:poller fixed-delay="${fixedDelay}" default="true">
        <int:advice-chain>
            <ref bean="pollAdvise"/>

        </int:advice-chain>
    </int:poller>


    <bean id="pollAdvise" class="org.springframework.integration.scheduling.PollSkipAdvice">
        <constructor-arg ref="healthCheckStrategy"/>

    </bean>

    <bean id="healthCheckStrategy" class="test.ServiceHealthCheckPollSkipStrategy">
        <property name="url" value="${url}"/>
        <property name="doHealthCheck" value="${doHealthCheck}"/>
    </bean>



    <bean id="credentials" class="org.springframework.integration.aws.core.BasicAWSCredentials">
        <property name="accessKey" value="${accessKey}"/>
        <property name="secretKey" value="${secretKey}"/>
    </bean>



    <bean id="clientConfiguration" class="com.amazonaws.ClientConfiguration">
        <property name="proxyHost" value="${proxyHost}"/>
        <property name="proxyPort" value="${proxyPort}"/>
        <property name="preemptiveBasicProxyAuth" value="false"/>
    </bean>


    <bean id="s3Operations" class="org.springframework.integration.aws.s3.core.CustomC1AmazonS3Operations">
        <constructor-arg index="0" ref="credentials"/>
        <constructor-arg index="1" ref="clientConfiguration"/>
        <property name="awsEndpoint" value="s3.amazonaws.com"/>
        <property name="temporaryDirectory" value="${temporaryDirectory}"/>
        <property name="awsSecurityKey"  value="${awsSecurityKey}"/>
    </bean>



    <!-- aws-endpoint="https://s3.amazonaws.com"  -->
    <int-aws:s3-inbound-channel-adapter aws-endpoint="s3.amazonaws.com"
                                        bucket="${bucket}"
                                        s3-operations="s3Operations"
                                        credentials-ref="credentials"
                                        file-name-wildcard="${fileNameWildcard}"
                                        remote-directory="${remoteDirectory}"
                                        channel="splitChannel"
                                        local-directory="${localDirectory}"
                                        accept-sub-folders="false"
                                        delete-source-files="true"
                                        archive-bucket="${archiveBucket}"
                                        archive-directory="${archiveDirectory}">
    </int-aws:s3-inbound-channel-adapter>

    <int-file:splitter id="s3splitter" input-channel="splitChannel" output-channel="bridge" markers="false" charset="UTF-8">

        <int-file:request-handler-advice-chain>
            <bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
                <property name="onSuccessExpression" value="payload.delete()"/>
            </bean>
        </int-file:request-handler-advice-chain>

    </int-file:splitter>

我很少有人怀疑如果我做对了。

1)如您所见,我有ExpressionEvaluatingRequestHandlerAdvice来删除文件。在将文件读入redis或读取最后一条记录后,文件是否会被删除?

2)我使用桌面管理器探索了redis我看到我有一个MetaData enter image description here

两个(文件和有效负载)metadatastore密钥和值是否会转到同一个表是这样的?还是应该是不同的metadatastore?

我可以使用有效载荷的散列而不是有效载荷作为密钥吗?有没有像payload.hash这样的东西!

1 个答案:

答案 0 :(得分:1)

抱歉,您仍然没有显示足够的配置来确定问题。

既没有ExpressionEvaluatingRequestHandlerAdvice,也没有s3splitter甚至S3入站通道适配器。

无论如何,我会尝试回答你的问题。

我说使用ExpressionEvaluatingRequestHandlerAdvice删除文件的最佳位置是FileSplitter。并且在读取最后一条记录后将其删除。实际上,即使在涉及任何分裂逻辑之前,通过IdempotentReceiverInterceptor进入Redis的商店也已完成。这是Idempotent接收器的前提:如果我们不接受重复的消息,请不要将消息传递到目标端点:

boolean accept = this.messageSelector.accept(message);
    if (!accept) {
        boolean discarded = false;
 .....

是的,看起来您应该使用具有不同密钥的不同RedisMetadataStore个实例。但这可能是相同的Redis服务器。

不确定您对payload.hash的意思。任何Java对象都有自己的hashCode()。虽然我确定你在分割代表文件中每一行的字符串之后就有了。所以,我认为你真的应该使用类似MD5的东西:

new BigInteger(1, md5.digest(value.toUpperCase().getBytes('UTF-8'))).toString(16).toUpperCase()