【问题标题】:Tomcat 7 server error after 10 seconds when long polling长轮询时 10 秒后 Tomcat 7 服务器错误
【发布时间】:2014-12-21 17:06:17
【问题描述】:

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

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

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

谁能帮我解决这个问题?

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

这是我的应用代码:

ResponseController.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();
    }

}

ResponseService.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');
    }
});

web.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


这是一个响应数据:

响应标头:

连接:“关闭”

内容长度:“0”

日期:“格林威治标准时间 2014 年 10 月 27 日星期一 19:48:10”

服务器:“Apache-Coyote/1.1”

更新 2


这是我的应用程序日志。我已将日志记录级别配置为 ALL。不幸的是,它们根本没有错误。 (我对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]

【问题讨论】:

  • 网络选项卡的响应区域应该有错误描述。在这里显示。
  • 我已经用响应头更新了我的帖子。
  • 请更新响应正文。
  • 没有。如您所见,内容长度为 0。
  • 错误 500 表示内部服务器错误,可以是任何东西。错误描述应该在某处报告。请配置您的日志,以便它显示错误描述并将其粘贴到此处。

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


【解决方案1】:

我遇到了同样的问题,但 asyncTimeout 还不够... 我正在使用 Zuul 反向代理我的 api,我忘记添加 zuul.host.connect-timeout-millis 和 zuul.host.socket-timeout-millis,你的解决方案 + 这个解决了我的问题。

【讨论】:

    【解决方案2】:

    好的。我找到了解决办法。

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

    对于异步连接(如我的例子),有一个单独的参数称为asyncTimeout。默认值为 10 秒。

    这样设置:

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

    解决了我的问题。

    【讨论】:

      猜你喜欢
      • 2013-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-28
      • 2019-02-10
      • 1970-01-01
      • 2014-05-30
      相关资源
      最近更新 更多