无法从smb删除文件时的文件回滚

时间:2018-11-15 13:09:22

标签: apache-camel activemq

我有一条骆驼路线,其中生产者是smb挂载,而消费者是ActiveMQ队列。

当SMB服务器无法从源SMB挂载删除文件时,我想回滚事务。但是,这是在事务的提交阶段发生的。

当使用 onCompletionExceptionHandler 时,我可以拦截该异常,但是捕获是在与文件连接的Exchange对象已经发送到目标ActiveMQ之后发生的。

是否有一种方法可以防止Camel首先提交事务或回滚事务,以使消息不发送到AMQ? Camel 2.17.2中存在此行为

1 个答案:

答案 0 :(得分:0)

让我们研究不同的消息传递方式:

  • 至少一次-消息传递到目标后,将从源中删除。同一封邮件可以发送多次。
    • 这就是你现在得到的。
  • 最多一次-邮件在传递到目标之前已从源中删除。数据可能会丢失。
    • 可能不是您想要的。
  • 恰好一次-消息将在传递到目标的同时从源中删除。
    • 圣杯。很难实现。

好,因此您基本上需要只一次语义。仅当在同一代理中的队列之间,数据库中的表之间或在本地磁盘上(或在同一“资源”内部)移动数据时,才能“实现”。

当您有多个协议/资源时,这几乎是不可能的,或者至少非常困难。有一些方法可以使用分布式事务处理协调器(例如Windows中的MSDTC或Java中的Atomikos)使用“两阶段提交”事务在某种程度上确保一次交付。这些将仅支持事务性资源,例如队列和数据库,而不支持文件系统,例如SMB。

另一种方法是使用sagas-pattern。但是,在这种情况下,这种模式可能有点过大。

那该怎么办?好吧-我可以想到至少一种方法:

Idempotent consumer pattern。这使Camel将每个消息的副本(或至少一个键,例如文件名)保存在内存中,以确保没有单个消息被发送一次以上。

// Something like this
from("smb://someplace?&idempotentKey=${file:name}&idempotent=true")
. // Whatnot
.to("activemq:queue:foobar");

请注意,如果需要更持久(但也更复杂)的东西,可以配置幂等存储库以将条目保留在数据库,磁盘或其他多个地方。