问题
当我的Web应用程序更新数据库中的项目时,它会通过Camel将包含项目ID的消息发送到ActiveMQ队列,其消费者将获得更新的外部服务(Solr)。外部服务独立于数据库读取。
我想要的是,如果Web应用程序发送另一条具有相同项目ID的消息,而旧的消息仍在队列中,则删除新消息以避免两次运行Solr更新。
在处理完更新请求并且具有该项目ID的消息不在队列中之后,应再次接受具有相同ID的新请求。
有没有办法让这项工作开箱即用?我真的很想放弃ActiveMQ并简单地将更新请求队列实现为具有唯一约束的数据库表,按时间戳或正在运行的插入ID排序。
到目前为止我尝试了什么
我已经在Stackoverflow上阅读了this和this页面。这些是那里提到的解决方案:
Camel中的幂等消费者:在这里,我可以指定一个表达式来定义构成重复的内容,但这也会阻止将来尝试发送相同的消息,即更新相同的项目。我只希望在它们仍在队列中时删除新的更新请求。
" ActiveMQ已经做重复检查,看看auditDepth
!":嗯,这看起来是一个好的开始,绝对最接近我的想要,但这会根据我无法设置的消息ID确定相等性。所以要么我找到了一种方法让ActiveMQ以某种方式生成此队列的消息ID 或我找到了一种方法来使审计内容看到我的项ID字段而不是消息ID。 (一个comment in my second link甚至建议使用"您在标题"上设置的明确定义的属性,但无法解释如何。)
编写一个自定义插件,如果它们与队列中已有的消息匹配,则会将传入消息重定向到deadletter队列。这似乎是目前为止提供的最完整的解决方案,但对于我认为是一项相当平凡且日常工作的任务,我感觉太过分了。
PS:我发现another SO page在没有答案的情况下问同样的事情。
答案 0 :(得分:3)
你想要的不是消息代理功能,在我之后重复,“消息代理不是数据库,消息代理不是数据库”,必要时重复。
代理的工作是从A点到B点可靠地获取消息。客户端通过消息选择器提供一些过滤功能,但这是最小的,主要用于仅保留单个客户端感兴趣的特定消息流入那里而不是其他一些客户可能负责处理的其他人。
如您所述,您的用例需要更具状态的数据库中心解决方案。创建一个代理插件来遍历队列以检查消息是重新发明轮子并且如果队列深度很大则容易出错,因为ActiveMQ可能甚至不会根据内存约束为您分页所有消息。