使用 EJB 异步方法的正确方法

Correct way to use EJB Asynchronous methods

我有两个任务需要执行,比如 task1task2,它们是同一业务流程的一部分。我必须在 task1 完成后向最终用户做出响应,因此必须将响应时间降至最低。

我目前的方法是执行 task1 并在 task1 完成后立即异步调用 task2 方法。 task2 很复杂,它的响应时间是我无法控制的,因为它有一些外部依赖性。

@Stateless
public class SessionBean1 {

    @Inject
    SessionBean2 sessionBean2;

    public void doTask1(){
        // task one stuff
        sessionBean2.doTask2();
    }

}



@Stateless
public class SessionBean2 {

    @Asynchronous
    public void doTask2(){
        // do task2 stuff
    }

}

在 websphere 8.0(使用的 EJB 容器)中,同步方法和异步方法由不同的线程池 运行。

我最初的假设是,即使 task2 表现不佳,task1 也不会产生任何影响,但很遗憾,事实并非如此。

如果task2表现不佳,异步线程池中的所有线程都会被占用。这将导致 task1 等待异步线程空闲,因此 task1 会产生影响。

webspherere 服务器日志中的消息: The request buffer for thread pool WorkManager.WebSphere_EJB_Container_AsynchMethods_Internal_WorkManager has reached its capacity

我的问题是什么是实现我在这里想要实现的目标的正确方法。

我觉得@AccessTimeout is what you are looking for. I see an example here 这将限制 .doTask2() 可以 运行 的时间并避免您的问题。

@Stateless
public class SessionBean1 {

    @Inject
    SessionBean2 sessionBean2;

    public void doTask1(){
        // task one stuff
        sessionBean2.doTask2();
    }

}

SessionBean2

@Stateless
public class SessionBean2 {
    @AccessTimeout(60000)//default timeunit is TimeUnit.MILLISECONDS
    @Asynchronous
    public void doTask2(){
        // do task2 stuff
    }

}

替代方案:

要限制异步进程可以占用的时间,请使用 handle.get(xx, TimeUnit.xx);方法。您还需要 return Future 而不仅仅是 void 才能使其正常工作。

我希望这适合您的用例,因为您需要调用 .get

@Stateless
public class SessionBean1 {

    @Inject
    SessionBean2 sessionBean2;

    public void doTask1(){
        // task one stuff
        Future<Void> handle = sessionBean2.doTask2();
        // do other stuff
        handle.get(10, TimeUnit.SECONDS);//If you want to block later

    }

}

SessionBean2

@Stateless
public class SessionBean2 {

    @Asynchronous
    public Future<Void> doTask2(){
        // do task2 stuff
        new AsyncResult<Void>(Void);
    }

}

另一种选择是在管理控制台中增加 "EJB asynchronous method invocation settings" 的 "Work request queue size"。这是一个队列,在实际线程池本身之前,因此这可能会给您争取更多时间。

理想情况下,这应该与上面建议的超时结合使用。