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

时间:2016-01-13 10:16:36

标签: java java-ee asynchronous ejb websphere

我需要执行两项任务,即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会产生影响。

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

我的问题是如何才能实现我想在这里实现的目标。

2 个答案:

答案 0 :(得分:2)

我认为@AccessTimeout正是您所寻找的。我看到一个例子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);方法。您还需要返回Future,而不仅仅是将其设置为无效。

我希望这适合您的用例,因为您需要调用.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);
    }

}

答案 1 :(得分:2)

另一种方法是增加管理控制台中“EJB异步方法调用设置”的“工作请求队列大小”。这是一个队列,在实际的线程池本身之前,所以这可能会给你带来更多的时间。

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