如果消息是从RabbitMQ生成和消费的,如何保留Apache Camel Exchange的属性

时间:2015-01-29 06:05:34

标签: java apache-camel rabbitmq

目前,有一个Tomcat运行实例,Apache Camel生成并使用直接路由,并且工作正常。例如:

    <dataFormats>
        <gzip id="gzip" />
    </dataFormats>  

    <route id="1_consumeAdServerMq" >
        <from uri="rabbitmq://localhost/adserver?queue=ad_google_dfa_reporting&amp;routingKey=ad_google_dfa_reporting&amp;declare=false&amp;autoAck=false&amp;prefetchEnabled=true&amp;prefetchCount=2&amp;concurrentConsumers=1"/>

            <bean ref="dfaReportingFact" method="execute"/>                             
            <to uri="direct:sendToS3" />        
    </route>

    <route id="2_uploadToS3" errorHandlerRef="dlc">
        <from uri="direct:sendToS3" />

        <setHeader headerName="CamelAwsS3Key">
            <method ref="dfaReportingFact" method="getS3Path"/>
        </setHeader>
        <marshal ref="gzip"/>
        <to uri="aws-s3://data?amazonS3Client=#aws-auth"/>
    </route>

第一个路由“1_consumeAdServerMq”使用来自RabbitMQ的消息,并通过方法“execute”上的Bean“dfaReportingFact”处理它,其中“execute”方法返回一个文件对象。最后,骆驼路线到uri“direct:sendToS3”。

在第二条路线“2_uploadToS3”上,它获取文件对象,并在gzip之后上传到S3。

问题是,如果第一条路线完成,并且正在第二条路线上工作,则突然有服务器重启。第二条路线未完成,应用程序服务器重新启动而不知道继续。

我尝试在第一条路由后将消息发送到另一个Rabbit队列(因此​​即使在服务器重启后,它肯定会继续),但它会丢失Camel Exchange的属性,我需要完成整个事务。以下是发送到RabbitMQ后丢失camel exchange属性的路由示例:

   <dataFormats>
        <gzip id="gzip" />
    </dataFormats>  

    <route id="1_consumeAdServerMq" >
        <from uri="rabbitmq://localhost/adserver?queue=ad_google_dfa_reporting&amp;routingKey=ad_google_dfa_reporting&amp;declare=false&amp;autoAck=false&amp;prefetchEnabled=true&amp;prefetchCount=2&amp;concurrentConsumers=1"/>

            <bean ref="dfaReportingFact" method="execute"/>                             
            <to uri="rabbitmq://localhost/adserver?routingKey=ad_google_dfa_reporting_upload&amp;declare=false&amp;bridgeEndpoint=true"/>       
    </route>

    <route id="2_uploadToS3" errorHandlerRef="dlc">
        <from uri="rabbitmq://localhost/adserver?queue=ad_google_dfa_reporting_upload&amp;routingKey=ad_google_dfa_reporting_upload&amp;declare=false&amp;autoAck=false&amp;prefetchEnabled=true&amp;prefetchCount=2&amp;concurrentConsumers=1"/>

        <setHeader headerName="CamelAwsS3Key">
            <method ref="dfaReportingFact" method="getS3Path"/>
        </setHeader>
        <marshal ref="gzip"/>
        <to uri="aws-s3://data?amazonS3Client=#aws-auth"/>
    </route>

在应用程序调试模式下,bean dfaReportingFact的方法“getS3Path”没有在方法“execute”期间设置的任何内容。我的getS3Path代码如下:

public String getS3Path(@Properties Map<String, Object> properties, @Header(value = "messageId") String filename){
    // the following code returns **null**, because there is no key match  for "model" in this concurrenthashmap
    DfaReportingModel model = (DfaReportingModel) properties.get("model"); 
    String path = model.getS3Path(adServerInstance);
    logger.info("path: "+ path);;
    return path;
}

如果上述方法出错,那么在服务器重启(有意或无意)后,确保路由“继续”或“恢复”的安全/最佳做法是什么?

1 个答案:

答案 0 :(得分:0)

当正确关闭Camel上下文时,default behavior of Camel将为路径提供足够的时间来完成。但是如果强制提到服务器关闭,那么飞行交换(以及这些交换的头部)就会丢失。

我们最近遇到了类似的问题,我们考虑实施自定义关闭策略,以便在路由再次出现时保持机上交换并重新启动处理。我们考虑的一种模式是以自定义格式保存到文件中,因此我们可以存储Exchange头和有效负载等元数据。最后,我们决定反对这一点,并且在强制关闭的情况下使用JMS事务从路由起点重新开始处理。

old thread on the Users mailing list讨论机上交流的故障转移,答案几乎相同。