我使用 Spring MVC's DeferredResult 类导致 Tomcat 静默崩溃 [英] My use of Spring MVC's DeferredResult class causes Tomcat to crash silently

查看:29
本文介绍了我使用 Spring MVC's DeferredResult 类导致 Tomcat 静默崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 Spring MVC 3.2 代码(它使用 DeferredResult 类):

I have the following Spring MVC 3.2 code (it uses the DeferredResult class):

@RequestMapping(value = "getMessages", method = RequestMethod.GET, produces = "application/json")
    @ResponseBody
    public DeferredResult<List<Message>> getMessages(@RequestParam final Long senderId) {
        final Long recipientId = memberService.retrieveCurrentMember().getId();
        final String messageRequestKey = new StringBuilder().append(senderId).append(":").append(recipientId).toString();
        final DeferredResult<List<Message>> deferredResult = new DeferredResult<List<Message>>(null, Collections.emptyList());
        messageRequests.put(messageRequestKey, deferredResult);

        deferredResult.onCompletion(new Runnable() {
            @Override
            public void run() {
                messageRequests.remove(messageRequestKey);
            }
        });

        List<Message> unReadMessages = messageService.findUnreadMessages(senderId, recipientId);
        if (!unReadMessages.isEmpty()) {
            deferredResult.setResult(unReadMessages);
        }
        return deferredResult;
    }

此方法由 ajax 调用连续轮询,它系统地导致 Tomcat 在第 9 次方法调用时崩溃.请注意,Tomcat 崩溃时没有任何错误消息.

This method is polled continuously by an ajax call and it systematically causes Tomcat to crash upon the 9th method invocation. Note that Tomcat crashes without any error message.

如果有人能帮助我确定此代码表现出这种行为的原因,我将不胜感激,也许是给我提供有关如何调试应用程序/tomcat 的提示.

推荐答案

我尝试了您修改后的 mvc 聊天代码.

I tried your modified mvc-chat code.

有了它,我一登录就发出了一个 GET 请求,由于超时是 3 秒,它超时并且 GET 响应带有一个空的消息列表.客户端立即发出另一个 GET 请求作为响应,第二个 GET 挂在myService.someTransactionalMethod();"中.在对messageRepository.findAll();"的调用中!

with it, a GET request was issued as soon as I signed-in and since the timeout was 3sec, it timedout and the GET response came with an empty list of messages. The client immediately issued another GET request in response to this, and the second GET hung inside "myService.someTransactionalMethod();" in the call to "messageRepository.findAll();" !

如果我增加超时时间并让 GET 请求完成",则后续的 GET 请求能够正确调用启用 Tx 的方法.但是,如果请求超时",则在启用 Tx 的方法中会阻止后续 GET 请求(来自同一聊天客户端).(即清理问题).

If I increase the timeout and let the GET request 'complete', then a subsequent GET request is able to call the Tx-enabled method properly. But if a request 'timedout', a subsequent GET request (from the same chat client) is blocked in the Tx-enabled method. (i.e a problem with clean-up).

同样,当 GET 未完成并且发出并行 GET 时(例如,从另一个浏览器窗口),第二个 GET 会在启用 Tx 的方法中被阻止.

Similarly, when a GET is outstanding and a parallel GET is issued (say, from another browser window) the second GET gets blocked in the Tx-enabled method.

这似乎是 DeferredResult 与 OEMIV 过滤器语义交互的问题.在 Spring 论坛上提出这个问题,你做对了!

This seems a problem with the DeferredResult's interaction with OEMIV filter's semantics. You have done the right thing by raising this in the Spring forum !

Edit1:为了确认上述声明,我从 xml 中删除了 OEMIV 过滤器(并保留所有其他代码,包括 Tx 方法和 DeferredResult,保持不变)并且它没有任何问题.

To confirm the above claim, I removed the OEMIV filter from xml (and left ALL other code, including the Tx method and the DeferredResult, unchanged) and it worked without any issues.

Edit2:Rossen Stoyanchev 在 Spring 论坛上评论说:

Rossen Stoyanchev commented on the Spring forum that :

"On the initial request thread, the OEMIV filter acquires an EM instance, then the 
 controller is invoked, which in turn invokes the tx method. The tx method re-uses the 
 same EM instance. Then the controller method returns and the Servlet container thread 
 is exited, but OEMIV filter doesn't release the EM instance because it is aware of the 
 async processing.
 When the DeferredResult is set, a dispatch is made back to the container, hitting the 
 OEMIV filter and the DispatcherServlet once again. When that thread completes, OEMIV 
 filter will release the EM instance. Note that this is true even if the DeferredResult
 is set in the controller method.".

从上面可以看出,当异步请求超时时,OEMIV 过滤器要么不参与,要么即使参与,也没有机会释放它持有的 EM 实例.

From the above, it looks as if, when the async request times out, the OEMIV filter is either not getting involved and even if it does get involved it does not get a chance to release the EM instance that it holds.

这篇关于我使用 Spring MVC&amp;#39;s DeferredResult 类导致 Tomcat 静默崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆