我正在编写一个使用Atmosphere插件的Grails应用程序。连接有效,但是每次我在浏览器中更新页面时,都会看到Web服务器添加了一个新的Daemon线程,此线程以后再也不会释放。
[线程数达到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 Tools Suite)。
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS91eXlPUy5qcGcifQ==” alt =“守护程序线程”>
如果解决方案不是简单的,我将感谢详细的分步说明或示例。
UPDATE:在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=[]}
....
您正在使用哪个Web服务器?听起来好像Web服务器没有检测到浏览器何时关闭连接。您可以在web.xml中添加以下超时检测器
org.atmosphere.cpr.CometSupport.maxInactiveActivity=30000 //30 seconds
我相信您的问题出在您的卸载事件中。 “ $(window).unload”。我至少在chrome中知道,您在unload或beforeunload事件中不能做很多事情。因此,您的浏览器可能永远不会触发unsubscribe()。
如果您查看Atmospheres jQuery pubsub示例,则可以在连接之前看到取消订阅的信息,函数connect(){unsubscribe();...
您可以编写一个循环来检查广播者,方法是通过推送无关紧要的数据来定期验证广播者(如果没有清理它们)。我需要更多地研究气氛,并希望有一个更好的解决方案。希望您可以在通过刷新创建新连接时清理线程,并在用户离开时让旧连接随会话过期。