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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34763961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:18:20  来源:igfitidea点击:

Correct way to use EJB Asynchronous methods

javajakarta-eeasynchronousejbwebsphere

提问by ares

I have two tasks that I need to perform say task1and task2which are a part of same business process. I have to give response to the end user when task1completes so it's response time have to be minimized.

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

My current approach is to perform task1and as soon as task1is finished, invoke task2method asynchronously. task2is complicated and it's response time is out of my control as it has some external dependency.

我目前的方法是执行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
    }

}

In websphere 8.0 (the EJB container in use) synchronous methods and asynchronous methods are run by different thread pools.

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

My initial assumption was that even if task2is performing badly, task1would have no impact, but sadly that's not true.

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

If task2is performing badly, all threads from asynchronous thread pool will be occupied. This will cause task1to wait for asynchronous threads to be free and hence task1has impact.

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

The message in websphrere server logs : The request buffer for thread pool WorkManager.WebSphere_EJB_Container_AsynchMethods_Internal_WorkManager has reached its capacity

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

My question is what would be a proper way to achieve what I'm trying to achieve here.

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

采纳答案by matt freake

Another alternative would be to increase the "Work request queue size" of the "EJB asynchronous method invocation settings" in the Admin Console. This is a queue, before the actual thread pool itself, so this might buy you some more time.

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

Ideally this should be used in combination with the timeouts suggested above.

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

回答by rjdkolb

I think @AccessTimeoutis what you are looking for. I see an example hereThis will limit the amount of time that .doTask2() can run and avoid your problem.

我认为@AccessTimeout正是您要找的。我在这里看到一个例子 这将限制 .doTask2() 可以运行的时间并避免您的问题。

@Stateless
public class SessionBean1 {

    @Inject
    SessionBean2 sessionBean2;

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

}

SessionBean2

会话Bean2

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

}

As an alternative :

作为备选 :

To limit the time the async process can take, use the handle.get(xx, TimeUnit.xx); method. You will also need to return Future and not just void to make it work.

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

I hope this suits your use case as you will need to call a .get

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

会话Bean2

@Stateless
public class SessionBean2 {

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

}