2016-08-30 11 views
7

我々はCONNECTフレーム渡していることをWebSocketを接続経由で春持っている:ハンドラが認め春STOMP WebSocketを介してスケジューリングしていないハートビート

CONNECT\naccept-version:1.2\nheart-beat:10000,10000\n\n\u0000 

は、新しいセッションを開始し、リターンより:

CONNECTED 
version:1.2 
heart-beat:0,0 

しかし、私たちは心拍動が欲しいので、WebSocketを開いたままにしておきます。 SockJSを使用しているではなく、です。

私は春のメッセージハンドラを通じて段階:それはheart-beat(ネイティブヘッダ)を取得

StompHeaderAccessor [headers={simpMessageType=CONNECT, stompCommand=CONNECT, nativeHeaders={accept-version=[1.2], heart-beat=[5000,0]}, simpSessionAttributes={}, simpHeartbeat=[[email protected], simpSessionId=46e855c9}] 

後ブローカーが認証した後、それは、注目すべきsimpHeartbeat=[[email protected], simpSessionId=46e855c9}]

メモリアドレスのように見えるものに設定します。

Processing CONNECT session=46e855c9(ここではsessionIdはsimpSessionIdとは異なります)

デバッグの前にTRACEを実行していたときに、「スケジューリングハートビート...」などの効果が得られましたが、今は表示されません。

何が起こっているのでしょうか?ハートビートを送信するために使用されSockJSタスクスケジューラ のスレッドプールから

SockJSタスクスケジューラの統計:

おかげ

私はdocumentationで説明を発見しました。 STOMPレベルでハートビート がネゴシエートされると、SockJSハートビートは無効になります。

SockJSのハートビートはSTOMPのハートビートと異なりますか?

答えて

5

はいSockJSのハートビートが異なります。基本的にSockJSプロトコルの同じ目的が、接続が「死んでいる」ように見えないようにして、プロキシがプロアクティブに閉じることができるようにすることです。より一般的には、ハートビートを使用すると、各側で接続の問題を事前に検出し、リソースをクリーンアップすることができます。

トランスポート層でSTOMPとSockJSを使用する場合、STOMPハートビートが使用されている場合、SockJSハートビートがオフになっている理由が両方ある必要はありません。しかし、ここではSockJSを使用していません。

設定は表示されていませんが、ハートビートを自動的に送信しないビルトインのシンプルなブローカーを使用していると思います。設定するときにハートビートを有効にするオプションが表示され、タスクスケジューラも設定する必要があります。

@Configuration 
@EnableWebSocketMessageBroker 
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { 

    @Override 
    public void registerStompEndpoints(StompEndpointRegistry registry) { 
     // ... 
    } 

    @Override 
    public void configureMessageBroker(MessageBrokerRegistry registry) { 
     registry.enableStompBrokerRelay(...) 
       .setTaskScheduler(...) 
       .setHeartbeat(...); 
    } 

} 
+4

あなたの「推測はあなたが内蔵されたシンプルなブローカーを使用していることである」にもかかわらず、 '' .enableStompBrokerRelay(...)を書くために、@Rossenを意図していましたか? '.enableSimpleBroker(...)'のように見えますか? –

4

開始スプリング4。2あなたが持つSockJS上でストンプを使用して、ハートビートの交渉結果を、サーバ側から、フルコントロールを持つことができるビルトインSimpleBroker:

public class WebSocketConfigurer extends AbstractWebSocketMessageBrokerConfigurer { 

    @Override 
    public void configureMessageBroker(MessageBrokerRegistry config) { 
     ThreadPoolTaskScheduler te = new ThreadPoolTaskScheduler(); 
     te.setPoolSize(1); 
     te.setThreadNamePrefix("wss-heartbeat-thread-"); 
     te.initialize(); 

     config.enableSimpleBroker("/") 
       /** 
       * Configure the value for the heartbeat settings. The first number 
       * represents how often the server will write or send a heartbeat. 
       * The second is how often the client should write. 0 means no heartbeats. 
       * <p>By default this is set to "0, 0" unless the {@link #setTaskScheduler 
       * taskScheduler} in which case the default becomes "10000,10000" 
       * (in milliseconds). 
       * @since 4.2 
       */ 
       .setHeartbeatValue(new long[]{heartbeatServer, heartbeatClient}) 
       .setTaskScheduler(te); 
    } 

    @Override 
    public void registerStompEndpoints(StompEndpointRegistry registry) { 
     registry.addEndpoint(.....) 
       .setAllowedOrigins(....) 
       .withSockJS(); 
    } 
} 
+0

すごく、それは私が他の場所で見つけることができなかった何かの本質的なものです!ありがとう! – thorinkor

+0

それはあなたを助けてくれてうれしい! – artemisian

5

我々春、WebSocketを、STOMPと春のセッションと同じ問題を抱えて - なしwebsocketがサーバー側でメッセージを受信しない間に、ハートビートとSpringセッションが期限切れになる可能性があります。我々は20000msごとにブラウザからSTOMPハートビートを有効にして、SimpMessageType.HEARTBEATをに追加しました。sessionRepositoryInterceptorは、メッセージのないSTOMPのハートビートでSpringセッションの最後のアクセス時間を更新します。我々は、インビルド春のセッションとのWebSocketセッション結合を可能にするためのベースとして抽象セッション WebSocketMessageBrokerConfigurerを使用する必要がありました。 Spring manual,第2の例。公式の例の春のセッションがインバウンドのWebSocket CONNECT/MESSAGE/SUBSCRIBE/UNSUBSCRIBEメッセージに更新ではなくハートビートされて、我々は再設定する必要がある理由、それは2つのことだ - 少なくともインバウンドハートビートを有効にしてハートビートをWebSocketをするために反応するように春のセッションを調整

public class WebSocketConfig extends AbstractSessionWebSocketMessageBrokerConfigurer<ExpiringSession> { 

    @Autowired 
    SessionRepositoryMessageInterceptor sessionRepositoryInterceptor; 

    @Override 
    public void configureMessageBroker(MessageBrokerRegistry config) { 
     sessionRepositoryInterceptor.setMatchingMessageTypes(EnumSet.of(SimpMessageType.CONNECT, 
       SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE, 
       SimpMessageType.UNSUBSCRIBE, SimpMessageType.HEARTBEAT)); 

     config.setApplicationDestinationPrefixes(...); 
     config.enableSimpleBroker(...) 
      .setTaskScheduler(new DefaultManagedTaskScheduler()) 
      .setHeartbeatValue(new long[]{0,20000}); 
    } 
} 

我々がしようとしたもう一つの方法は、いくつかの再実装SessionRepositoryMessageInterceptor機能のアウトバウンドのWebSocketメッセージに春のセッションに最終アクセス時刻を更新プラスリスナー経由でのWebSocketセッション - >春のセッションマップを維持するためですが、上記のコードではなかったですトリック。

関連する問題