目前,有一个Tomcat运行实例,Apache Camel生成并使用直接路由,并且工作正常。例如:
<dataFormats>
<gzip id="gzip" />
</dataFormats>
<route id="1_consumeAdServerMq" >
<from uri="rabbitmq://localhost/adserver?queue=ad_google_dfa_reporting&routingKey=ad_google_dfa_reporting&declare=false&autoAck=false&prefetchEnabled=true&prefetchCount=2&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&routingKey=ad_google_dfa_reporting&declare=false&autoAck=false&prefetchEnabled=true&prefetchCount=2&concurrentConsumers=1"/>
<bean ref="dfaReportingFact" method="execute"/>
<to uri="rabbitmq://localhost/adserver?routingKey=ad_google_dfa_reporting_upload&declare=false&bridgeEndpoint=true"/>
</route>
<route id="2_uploadToS3" errorHandlerRef="dlc">
<from uri="rabbitmq://localhost/adserver?queue=ad_google_dfa_reporting_upload&routingKey=ad_google_dfa_reporting_upload&declare=false&autoAck=false&prefetchEnabled=true&prefetchCount=2&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;
}
如果上述方法出错,那么在服务器重启(有意或无意)后,确保路由“继续”或“恢复”的安全/最佳做法是什么?
答案 0 :(得分:0)
当正确关闭Camel上下文时,default behavior of Camel将为路径提供足够的时间来完成。但是如果强制提到服务器关闭,那么飞行交换(以及这些交换的头部)就会丢失。
我们最近遇到了类似的问题,我们考虑实施自定义关闭策略,以便在路由再次出现时保持机上交换并重新启动处理。我们考虑的一种模式是以自定义格式保存到文件中,因此我们可以存储Exchange头和有效负载等元数据。最后,我们决定反对这一点,并且在强制关闭的情况下使用JMS事务从路由起点重新开始处理。
有old thread on the Users mailing list讨论机上交流的故障转移,答案几乎相同。