34

特定のエンティティの変更に関心のあるすべてのクライアントに状態を同期したいと思います。だから私は次のようなものを達成したいと思います:

  • エンティティで CRUD API を公開する ( および を介しHTTP/RESTwebsockets)
  • (変更呼び出しの)応答をwebsocketsトピックにルーティングします

技術的には、 spring-data-restspring websocket の実装を組み合わせて、spring-data-websocket のようなものを実現するアイデアに興味があります。

私の頭に浮かぶ2つの解決策があり、実際には両方とも次のようになります。

  • spring-data-rest を介してエンティティを公開するREST/HTTP API
  • websocketコントローラ (エンティティの変更呼び出しに使用)

コントローラーは次のwebsocketようになります。

@Controller
public class EntityAWebSocketController {
      @MessageMapping("/EntityA/update")
      @SendTo("/topic/EntityA/update")
      public EntityA update(EntityA entityA) throws Exception {
           // persist,....
           return entityA;
     }
}

シナリオ 1:Websocket APIから呼び出されたREST/HTTP API

ルール:

  • クライアントのリクエストは常にREST/HTTP API
  • 応答はREST/HTTP APIすべての操作に対するものです
  • さらに、操作を変更すると、websocketメッセージも表示されます

技術的には、次の方法で実現できます。

  • spring-rest-data イベントwebsocketからコントローラーを呼び出す(つまり、、、)AfterCreateEventAfterSaveEventAfterLinkSaveEventAfterDeleteEvent

私が行く必要があるので、それでも解決策は私にはかなりうんざりしているようです:

  1. クライアント A --HTTPリクエスト --> サーバー (spring-data-rest コントローラー)
  2. サーバー (spring-data-rest コントローラーの AfterXXXEvent) --websocketメッセージ --> Springwebsocketコントローラー
  3. Spring websocket コントローラー --websocketトピック経由のメッセージ --> トピックに関心のあるすべてのクライアント
  4. サーバー (spring-data-rest コントローラー) --HTTP応答 --> クライアント A

シナリオ 2:Websocket APIから独立REST API

ルール:

  • クライアント要求はREST/HTTP API非変更操作専用です
  • 応答はREST/HTTP API非変更操作のみです
  • クライアントwebsocketはすべての変更操作に対してメッセージを送信します
  • websocketメッセージは、すべての変更操作に対してのみクライアントに送信されます

他にアイデアが思い浮かばない場合は、後者の方法を使用しますが、それでも、spring-data-websockets のようなものC(R)UDを介して公開されるメソッドを何らかの方法で生成し、ルートのみを処理できれば素晴らしいと思います。websockets私の実装。

すべてのエンティティのすべてのメソッドを( *WebSocketControllersを介して) 手動で公開する必要があるように感じます。CUDそして、私はそれには怠惰すぎるかもしれません。

アイデア?

4

2 に答える 2

0

しばらくの間、同じアーキテクチャが私の頭を悩ませていました。そのすべての欠点と利点について言及したい場合、それは長い話になるので、実装に飛び込みましょう。

2 番目のシナリオは有効ですが、前述のように、同じ websocket セッションで crud アクションを実行することをお勧めします。これにより、すべてのリクエストで HTTP ハンドシェイクが不要になり、メッセージの本文サイズが縮小されるため、レイテンシが改善されます。その間、サーバーへの永続的な接続が既にあるので、それを有効に活用してみませんか?

私はしばらく探し回ったが、あなたの質問から6年経っても、これを実現できるWebsocketプロトコルを見つけることができなかったので、別のダミープロジェクトに必要だったので、自分でそれに取り組むことにしました.

このようなプロトコルのもう 1 つの利点は、既に作成されているコントローラーに多くの変更を加える必要がないことです。そのため、Spring Framework (たとえば) のアノテーションをサポートし、そこから websocket エンドポイントを作成できる必要があります。Spring のような別のフレームワークでそのようなプロトコルを実装することの難しい部分は、ServletRequest と ServletResponse を作成し、それらを独自の websocket プロトコルに変換するのは良くないため、いくつかの利点が失われることです。たとえば、その時点までにアプリケーションで作成した http フィルターは意味がありません。これらのフィルターを介して websocket メッセージを渡すのは簡単ではないからです。

プロトコル自体について: クライアント側のコールバックをリクエスト ID にマップできるように、リクエストごとに一意の ID とともに、すべてを json 形式で渡すことにしました。そしてもちろん、フィルターを追加するためのフィルター チェーンがあります。

ここで対処するのが難しいもう 1 つのことは、場合によっては http フィルターのように機能する Spring Security です。私自身のライブラリでは、最終的に次のような注釈を処理できましたが、HTTP セキュリティ構成で@PreAuthorize使用している場合は問題になります。antMatchers

したがって、http コントローラーを呼び出すための websocket アダプターの作成には、多くの欠点があります。

ここでプロジェクトを確認できます: Rest Over Websocket。Spring Boot用に書かれています。

于 2020-08-14T07:45:23.287 に答える