java - 长轮询 10 秒后 Tomcat 7 服务器错误

标签 java spring-mvc tomcat7 long-polling internal-server-error

我正在尝试在 Java 网络应用程序中实现长轮询。该应用程序是使用 Spring MVC 3.2 编写的,我使用了 DeferredResult 对象(它代表 Servlet 3.0 异步响应功能)。

问题是,在使用 DeferredResult 时,每次发送请求时,我都会在 10 秒后收到内部服务器错误(代码 500)。预期结果是 30 秒后的文本数据。我的应用程序日志中没有任何内容,Tomcat 日志中也没有任何内容,但在 FireFox 网络监视器中我看到了这个 500 错误。

另一方面,当我发送同步请求并在服务器中保持 30 秒时,它会成功完成。

谁能帮我解决这个问题?

本文末尾有一个测试应用程序下载链接。这是一个 Maven 应用程序。

这是我的应用程序代码:

响应 Controller .java

@Controller
@RequestMapping("responses")
public class ResponseController {

    @Autowired
    private ResponseService messagesService;

    @RequestMapping(value="/async", method=RequestMethod.GET)
    @ResponseBody
    public DeferredResult<String> getAsyncUpdate() {
        return messagesService.getAsyncUpdate();
    }

    @RequestMapping(value="/sync", method=RequestMethod.GET)
    @ResponseBody
    public String getSyncUpdate() {
        return messagesService.getSyncUpdate();
    }

}

响应服务.java

@Service
public class ResponseService {

    private DeferredResult<String> deferredResult;

    public DeferredResult<String> getAsyncUpdate(){
        deferredResult = new DeferredResult<String>();
        return deferredResult;
    }

    public String getSyncUpdate(){
        long startTime = System.currentTimeMillis();
        while( System.currentTimeMillis() - startTime <30000){

        }
        return "RESULT";
    }

    @Scheduled(fixedDelay=500)
    public void refresh(){
        if(deferredResult != null){
            long startTime = System.currentTimeMillis();
            while( System.currentTimeMillis() - startTime <30000){

            }
            deferredResult.setResult("RESULT");
        }
    }

}

mvc-dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/mvc     
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
        http://www.springframework.org/schema/task 
        http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <context:component-scan base-package="pl.prv.mra.test.app" />
    <context:annotation-config/>

    <aop:aspectj-autoproxy/>

    <mvc:annotation-driven >
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
        </mvc:message-converters>
    </mvc:annotation-driven>

    <task:annotation-driven/>

    <mvc:resources location="/resources/**" mapping="/resources/**"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

JQuery 异步响应请求

$.ajax({
    url : "responses/async",
    type : "GET",
    timeout : 60000,
    dataType : "json",
    success : function(){
        alert('SUCCESS');
    },
    error : function(){
        alert('FAILURE');
    }
});

JQuery 请求同步响应

$.ajax({
    url : "responses/sync",
    type : "GET",
    timeout : 60000,
    dataType : "json",
    success : function(){
        alert('SUCCESS');
    },
    error : function(){
        alert('FAILURE');
    }
});

网络.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <display-name>test-app</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <async-supported>true</async-supported>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

Tomcat server.xml 文件

<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.core.AprLifecycleListener"
        SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JasperListener" />
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

    <GlobalNamingResources>
        <Resource name="UserDatabase" auth="Container"
            type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved"
            factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
            pathname="conf/tomcat-users.xml" />
    </GlobalNamingResources>

    <Service name="Catalina">

        <Connector port="8080" protocol="HTTP/1.1"
            connectionTimeout="20000" redirectPort="8443" />

        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

        <Engine name="Catalina" defaultHost="localhost">

            <Realm className="org.apache.catalina.realm.LockOutRealm">
                <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                    resourceName="UserDatabase" />
            </Realm>

            <Host name="localhost" appBase="webapps" unpackWARs="true"
                autoDeploy="true">

                <Valve className="org.apache.catalina.valves.AccessLogValve"
                    directory="logs" prefix="localhost_access_log." suffix=".txt"
                    pattern="%h %l %u %t &quot;%r&quot; %s %b" />

            </Host>
        </Engine>
    </Service>
</Server>

我的环境配置

  • 操作系统:Linux Mint 16

  • 服务器:Apache Tomcat 7.0.55

  • Java:Java 1.7.0_67

Test application download link

更新 1


这是一个响应数据:

响应 header :

连接:“关闭”

内容长度:“0”

日期:“2014 年 10 月 27 日星期一 19:48:10 GMT”

服务器:“Apache-Coyote/1.1”

更新 2


这是我的应用程序日志。我已将日志记录级别配置为全部。不幸的是,它们根本没有错误。 (我对 tomcat 日志做了同样的结果):

2014-11-01 15:33:09 DEBUG RequestMappingHandlerMapping:220 - Looking up handler method for path /responses/async
2014-11-01 15:33:09 TRACE RequestMappingHandlerMapping:264 - Found 1 matching mapping(s) for [/responses/async] : [{[/responses/async],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}]
2014-11-01 15:33:09 DEBUG RequestMappingHandlerMapping:227 - Returning handler method [public org.springframework.web.context.request.async.DeferredResult<java.lang.String> pl.prv.mra.test.app.controllers.ResponseController.getAsyncUpdate()]
2014-11-01 15:33:09 DEBUG DefaultListableBeanFactory:246 - Returning cached instance of singleton bean 'responseController'
2014-11-01 15:33:09 TRACE DispatcherServlet:1122 - Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@7e036b3]
2014-11-01 15:33:09 DEBUG DispatcherServlet:912 - Last-Modified value for [/test-app/responses/async] is: -1
2014-11-01 15:33:09 TRACE HandlerMethod:129 - Invoking [getAsyncUpdate] method with arguments []
2014-11-01 15:33:09 TRACE HandlerMethod:135 - Method [getAsyncUpdate] returned [org.springframework.web.context.request.async.DeferredResult@4810881c]
2014-11-01 15:33:09 TRACE HandlerMethodReturnValueHandlerComposite:78 - Testing if return value handler [org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler@2a426218] supports [org.springframework.web.context.request.async.DeferredResult<java.lang.String>]
2014-11-01 15:33:09 TRACE HandlerMethodReturnValueHandlerComposite:78 - Testing if return value handler [org.springframework.web.method.annotation.ModelMethodProcessor@6c362b54] supports [org.springframework.web.context.request.async.DeferredResult<java.lang.String>]
2014-11-01 15:33:09 TRACE HandlerMethodReturnValueHandlerComposite:78 - Testing if return value handler [org.springframework.web.servlet.mvc.method.annotation.ViewMethodReturnValueHandler@5856cf4c] supports [org.springframework.web.context.request.async.DeferredResult<java.lang.String>]
2014-11-01 15:33:09 TRACE HandlerMethodReturnValueHandlerComposite:78 - Testing if return value handler [org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor@2b43b3e3] supports [org.springframework.web.context.request.async.DeferredResult<java.lang.String>]
2014-11-01 15:33:09 TRACE HandlerMethodReturnValueHandlerComposite:78 - Testing if return value handler [org.springframework.web.servlet.mvc.method.annotation.CallableMethodReturnValueHandler@deae877] supports [org.springframework.web.context.request.async.DeferredResult<java.lang.String>]
2014-11-01 15:33:09 TRACE HandlerMethodReturnValueHandlerComposite:78 - Testing if return value handler [org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler@3943e3c4] supports [org.springframework.web.context.request.async.DeferredResult<java.lang.String>]
2014-11-01 15:33:10 DEBUG WebAsyncManager:429 - Concurrent handling starting for GET [/test-app/responses/async]
2014-11-01 15:33:10 TRACE DispatcherServlet:1028 - Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@655d2842
2014-11-01 15:33:10 DEBUG DispatcherServlet:963 - Leaving response open for concurrent processing
2014-11-01 15:33:10 TRACE XmlWebApplicationContext:332 - Publishing event in WebApplicationContext for namespace 'mvc-dispatcher-servlet': ServletRequestHandledEvent: url=[/test-app/responses/async]; client=[127.0.0.1]; method=[GET]; servlet=[mvc-dispatcher]; session=[55143812B6586F66C0001D3F41B1947C]; user=[null]; time=[13ms]; status=[OK]
2014-11-01 15:33:10 TRACE XmlWebApplicationContext:332 - Publishing event in Root WebApplicationContext: ServletRequestHandledEvent: url=[/test-app/responses/async]; client=[127.0.0.1]; method=[GET]; servlet=[mvc-dispatcher]; session=[55143812B6586F66C0001D3F41B1947C]; user=[null]; time=[13ms]; status=[OK]

最佳答案

好的。我找到了解决方案。

在 Tomcat 配置中(在 server.xml 文件中)有一个 HTTP/1.1 连接器。我认为 connectionTimeout 参数定义了每个连接的超时,但它没有。

对于异步连接(就像我的情况),有一个名为 asyncTimeout 的单独参数.它的默认值为 10 秒。

这样设置:

<Connector port="8080" protocol="HTTP/1.1" asyncTimeout="60000" connectionTimeout="20000" redirectPort="8443" />

解决了我的问题。

关于java - 长轮询 10 秒后 Tomcat 7 服务器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26571994/

相关文章:

java - Tomcat 7 "SEVERE: A child container failed during start"

java - 使用 java config 在 Spring 应用程序中的 Web 项目之外单独存储属性

java - 如何运行多模块maven应用程序?

java ews api - 网络凭据?

java - 在 CodingBat 上为 2 个字符串的 substring() 逻辑苦苦挣扎

java - JScrollPane - 它如何显示 JTable 标题?

java - 如何使用 spring mvc 将图像上传到 webapp/resources/images 目录?

java - spring mvc HTTP状态404基本启动

java - 如何将tomcat web应用迁移到jetty

java - Spring boot 无法访问多个数据源