How do you quickly close a nonresponsive websocket in Java Spring Tomcat?

后端 未结 4 1111
鱼传尺愫
鱼传尺愫 2021-01-11 15:09

I have a real-time application with clients using websockets to connect with a Spring Framework server, which is running Spring Boot Tomcat. I want the server to quickly (wi

相关标签:
4条回答
  • 2021-01-11 15:17

    The approach I eventually took was to implement an application-layer ping-pong protocol.

    • The server sends a ping message with period p to the client.
    • The client responds to each ping message with a pong message.
    • If the server sends more than n ping messages without receiving a pong response, it generates a timeout event.
    • The client can also generate a timeout event if it does not receive a ping message in n*p time.

    There should be a much simpler way of implementing this using timeouts in the underlying TCP connection.

    0 讨论(0)
  • 2021-01-11 15:19

    ServletServerContainerFactoryBean simply configures the underlying JSR-356 WebSocketContainer through Spring configuration on startup. If you peek inside you'll see it's trivial.

    From what I can see in Tomcat code about the handling of maxSessionIdleTimeout, the WsWebSocketContainer#backgroundProcess() method runs every 10 seconds by default to see if there are expired sessions.

    I suspect also the pings you're sending from the server are making the session appear active, hence not helping with regards to the idle session timeout configuration.

    As to why Tomcat doesn't realize the client is disconnected sooner, I can't really say. In my experience if a client closes a WebSocket connection or if I kill the browser it's detected immediately. In any case that's more to do with Tomcat not Spring.

    0 讨论(0)
  • 2021-01-11 15:20

    As the question and the top-voted answer are quite old, wanted to add the easiest way to achieve the same with spring - websocket implementation.

    Refer section 4.4.8. Simple Broker

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
        private TaskScheduler messageBrokerTaskScheduler;
    
        @Autowired
        public void setMessageBrokerTaskScheduler(TaskScheduler taskScheduler) {
            this.messageBrokerTaskScheduler = taskScheduler;
        }
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {
    
            registry.enableSimpleBroker("/queue/", "/topic/")
                    .setHeartbeatValue(new long[] {10000, 20000})
                    .setTaskScheduler(this.messageBrokerTaskScheduler);
    
            // ...
        }
    }
    

    When returning the connect response frame, the websocket-server needs to send the hearbeat params to enable ping from the clientside.

    If you are using SOCKJS implementation on the clientside, then no additional code is needed to add align to PING/PONG implementation.

    0 讨论(0)
  • 2021-01-11 15:34

    Application Events may help you.

    PS: Annotation driven events

    PS2: I made an example project for you

    0 讨论(0)
提交回复
热议问题