【问题标题】:Jetty Websocket IdleTimeoutJetty Websocket IdleTimeout
【发布时间】:2017-12-06 12:38:33
【问题描述】:

我最近一直在使用 Jetty API (9.4.5 release) 开发带注释的 websockets,并与之聊天。

但是我遇到了一个问题,5 分钟后(我相信这是默认计时器),会话关闭(不是由于错误)。 我找到的唯一解决方案是在关闭事件时通知我的套接字并在新套接字中重新打开连接。

但是我在 stackOverflow 上看到,通过在 WebsocketPolicy 中设置 IdleTimeOut,我可以避免这个问题:

  1. 例如,我尝试设置为 3600000,但行为根本没有改变

  2. 我也尝试将其设置为-1,但出现以下错误:IdleTimeout [-1] must be a greater than or equal to 0

    private ServletContextHandler setupWebsocketContext() {
        ServletContextHandler websocketContext = new AmosContextHandler(ServletContextHandler.SESSIONS |  ServletContextHandler.SECURITY);
    
        WebSocketHandler socketCreator = new WebSocketHandler(){
            @Override
            public void  configure(WebSocketServletFactory factory){    
                factory.getPolicy().setIdleTimeout(-1);
                factory.getPolicy().setMaxTextMessageBufferSize(MAX_MESSAGE_SIZE);
                factory.getPolicy().setMaxBinaryMessageBufferSize(MAX_MESSAGE_SIZE);
                factory.getPolicy().setMaxTextMessageSize(MAX_MESSAGE_SIZE);
                factory.getPolicy().setMaxBinaryMessageSize(MAX_MESSAGE_SIZE);          
                factory.setCreator(new UpgradedSocketCreator());
    
    
            }
    
        };  
        ServletHolder sh = new ServletHolder(new WebsocketChatServlet());  
        websocketContext.addServlet(sh, "/*");  
        websocketContext.setContextPath("/Chat");
        websocketContext.setHandler(socketCreator);
        websocketContext.getSessionHandler().setMaxInactiveInterval(0);
        return websocketContext;
    }
    

我还尝试通过调用session.getpolicy.setIdleTimeOut() 直接在OnConnect 事件中更改策略,但我没有注意到任何结果。

这是预期的行为还是我遗漏了什么?感谢您的帮助。

编辑:

登录关闭: 客户端:

2017-07-03T12:48:00.552 DEBUG   HttpClient@179313750-scheduler  Ignored idle endpoint SocketChannelEndPoint@2fb4b627{localhost/127.0.0.1:5080<->/127.0.0.1:53835,OPEN,fill=-,flush=-,to=1/300000}{io=0/0,kio=0,kro=1}->WebSocketClientConnection@e0198ece[ios=IOState@3ac0ec79[CLOSING,in,!out,close=CloseInfo[code=1000,reason=null],clean=false,closeSource=LOCAL],f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[CLIENT,validating],p=Parser@65c4d838[ExtensionStack,s=START,c=0,len=187,f=null]]

服务器端:

 2017-07-03T12:48:00.595    DEBUG   Idle pool thread    onClose WebSocketServerConnection@e0033d54[ios=IOState@10d40dca[CLOSED,!in,!out,finalClose=CloseInfo[code=1000,reason=null],clean=true,closeSource=REMOTE],f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[SERVER,validating],p=Parser@317213f3[ExtensionStack,s=START,c=0,len=2,f=CLOSE[len=2,fin=true,rsv=...,masked=true]]]<-SocketChannelEndPoint@690dfbfb'{'/127.0.0.1:53835<->/127.0.0.1:5080,CLOSED,fill=-,flush=-,to=1/360000000}'{'io=0/0,kio=-1,kro=-1}->WebSocketServerConnection@e0033d54[ios=IOState@10d40dca[CLOSED,!in,!out,finalClose=CloseInfo[code=1000,reason=null],clean=true,closeSource=REMOTE],f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[SERVER,validating],p=Parser@317213f3[ExtensionStack,s=START,c=0,len=2,f=CLOSE[len=2,fin=true,rsv=...,masked=true]]]
2017-07-03T12:48:00.595 DEBUG   Idle pool thread    org.eclipse.jetty.util.thread.Invocable$InvocableExecutor@4f13dee2 invoked org.eclipse.jetty.io.ManagedSelector$$Lambda$193/682154970@551e133a
2017-07-03T12:48:00.595 DEBUG   Idle pool thread    EatWhatYouKill@6ba355e4/org.eclipse.jetty.io.ManagedSelector$SelectorProducer@7b1559f1/PRODUCING/0/1 produce exit
2017-07-03T12:48:00.595 DEBUG   Idle pool thread    ran EatWhatYouKill@6ba355e4/org.eclipse.jetty.io.ManagedSelector$SelectorProducer@7b1559f1/PRODUCING/0/1
2017-07-03T12:48:00.595 DEBUG   Idle pool thread    run EatWhatYouKill@6ba355e4/org.eclipse.jetty.io.ManagedSelector$SelectorProducer@7b1559f1/PRODUCING/0/1
2017-07-03T12:48:00.595 DEBUG   Idle pool thread    EatWhatYouKill@6ba355e4/org.eclipse.jetty.io.ManagedSelector$SelectorProducer@7b1559f1/PRODUCING/0/1 run
2017-07-03T12:48:00.597 DEBUG   Idle pool thread    127.0.0.1 has disconnected ! 

2017-07-03T12:48:00.597 DEBUG   Idle pool thread    Disconnected:  127.0.0.1 (127.0.0.1)  (statusCode= 1,000 , reason=null) 

【问题讨论】:

  • 您可以发布您的日志吗?如果套接字被另一端关闭,您通常会收到某种错误。保活设置也可能会影响
  • 我将编辑评论以添加客户端和服务器端的日志。但是我没有在策略中找到任何 keepalive 参数。这是 Jetty Websocket API 中的东西吗?
  • 这个答案可能对stackoverflow.com/questions/44882256/…有帮助

标签: java session websocket timeout jetty


【解决方案1】:

注解@WebSocket 有选项:

int maxIdleTime() default -2;

其实还不清楚是什么意思。

如果你检查实现,你会发现:

if (anno.maxIdleTime() > 0)
{
this.policy.setIdleTimeout(anno.maxIdleTime());
}

方法实现:

/**
 * The time in ms (milliseconds) that a websocket may be idle before closing.
 * 
 * @param ms
 *            the timeout in milliseconds
 */
public void setIdleTimeout(long ms)
{
    assertGreaterThan("IdleTimeout",ms,0);
    this.idleTimeout = ms;
}

最后:

/**
 * The time in ms (milliseconds) that a websocket may be idle before closing.
 * <p>
 * Default: 300000 (ms)
 */
private long idleTimeout = 300000;

结论:负值应用默认行为(300000 毫秒)。您需要根据您的业务价值配置“idleTimeout”。

PS:解决了我的问题:

@WebSocket(maxIdleTime = Integer.MAX_VALUE)

【讨论】:

  • 超长空闲超时,或无限空闲超时,在有许多用户的生产机器上很少是一个好主意。 (如果这不适用于您,请继续设置超长空闲超时)
  • 大部分是对的。就我而言,它是网络摄像头视频流。打开/关闭连接是单独的逻辑。
【解决方案2】:

带注释的 WebSocket 在注释中有自己的超时设置。

@WebSocket(maxIdleTime=30000)

【讨论】:

  • 感谢 Joakim 的回答,它有效!我还可以将 maxIdleTime 设置为 -1 以实现无限保活计时器吗?它似乎不起作用,无论如何我可以将 IdleTime 设置得足够长,这样问题就解决了。
  • 请注意,ServerConnector(s) 也可能具有 IdleTimeout 设置,这可能会推翻 WebSocket 空闲超时设置。
  • @GérardBinkhorst WebSocket 空闲超时覆盖此 WebSocket 连接的 ServerConnector & Channel & EndPoint 的空闲超时。
  • 我的评论没有明确表述。假设 10 秒的连接器空闲超时将在 10 秒后空闲超时 websocket,即使 websocket 空闲超时值设置得更大。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-03
  • 2015-06-24
  • 2015-03-08
相关资源
最近更新 更多