1

我正在编写一个使用 Atmosphere 插件的 Grails 应用程序。连接有效,但每次我在浏览器中更新页面时,我都会看到我的 Web 服务器添加了一个新的守护线程,该线程之后永远不会发布。

线程数达到 200 后,Web 服务器冻结。

似乎没有文档解释使用 Atmosphere 插件处理资源(断开连接)的正确方法是什么?

我的客户代码这样做:

var connectedEndpoint = null;

$(function() 
{
function callback(response)
{
    if (response.transport != 'polling' && response.state != 'connected' && response.state != 'closed') {
        if (response.status == 200) {
            eval(response.responseBody);
        }
    }
}

$.atmosphere.subscribe('${resource(dir: '/atmosphere/channel')}', callback, $.atmosphere.request = {transport: 'streaming'});
connectedEndpoint = $.atmosphere.response;

});

$(window).unload( function () 
{ 
    $.atmosphere.unsubscribe();
    connectedEndpoint = null;
});

我在服务器端使用大气处理程序;

package demo

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import org.atmosphere.cpr.AtmosphereHandler
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;

class DemoController implements AtmosphereHandler<HttpServletRequest, HttpServletResponse> {

@Override
public void destroy() {
    println "destroy"
}

@Override
public void onRequest( AtmosphereResource<HttpServletRequest, HttpServletResponse> event) throws IOException 
{
    event.suspend()
}

@Override
public void onStateChange( AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) throws IOException 
{
    if (event.isSuspended()) 
    {
        event.resource.response.writer.with {
            def message = event.message
            write "set${message.paramName}(\"${message.id}\",\"${message.value}\");"
            flush()
        }
    }
}
}

处理程序的destroy函数永远不会被调用!

下一张图片显示我有 23 个线程正在运行。当我启动我的应用程序时,其中大约有 6 个,每次按 F5 时都会添加它们!如果我禁用气氛,则不会添加新线程,因此此问题与气氛有关。(我在 Windows7 上使用 SpringSource 工具套件)。

守护线程

如果解决方案不是微不足道的,我将不胜感激详细的分步说明或示例。

更新:在 Tomcat 中部署后,每 20 秒出现以下错误:

Apr 02, 2012 2:35:15 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor host-manager.xml
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor manager.xml
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory docs
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory examples
Apr 02, 2012 2:35:17 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory ROOT
Apr 02, 2012 2:35:17 PM org.apache.coyote.http11.Http11AprProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Apr 02, 2012 2:35:17 PM org.apache.coyote.ajp.AjpAprProtocol start
INFO: Starting Coyote AJP/1.3 on ajp-8009
Apr 02, 2012 2:35:17 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 11401 ms
2012-04-02 14:41:17,122 [http-8080-39] ERROR cpr.AsynchronousProcessor  - failed
 to timeout resource AtmosphereResourceImpl{, hasCode-1035775543,
 action=org.atmosphere.cpr.AtmosphereServlet$Action@f2718e,
 broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
 cometSupport=org.atmosphere.container.TomcatCometSupport@107fff7,
 serializer=null,
 isInScope=true,
 useWriter=true,
 listeners=[]}
2012-04-02 14:42:15,034 [http-8080-69] ERROR cpr.AsynchronousProcessor  - failed
 to timeout resource AtmosphereResourceImpl{, hasCode-58082012,
 action=org.atmosphere.cpr.AtmosphereServlet$Action@ae4dd4,
 broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
 cometSupport=org.atmosphere.container.TomcatCometSupport@107fff7,
 serializer=null,
 isInScope=true,
 useWriter=true,
 listeners=[]}
2012-04-02 14:44:41,159 [http-8080-13] ERROR cpr.AsynchronousProcessor  - failed
 to timeout resource AtmosphereResourceImpl{, hasCode648226529,
 action=org.atmosphere.cpr.AtmosphereServlet$Action@507e61,
 broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
 cometSupport=org.atmosphere.container.TomcatCometSupport@107fff7,
 serializer=null,
 isInScope=true,
 useWriter=true,
 listeners=[]}

 ....
4

2 回答 2

1

您使用的是哪个网络服务器?听起来 Web 服务器没有检测到浏览器何时关闭连接。您可以在 web.xml 中添加以下超时检测器

org.atmosphere.cpr.CometSupport.maxInactiveActivity=30000 //30 seconds
于 2012-03-12T14:37:51.063 回答
0

我相信您的问题出在您的卸载事件中。“$(窗口)。卸载”。我知道至少在 chrome 中,你不能在 unload 或 beforeunload 事件中做太多事情。因此,您的浏览器可能永远不会触发 unsubscribe()。

如果您查看 Atmospheres jquery pubsub 示例,您可以在连接之前看到取消订阅,函数 connect() { unsubscribe(); ...

您可以编写一个循环来检查广播公司,方法是推送无关紧要的数据来定期验证广播公司(如果它们没有被清理)。我需要更多地研究气氛,并希望有更好的解决方案。希望您可以在通过刷新创建新连接时清理线程,并在用户离开时让旧连接与会话过期。

于 2012-04-23T16:21:42.670 回答