2017-02-26 88 views
1

我正在使用角(1.5.x)中的SockJS + stomp客戶端與彈簧(mvc)服務器建立websocket。除此之外,所有的工作都可以正常工作:如果我終止了服務器,那麼stomp客戶端在瀏覽器上檢測連接錯誤需要兩分鐘的時間。有一種方法可以在服務器死亡或斷開連接後立即管理更短(或立即)的超時或拋出事件嗎?stompjs xhr_streaming超時

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 
+0

你可以發佈用於創建連接的javascript代碼,是你訂閱一個回調函數到連接錯誤事件? – artemisian

+0

@artemisian請參閱上面的代碼,謝謝! – user2994871

+0

請添加'socket.client.debug = function(msg){console.log(msg)};'並檢查心跳協商(在控制檯中搜索心跳)?如果在服務器斷開連接時打印任何消息 – artemisian

回答

2

我不是WS專家,但基礎上,通過問題的評論我們的談話,我WS的理解很明顯,你的服務器是在所有談判與NO心臟,跳動的連接:heart-beat 0,0 。第一個0是客戶端根本不需要來自服務器的數據包的最大時間(以毫秒爲單位)(當超時時間過去,服務器任何一方都沒有通信發送心跳幀時),第二個0是相當於從服務器的角度來看。

您應該設置您的服務器定期發送心跳,並期望來自客戶端的心跳。這樣,您可以讓服務器和客戶端更好地管理WS連接資源,並確保在應用停頓的連接檢測策略或任何其他機制時,連接不會被「網​​絡」斷開。

我不知道你是如何設置您的WS服務器,但下面的示例適用於一個簡單的WS服務器在春季啓動:

import org.springframework.beans.factory.annotation.Value; 
import org.springframework.messaging.simp.config.MessageBrokerRegistry; 
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 
import org.springframework.stereotype.Component; 
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; 
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; 

@Component 
public class WebSocketConfigurer extends AbstractWebSocketMessageBrokerConfigurer { 

    @Override 
    public void configureMessageBroker(MessageBrokerRegistry config) { 
     long heartbeatServer = 10000; // 10 seconds 
     long heartbeatClient = 10000; // 10 seconds 

     ThreadPoolTaskScheduler ts = new ThreadPoolTaskScheduler(); 
     ts.setPoolSize(2); 
     ts.setThreadNamePrefix("wss-heartbeat-thread-"); 
     ts.initialize(); 

     config.enableSimpleBroker("/topic") 
       .setHeartbeatValue(new long[]{heartbeatServer, heartbeatClient}) 
       .setTaskScheduler(ts); 
    } 

    @Override 
    public void registerStompEndpoints(StompEndpointRegistry registry) { 
     registry.addEndpoint("/my/ws/endpoint") 
       .setAllowedOrigins("*") 
       .withSockJS(); 
    } 
} 
+0

因此,爲了設置客戶端期望心跳,這是我可以通過stompJS/SockJS做的事情,或者它必須通過角度http協議? – user2994871

+0

客戶端發送心跳建議,但服務器將在心跳協商條款中有最後一個字。那麼你的春天配置誰將設置心跳計時 – artemisian

+1

因此,我已經有了所有的心跳東西連線和工作;但是在瀏覽器(Safari Technology Preview)控制檯上,我可以輸入以下錯誤:'不兼容SockJS!主站點使用:「1.1.2」,iframe:「1.0.0」。在ff/Chrome中,錯誤是:'握手響應之前關閉了websocket連接。'。這個錯誤是間歇性的。任何想法? – user2994871