Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetty Websocket IdleTimeout

I've been working on annotated websockets lately, with the Jetty API (9.4.5 release) , and made a chat with it.

However i got an issue, after 5 minutes (which i believe is the default timer), the session is closed (it is not due to an error). The only solution I've found yet, is to notify my socket On closing event and reopen the connection in a new socket.

However i've read on stackOverflow, that by setting IdleTimeOut in the WebsocketPolicy, i could avoid the issue:

  1. I've tried setting to 3600000 for instance, but the behavior does not change at all

  2. I also tried to set it to -1 but i get the following error: 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;
    }
    

I've also tried to change the policy directly in the OnConnect event, by using the call session.getpolicy.setIdleTimeOut(), but I haven't noticed any results.

Is this an expected behavior or am I missing something? Thanks for your help.

EDIT:

Log on the closure: Client Side:

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]]

Server side:

 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) 
like image 309
Youri Avatar asked Jul 03 '17 09:07

Youri


2 Answers

Annotated WebSockets have their own timeout settings in the annotation.

@WebSocket(maxIdleTime=30000)
like image 50
Joakim Erdfelt Avatar answered Oct 14 '22 03:10

Joakim Erdfelt


The annotation @WebSocket has option:

int maxIdleTime() default -2;

In fact it's not clear what does it mean.

If you check implementation, you can find:

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

method implementation:

/**
 * 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;
}

and finally:

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

Conclusion: negative value apply default behavior (300000 ms). You need to configure 'idleTimeout' according your business value.

PS: solved my case with:

@WebSocket(maxIdleTime = Integer.MAX_VALUE)
like image 30
ilu Avatar answered Oct 14 '22 04:10

ilu