I'm using SockJS + stomp client in angular(1.5.x) to establish websocket with a spring (mvc) server. All works fine except this: if I kill the server, it takes up to two minutes for the stomp client to detect connection error on the browser. Is there a way to manage a much shorter (or immediate) timeout or throw an event as soon as the server died or is disconnected?
function socketService($rootScope, $q, $log, $timeout, URL) {
var listener = $q.defer(),
socket = {
client: null,
stomp: null
};
var reconnect = function() {
$log.info('Reconnecting');
$timeout(function() {
initialize();
}, 2000);
};
var getMessage = function(data) {
var message = JSON.parse(data), out = {};
out.message = message;
if (message.metadata) {
out.time = new Date(message.metadata.timestamp);
}
$log.info(out);
return out;
};
var startListener = function() {
$log.info('Connected');
socket.stomp.subscribe(URL.PROCESS_UPDATES, function(data) {
listener.notify(getMessage(data.body));
});
socket.stomp.subscribe(URL.CONTAINER_UPDATES, function(data) {
listener.notify(getMessage(data.body));
});
$rootScope.$broadcast('web_socket_event', 'CONNECTED');
};
var errorCallback = function (error) {
// Browser gets here 2 minutes after the server is killed. Seems like might be affected by the the xhr_streaming timeout
$rootScope.$broadcast('web_socket_event', 'DISCONNECTED');
reconnect();
};
return {
initialize: initialize,
receive: receive
};
function initialize() {
var header = {
'accept-version': 1.1
};
$log.info('Connecting');
// custom header to specify version.
socket.client = new SockJS(header, URL.ROOT + URL.UPDATES);
socket.client.debug = function(){};
socket.stomp.heartbeat.outgoing = 0;
socket.stomp.heartbeat.incoming = 2000;
socket.stomp = Stomp.over(socket.client);
socket.stomp.connect({}, startListener, errorCallback);
socket.stomp.onerror = errorCallback;
socket.stomp.onclose = reconnect;
};
function receive() {
return listener.promise;
};
}
**// browser console:**
Opening Web Socket...
stomp.js:145 Web Socket Opened...
stomp.js:145 >>> CONNECT
accept-version:1.1,1.0
heart-beat:0,2000
stomp.js:145 <<< CONNECTED
version:1.1
heart-beat:2000,0
stomp.js:145 connected to server undefined
stomp.js:145 check PONG every 2000ms
I'm not an expert in WS but based on our conversation through the question comments, and my understanding of WS it's clear that your server is negotiating a connection with NO heart-beats at all:
heart-beat 0,0
. The first 0 is the max time (in millis) that the client should expect no packets from the server at all (when this timeout elapses with no communication at all from either side the server should send a heartbeat frame), the 2nd 0 is the equivalent but from looked from the server perspective.You should set up your server to send a heartbeat periodically and also to expect a heartbeat from the client. This way you allow your server and client to have a better management on the WS connection resources and also you ensure that the connection doesn't get disconnected by the 'network' when applying stalled connection detection policies or by any other mechanism.
I don't know how you have set up your WS server but the below sample applies to a simple WS server in spring boot: