Spring Web Reactive | 5. RSocket | 5.1. 概要
RSocketは、TCP、WebSocket、その他のバイトストリーム転送を通じて多重化された全二重通信を行うアプリケーションプロトコルです。次の対話モデルのいずれかを使用します。
Request-Response: 1つのメッセージを送信し、1つ受信します。Request-Stream: 1つのメッセージを送信し、メッセージストリームを受信します。Channel: 双方向でメッセージストリームを送信します。Fire-and-Forget: 一方向のメッセージを送信します。
最初の接続が確立されると、両側は対称になり、どちらからでも対話を開始できます。クライアントとサーバーの区別はなくなります。そのため、参加者はリクエスターとレスポンダー、対話はリクエストストリームまたは単にリクエストと呼ばれます。
RSocketの主な機能と利点は次のとおりです。
- ネットワーク境界を越えたReactive Streamsセマンティクス:
Request-StreamやChannelなどのストリーミングリクエストでは、バックプレッシャー信号がリクエスターとレスポンダーの間を移動します。これにより、要求元でレスポンダーの速度を抑え、ネットワーク層の輻輳制御やバッファリングへの依存を減らせます。 - リクエストのスロットリング:
LEASEフレームに由来してleasingと呼ばれます。各エンドポイントは、一定期間に相手側が送信できるリクエスト数を制限できます。leaseは定期的に更新されます。 - セッション再開: 接続が失われても一部の状態を保持できます。状態管理はアプリケーションに対して透過的であり、バックプレッシャーと連携して可能な場合にプロデューサーを停止し、必要な状態を減らします。
- 大きなメッセージの断片化と再構築。
- Keepaliveハートビート。
RSocketには複数言語の実装があります。JavaライブラリはProject Reactor上に構築され、転送にはReactor Nettyを使用します。アプリケーションのReactive Streams publisherの信号は、RSocketを通じてネットワーク上を透過的に伝達されます。
5.1.1. プロトコル
RSocketの利点の一つは、ネットワーク動作とプロトコル拡張を定義した読みやすい仕様です。言語実装や上位フレームワークAPIに関係なく、仕様を読む価値があります。このセクションでは簡潔な概要を説明します。
接続
クライアントは最初にTCPやWebSocketなどの低レベルなストリーミング転送を通じてサーバーへ接続し、接続パラメーターを設定するSETUPフレームを送信します。
サーバーはSETUPフレームを拒否できます。通常は送受信後にどちら側からでもリクエストを開始できます。ただし、SETUPがleasingセマンティクスを使用する場合、各側は相手からのLEASEフレームを待つ必要があります。
リクエスト
接続後、どちら側からでもREQUEST_RESPONSE、REQUEST_STREAM、REQUEST_CHANNEL、REQUEST_FNFフレームのいずれかでリクエストを開始できます。各フレームは、リクエスターからレスポンダーへ1つのメッセージを伝えます。
レスポンダーはレスポンスメッセージを含むPAYLOADフレームを返します。REQUEST_CHANNELでは、リクエスターも追加リクエストメッセージを含むPAYLOADフレームを送信します。
Request-StreamやChannelなどのメッセージストリームでは、レスポンダーはリクエスターの需要信号を考慮する必要があります。需要はメッセージ数で表されます。初期需要はREQUEST_STREAMとREQUEST_CHANNELフレームで指定し、後続需要はREQUEST_Nフレームで通知します。
どちら側からでも、個別リクエストではなく接続全体に対するメタデータ通知をMETADATA_PUSHフレームで送信できます。
メッセージ形式
RSocketメッセージにはデータとメタデータが含まれます。メタデータはルート、セキュリティトークンなどを運べます。データとメタデータは異なる形式を使用できます。各MIMEタイプはSETUPフレームで宣言し、接続上のすべてのリクエストに適用されます。
すべてのメッセージへメタデータを含められますが、ルートなどのリクエスト単位のメタデータは通常、最初のREQUEST_RESPONSE、REQUEST_STREAM、REQUEST_CHANNEL、REQUEST_FNFフレームだけに含めます。
プロトコル拡張は一般的なメタデータ形式を定義します。
5.1.2. Java実装
RSocketのJava実装はProject Reactor上に構築されています。TCPとWebSocket転送はReactor Nettyを使用します。Reactorはプロトコル実装を簡素化し、アプリケーションでは宣言的な演算子と透過的なバックプレッシャーを備えたFluxとMonoを自然に使用できます。
RSocket Java APIは意図的に最小限に保たれています。プロトコル機能に集中し、RPCコード生成などのアプリケーションプログラミングモデルは独立した上位レベルの関心事として扱います。
主要なio.rsocket.RSocket契約は、単一メッセージを表すMono、メッセージストリームを表すFlux、データとメタデータをバイトバッファーとして公開するio.rsocket.Payloadを使用して4つの対話タイプをモデル化します。この契約は対称です。アプリケーションはリクエスト用のRSocketを受け取り、レスポンス処理用のRSocketを実装します。
これは完全な入門ではありません。通常、SpringアプリケーションがAPIを直接使用する必要はありませんが、SpringなしでRSocketを試すことも有用です。RSocket Javaリポジトリには多数のサンプルアプリケーションがあります。
5.1.3. Springサポート
spring-messagingモジュールには次の機能があります。
- RSocketRequester: データとメタデータのエンコード、デコードを使用し、
io.rsocket.RSocketを通じてリクエストする流れるようなAPI。 - アノテーション付きレスポンダー:
@MessageMappingレスポンス用のアノテーション付きハンドラーメソッド。
spring-webモジュールには、Jackson CBOR/JSONやProtobufなど、RSocketアプリケーションで必要になる可能性が高いエンコーダーとデコーダーの実装があります。効率的なルートマッチングのためのプラグイン可能なPathPatternParserも含まれます。
Spring Boot 2.2は、TCPまたはWebSocket経由のRSocketサーバー起動をサポートします。WebFluxサーバーからWebSocket経由でRSocketを公開する選択肢もあります。RSocketRequester.BuilderとRSocketStrategiesのクライアントサポートと自動設定も提供します。詳細はSpring BootリファレンスのRSocketセクションを参照してください。
Spring Security 5.2はRSocketをサポートします。
Spring Integration 5.2は、RSocketクライアントとサーバーと連携するインバウンドおよびアウトバウンドゲートウェイを提供します。詳細はSpring Integrationリファレンスを参照してください。
Spring Cloud GatewayはRSocket接続をサポートします。