【问题标题】:My use of Spring MVC's DeferredResult class causes Tomcat to crash silently我使用 Spring MVC 的 DeferredResult 类导致 Tomcat 静默崩溃
【发布时间】:2013-03-11 13:26:27
【问题描述】:

我有以下 Spring MVC 3.2 代码(它使用 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 崩溃时没有任何错误消息。

如果有人能帮助我确定这段代码出现这种行为的原因,我将不胜感激,或许可以给我有关如何调试应用程序/tomcat 的提示。

【问题讨论】:

  • 这对您来说仍然是个问题吗?如果是,您能否提供更多代码(例如,与 messageService 和 messageRequests 相关的代码)?
  • 嗨,文丹。是的,这对我来说仍然是个问题。我在 springsource 论坛上打开了一个帖子:here 带有一个示例应用程序。如果我能提供更多信息,请告诉我。

标签: tomcat servlets spring-mvc asynchronous


【解决方案1】:

我试过你修改后的mvc-chat code

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

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

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

这似乎是 DeferredResult 与 OEMIV 过滤器语义交互的问题。 您在 Spring 论坛上提出这个问题是正确的!

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

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

"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 实例。

【讨论】:

  • 非常感谢您对此进行调查。
猜你喜欢
  • 1970-01-01
  • 2013-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-11
  • 2012-07-29
  • 2014-08-25
  • 1970-01-01
相关资源
最近更新 更多