1. ホーム
  2. rest

[解決済み] RESTful HTTPの代わりにWebsocketを使用する際の落とし穴とは?

2023-05-21 03:26:50

質問

私は現在、クライアントが大きな仕事を要求し、それをサーバーに送信することを必要とするプロジェクトに取り組んでいます。次に、サーバーは仕事を分割し、クライアントがGETコールを行うためのURLの配列で応答し、データをストリームバックします。私はこのプロジェクトの生え抜きで、現在、効率性を高めるためにSpringウェブソケットを使っています。クライアントがサーバーにストリームバックする準備ができたかどうか常にpingを打つ代わりに、ウェブソケットが直接クライアントに連絡するようになりました。

ウェブソケットに全プロセスを終始管理させるのは悪い考えでしょうか?私はSpringウェブソケットでSTOMPを使用していますが、RESTを捨ててもまだ大きな問題があるのでしょうか?

どのように解決するのですか?

RESTful HTTPでは ステートレスリクエスト/レスポンスシステム であり、クライアントがリクエストを送信し、サーバーがレスポンスを返す。

ウェブソケットでは ステートフル(または潜在的にステートフル)なメッセージパッシングシステムがあり、メッセージはどちらにも送ることができます。 であり、メッセージの送信は RESTful な HTTP リクエスト/レスポンスよりも低いオーバーヘッドを持ちます。

この 2 つは、異なる強みを持つかなり異なる構造です。

接続された WebSocket の主な利点は次のとおりです。

  1. 双方向のコミュニケーション。 つまり、サーバはいつでもクライアントに何かを通知することができます。 そのため、新しいものがあるかどうかを確認するために定期的にサーバーをポーリングする代わりに、クライアントは WebSocket を確立して、サーバーから来るあらゆるメッセージをただ聞くことができます。 サーバーから見ると、クライアントにとって関心のあるイベントが発生すると、サーバーは単にメッセージをクライアントに送信します。 サーバーは、プレーンな HTTP ではこれを行うことができません。

  2. メッセージごとのオーバーヘッドを低減します。 クライアントとサーバーの間で多くのトラフィックが流れることが予想される場合、WebSocketを使用するとメッセージあたりのオーバーヘッドが低くなります。 これは、TCP 接続がすでに確立されており、すでに開いているソケットにメッセージを送信するだけでよいからです。 HTTP RESTリクエストでは、まずTCPコネクションを確立する必要があり、クライアントとサーバーの間で何往復もする必要があります。 そして、HTTPリクエストを送信し、レスポンスを受信してTCPコネクションを閉じます。 HTTPリクエストには、たとえそのリクエストに関係なくても、そのサーバーに配置されているすべてのCookieなどのオーバーヘッドが必ず含まれます。 HTTP/2(最新のHTTP仕様)では、クライアントとサーバーの両方で使用されている場合、1つのTCPコネクションを単一のリクエスト/レスポンス以上に使用できるため、この点でさらなる効率化が可能です。 もし、https の REST リクエスト/レスポンスを行うために、TCP レベルで行われるすべてのリクエスト/レスポンスをグラフにすると、すでに確立された WebSocket 上でメッセージを送信する場合と比較して、どれだけのことが行われているのか驚くことでしょう。

  3. 状況によってはより高いスケール メッセージごとのオーバーヘッドが少なく、何かが新しくなったかどうかを調べるためのクライアントのポーリングがないため、これは拡張性 (特定のサーバーが提供できるクライアントの数) を高めることにつながる可能性があります。 WebSocket のスケーラビリティにも欠点があります (下記参照)。

  4. ステートフル接続です。 クッキーやセッションIDに頼ることなく、与えられた接続のためにプログラム内に直接状態を保存することができます。 ほとんどの問題を解決するためにステートレス接続で多くの開発が行われてきましたが、時にはステートフル接続の方がシンプルな場合もあります。

RESTfulなHTTPリクエスト/レスポンスの主な利点は以下の通りです。

  1. ユニバーサル対応。 HTTP よりも普遍的にサポートされるのは難しいです。 WebSocket は現在、比較的良いサポートを享受していますが、WebSocket のサポートが定期的に利用できない状況もまだあります。

  2. より多くのサーバ環境に対応。 サーバプロセスの長時間稼働を許さないサーバ環境があります (一部の共用ホスティング環境)。 このような環境では、HTTPリクエストはサポートできても、長時間動作するWebSocket接続はサポートできません。

  3. 状況によってはより高いスケール 継続的に接続された TCP ソケットに対する webSocket の要件は、HTTP リクエストが要求しないサーバー インフラストラクチャに、いくつかの新しいスケール要件を追加します。 そのため、これは結局トレードオフの空間となります。 WebSocket の利点が本当に必要でないか、重要な方法で使用されていない場合、HTTP リクエストの方が実際によくスケールするかもしれません。 これは間違いなく、特定の使用プロファイルに依存します。

  4. 単発の場合 リクエスト/レスポンス の場合、単一の HTTP リクエストは、webSocket を確立してそれを使用し、その後閉じるよりも効率的です。 これは、webSocket を開くことが HTTP リクエスト/レスポンスで始まり、その後、双方が webSocket 接続へのアップグレードに合意した後に、実際の webSocket メッセージが送信できるようになるためです。

  5. ステートレスです。 もしあなたの仕事がステートレスなインフラストラクチャを持つことでより複雑にならないのであれば、ステートレスな世界はスケーリングやフェイルオーバーをより簡単にすることができます(ロードバランサの後ろにサーバプロセスを追加または削除するだけです)。

  6. 自動的にキャッシュ可能です。 適切なサーバ設定により、http レスポンスはブラウザまたはプロキシによってキャッシュされることができます。 WebSocket経由で送信されたリクエストには、そのような組み込みのメカニズムはありません。


では、ご質問の方法について。

RESTful HTTPの代わりにwebsocketを使用することの落とし穴は何ですか?

  1. 大規模 (数十万クライアント) になると、同時に接続された多数の WebSocket をサポートするために、特別なサーバー作業が必要になる場合があります。

  2. すべての可能なクライアントまたはツールセットは、HTTP リクエストをサポートするのと同じレベルで、WebSocket またはそれを介して行われるリクエストをサポートしません。

  3. いくつかの安価なサーバー環境は、webSocket をサポートするために必要な、長時間稼働するサーバープロセスをサポートしていません。

進行状況の通知をクライアントに返すことがアプリケーションにとって重要である場合、進行状況を送信し続ける長時間稼働のhttp接続を使用するか、webSocketを使用するかのどちらかでしょう。 WebSocketの方が簡単でしょう。 この特定のアクティビティの比較的短い期間だけ WebSocket が必要な場合は、クライアントにデータをプッシュする機能が必要な期間だけ WebSocket を使用し、通常のリクエスト/レスポンス アクティビティのために http リクエストを使用することで、トレードオフの最適な全体像を見つけることができます。