Reputation: 1829
I am using Wicket with an embedded Jetty webserver. The application is using websockets, therefore the Jetty setup looks the following:
FilterHolder filterHolder = new FilterHolder(Jetty9WebSocketFilter.class);
filterHolder.setInitParameter("applicationClassName", "MyApplication");
filterHolder.setInitParameter("filterMappingUrlPattern", "/*");
WebAppContext context = new WebAppContext();
context.setResourceBase(".");
context.addFilter(filterHolder, "/*", null);
context.addServlet(DefaultServlet.class, "/*");
Server server = new Server(8083);
server.setHandler(context);
try {
server.start();
} catch (Exception e) {
e.printStackTrace();
}
Everything works fine, besides the websocket timeout. Research showed that Jetty's websocket connections time out, although this is not common for webservers.
After researching I stumbled upon the following init parameter, that I now pass to my filterHolder
:
filterHolder.setInitParameter("maxIdleTime", "5000");
And apparently this parameter does something - because now the timeout occurs notably faster than before, exactly after 5 seconds.
But I couldn't figure out how I can disable the timeout completely. Using -1
, 0
or even Integer.MIN_VALUE
instead of 5000
does nothing, there is still a timeout after a while. The documentation I found says nothing about an according value.
What init parameter can I use to disable the websocket timeout? Or do I have to stick with setting the timeout to some ridiculously high value?
Upvotes: 1
Views: 2028
Reputation: 49452
Jetty 9.1 has its own WebSocketUpgradeFilter
, use that one, and then modify the default policy's idle timeout.
Example:
package jetty.websocket;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
import org.eclipse.jetty.websocket.server.pathmap.ServletPathSpec;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
public class JettyWebSocketViaFilter
{
@WebSocket
public static class EchoSocket
{
@OnWebSocketMessage
public void onMessage(Session session, String msg)
{
session.getRemote().sendStringByFuture(msg);
}
}
public static class EchoCreator implements WebSocketCreator
{
private EchoSocket echoer = new EchoSocket();
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
{
return echoer;
}
}
public static void main(String[] args)
{
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
// Setup the basic application "context" for this application at "/"
// This is also known as the handler tree (in jetty speak)
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
// Add the websocket filter
WebSocketUpgradeFilter wsfilter = WebSocketUpgradeFilter.configureContext(context);
wsfilter.getFactory().getPolicy().setIdleTimeout(5000);
wsfilter.addMapping(new ServletPathSpec("/"),new EchoCreator());
// The filesystem paths we will map
String staticRoot = "src/main/webapp/websocket/protocol";
ServletHolder holderDefault = new ServletHolder("default",DefaultServlet.class);
holderDefault.setInitParameter("resourceBase",staticRoot);
holderDefault.setInitParameter("dirAllowed","true");
context.addServlet(holderDefault,"/");
try
{
server.start();
server.join();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
}
}
Timeouts in Jetty with WebSockets:
Since WebSocket is an upgraded HTTP/1.1 request you have essentially 2 timeouts to worry about.
First is the connector idle timeout, that will be used for the HTTP/1.1 initial portion of the incoming Upgrade request. This is configured at the server level, with the connector that it has. With Jetty, any value 0 or below is considered an infinite timeout.
Next, you have the websocket endpoint specific idle timeout. If it has a value greater than 0, then it is applied to already established connection's idle timeout (the one from the server side).
Some combinations and what it means ...
Server Connector IdleTimeout | WebSocket Endpoint IdleTimeout | Actual Timeout
------------------------------+--------------------------------+----------------
30,000 ms | -1 | 30,000 ms
30,000 ms | 10,000 ms | 10,000 ms
30,000 ms | 400,000 ms | 400,000 ms
500,000 ms | -1 | 500,000 ms
500,000 ms | 200 ms | 200 ms
-1 | -1 | (infinite)
-1 | 1,000 ms | 1,000 ms
You can think of the Server Connector IdleTimeout as a TCP level timeout, while the WebSocket endpoint timeout is an application level idle timeout.
Hope this helps.
Upvotes: 2