消息驱动的bean和超时中长时间运行的任务

时间:2015-04-15 02:14:14

标签: java ejb jms message-driven-bean tomee

我想使用MDB(小时)处理一些非常长时间运行的任务,但是MDB是由JMS支持的,它有一些超时(我认为大约需要10分钟)。

更糟糕的是,工作也是持久的。

由于我无法捕获MDB上的超时异常(可以吗?),我正在考虑手动处理JMS使用者的选项。手动处理它可以通过两种方式完成:同步或异步。

异步我会回到实现MessageListener的无状态bean,然后我就再也无法处理超时了。

同步,我想,我可以处理catch块中的超时,但是,如何在TomEE +内部实现一个实例/工作池/正在侦听队列,等待作业处理? (记住,这里的超时不是等待消息出现在队列中的时间,而是执行长时间运行任务的时间)

3 个答案:

答案 0 :(得分:3)

尝试分离消费JMS消息和长时间运行的处理任务

MDB可以从队列中获取消息并使用调用无状态会话bean Asynchronous Method Invocation

答案 1 :(得分:3)

为什么不将长时间运行的进程分解为单独的对象? > 如果有办法控制这些单独对象的池大小,它可能是一种方式。你想试试答案吗? : - )

您不希望随着时间的推移不受控制的对象增长?嗯......我可以看到你要去哪里。

我唯一能想到的是使用并发框架中的FixedThreadPool。产生一个线程来执行长时间运行的任务,并确保MDB在交付工作后立即返回。通过在测试环境中分析应用程序来控制线程池。

Weblogic和Websphere等应用程序服务器为您提供了类似WorkManager的复杂框架。

答案 2 :(得分:0)

JEE7中存在ManagedExecutorService来处理异步任务的执行。通过利用Future接口实现(请参阅FutureTask),任务也可以取消。以下是一个示例,不要将其复制1:1并在生产中使用它。 UUID的未来地图中的内存泄漏永远不会被清除。

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.RunnableFuture;

import javax.annotation.Resource;
import javax.enterprise.concurrent.ManagedExecutorService;
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class AsyncTaskManager {

    @Resource
    private ManagedExecutorService mes;

    private Map<String, Future> futureByUUID = new ConcurrentHashMap<>();

    /**
     * Launch the provided Future implemented task.
     * @param runnable The runnable implementation to execute.
     * @param <R> The type of the task result returned.
     * @return The UUID that the executing ask is mapped to.
     */
    public <R> String launch (RunnableFuture<R> runnable) {
        String uuid = UUID.randomUUID().toString();
        mes.submit(runnable);
        futureByUUID.put(uuid, runnable);
        return uuid;
    }

    /**
     * Retrieve a future instance by it's UUID.
     * @param uuid The uuid of the future.
     * @param <T> The type of the future's result.
     * @return The future instance.
     */
    @SuppressWarnings("unchecked")
    public <T> Future<T> getByUUID (String uuid) {
        return (Future<T>)futureByUUID.get(uuid);
    }
}

有一整套接口和类可以组合在一起,以改变执行程序服务中任务的行为。例如,ManagedTask接口可以访问其中一些行为。

ManagedExecutorService用于MGolovanov的答案中提到的@Asynchronous EJB方法注释。任务创建和Future实例创建由EJB框架处理。