繁体   English   中英

您能以编程方式更改Java嵌入式代理中队列的“死信”处理吗?

[英]Can you programmatically alter a queue's “dead letter” handling in a Java embedded broker?

背景

在高级别,我有一个Java应用程序,其中某些事件应该触发当前用户采取的某个操作。 但是,事件可能非常频繁,并且操作始终相同。 因此,当第一个事件发生时,我想在不久的将来安排行动(例如5分钟)。 在该时间窗口期间,后续事件不应采取任何操作,因为应用程序发现已经安排了操作。 一旦计划的操作执行,我们将返回步骤1,下一个事件将再次开始循环。

我的想法是通过在应用程序本身内嵌入内存中的ActiveMQ实例来实现这种过滤和限制机制(我不关心队列持久性)。

我相信JMS 2.0支持延迟传送的概念,延迟消息位于“暂存队列”中,直到传送到真实目的地为止。 但是,我也相信ActiveMQ还不支持JMS 2.0规范......所以我正在考虑模仿生存时间(TTL)值和死信队列(DLQ)处理的相同行为。

基本上,我的消息生成器代码会将消息放在虚拟登台队列上,消费者从中没有任何东西 消息将以5分钟的TTL值放置,并在到期时ActiveMQ将它们转储到DLQ中。 这是我的消息消费者实际消费消息的队列。

我认为我不想实际使用“默认”DLQ,因为我不知道ActiveMQ可能会在那里转储哪些与我的应用程序代码完全无关的内部事物。 所以我认为我的虚拟登台队列最好有自己的自定义DLQ。 我只看过一页讨论DLQ配置的ActiveMQ文档,它只针对独立的ActiveMQ安装(不是嵌入在应用程序中的内存代理)的XML配置文件。

是否可以在运行时以编程方式为嵌入式ActiveMQ实例中的队列配置自定义DLQ?

如果你认为我走错了路,我也有兴趣听听其他建议。 我对JMS比AMQP更熟悉,所以我不知道Qpid或其他一些Java嵌入式AMQP代理是否更容易。 无论Apache Camel究竟是什么(!),我相信它应该在这类事情上表现出色,但这种学习曲线对于这个用例来说可能是彻底的过度杀伤力。

虽然你担心Camel对于这个用例可能是一个严重的过度杀伤,但我认为ActiveMQ对于你所描述的用例来说已经严重过度。

您希望在事件发生5分钟后安排事情发生,并且只消耗第一个事件并忽略第一个事件和5分钟之间的所有事件,对吗? 为什么不从现在开始通过ScheduledExecutorService或您喜欢的调度机制安排处理方法5分钟,并将事件保存在HashMap<User, Event>成员变量中。 如果在处理方法触发之前有更多事件进入该用户,您将看到已经存储了一个事件而没有存储新事件,因此您将忽略除第一个之外的所有事件。 在处理方法结束时,从HashMap删除此用户的事件,然后将存储和计划下一个要进入的事件。

运行ActiveMQ只是为了获得这种行为似乎比你需要的更多。 如果没有,你能解释一下原因吗?

编辑:

如果您沿着这条路走下去,请不要使用消息TTL来使您的消息过期; 让(唯一的)消费者将它们读入内存并使用上述内存解决方案仅每5分钟处理一次(最多)一批。 要么具有带有消息选择器的单个队列,要么使用动态队列,每个用户一个。 你不需要DLQ来实现延迟,即使你可以做到这一点,它也不会给你批处理所有功能,所以你每5分钟只运行一次。 这不是你想要贬低的道路,即使你弄清楚如何。

一个简单的解决方案是跟踪并发结构中的挂起操作,并使用ScheduledExecutorService来执行它们:

private static final Object RUNNING = new Object();
private final ConcurrentMap<UserId, Object> pendingActions = 
    new ConcurrentHashMap<>();
private ScheduledExecutorService ses = Executors.newScheduledThreadPool(10);


public void takeAction(final UserId id) {
    Object running = pendingActions.putIfAbsent(id, RUNNING);  // atomic
    if(running == null) {                // no pending action for this user
        ses.schedule(new Runnable() {
            @Override
            public void run() {
                doWork();
                pendingActions.remove(id);
            }
        }, 5, TimeUnit.MINUTES);
    }
}

使用Camel可以使用带有参数completionIntervalAggregator组件轻松实现,因此每隔五分钟就可以检查列表聚合消息是否为空,如果它没有向负责用户操作的路由发送消息并清空列表。 您确实需要维护整个交换列表,只需要维护状态(计划用户行为与否)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM