nginxプロキシsocket.ioサービスの落とし穴の詳細な説明

nginxプロキシsocket.ioサービスの落とし穴の詳細な説明

Nginx は 2 つの socket.io サーバーをプロキシします。 socket.ioの動作モードはポーリングからwebsocketにアップグレードされました

現象

nginx 経由でサービスをリクエストすると、大量の 400 エラーが発生していました。Websocket にアップグレードできる場合もあれば、エラーが報告され続ける場合もありました。ただし、 ip+端口を介して直接アクセスすると、100% 成功します。

分析する

シド

SID が私たちの問題の鍵です。最初に接続を作成するとき (ポーリング モードは長い接続をシミュレートします)、クライアントは次のような要求を開始します。

https://***/?EIO=3&transport=polling&t=1540820717277-0

メッセージを受信した後、サーバーはオブジェクトを作成し、それを接続にバインドし、セッションをマークするための sid (セッション ID) を返します。セッションとは何を意味するのでしょうか? セッションとは一連のインタラクションであり、これらのインタラクションは相互に関連しています。このシナリオでは、次の http リクエストが来たときに、以前に理論上の長い接続にバインドされていたオブジェクトを見つける必要があります (ここでは Websocket がないので、理論上のものです)。 HTTP リクエストはステートレスであり、各リクエストは独立していることがわかっているので、socket.io ではこれを実現するために SID を導入しています。リクエストを受信すると、サーバーは sid を生成し、応答を確認します。

次のようにコードをコピーします
{"sid":"EoGaL3fRQlpTOaLp5eST","アップグレード":["websocket"],"pingInterval":8000,"pingTimeout":10000}

後続の各リクエストでは、Websocket リクエストを確立するためのリクエストも含め、この sid を送信する必要があります。したがって、sid はポーリングとポーリングを Websocket にアップグレードするための鍵となります。この後のリクエストは次のようになります。

https://***/?EIO=3&transport=polling&t=1540820717314-1&sid=EoGaL3fRQlpTOaLp5eST

または

wss://***/?EIO=3&transport=websocket&t=1540820717314-1&sid=EoGaL3fRQlpTOaLp5eST

そこで疑問になるのが、リクエストに含まれる SID がサーバーによって生成されなかった場合はどうなるかということです。サーバーはそれを認識せず、400を返し、

無効なSID

これが私たちが遭遇した問題です。nginx のデフォルトの負荷分散戦略はポーリングなので、リクエストは SID を生成したマシンではないマシンでヒットする可能性があります。この時点で、400 を受け取ります。運が良ければ、元のマシンでもヒットする可能性があります。さらに運が良ければ、Websocket 接続が確立されるまで持続することもできます。

解決する

ここに2つの解決策があります

  1. Nginx は負荷分散に ip_hash を使用し、クライアントからのすべてのリクエストが 1 つのサーバーに送信されるようにします。
  2. ポーリングモードは使用せず、WebSocketのみを使用してください

どちらの選択肢にも長所と短所があります。 2 番目は明らかで、Websocket をサポートしていない古いブラウザやクライアントは動作しません。最初の問題は、より隠れたものです。マシンを追加または削除するとどうなるか想像してみてください。このとき、ip_hash 戦略のモデルが変更され、以前の接続はすべて無効になります。ただし、マイクロサービスの場合、スケーリングは非常に頻繁に行われる操作であり (特に製品が開発段階にある場合)、このような損失のあるスケーリングはおそらく受け入れられません。

まとめると、websocket を直接使用することをお勧めします。結局のところ、websocket をサポートしていない古いバージョンはわずかな割合を占めており、最初にポーリングするよりも時間がかかりません。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • nginxリバースプロキシwebSocket設定の詳細な説明
  • Nginx リバース プロキシ WebSocket 応答 403 の解決方法の詳細な説明
  • Nginx 実戦リバースプロキシ WebSocket 構成例
  • Nginx を WebSocket プロキシとして使用するチュートリアル
  • Nginx リバース プロキシ Websocket 構成例

<<:  Vue SPA ファースト スクリーン最適化ソリューション

>>:  mysql data_dirの変更によって発生するエラー問題を解決する

推薦する

Linux で利用可能なネットワーク インターフェイスを表示する方法

序文Linux システムをインストールした後の最も一般的なタスクは、ネットワーク構成です。もちろん、...

MySQLテーブルをコピーする方法

目次1.mysqlダンプ実行プロセス:特徴2. CSVファイルをエクスポートする(最も柔軟性が高い)...

MySQL 5.7.20 の解凍バージョンをインストールするための詳細な手順 (2 つの方法)

Windows 64ビットでのMySQLのインストールについて説明します。5.7以降、MySQLの...

CSS のグリッドプロパティの使用に関する詳細な説明

グリッドレイアウト親要素に追加された属性グリッドテンプレートの列/グリッドテンプレートの行要素の行ま...

MySQL テーブルパーティションの使用法と基本原理の詳細な説明

目次パーティションテーブルとはパーティションテーブルの適用シナリオパーティションテーブルの制限パーテ...

HTML に埋め込まれた Flash HTML ウェブページ コードに Flash ファイルを埋め込むソリューション (パート 1)

中国の習慣では、旧暦の1月15日より前に新年を祝います。ここで、庭にいる友人たちに新年の幸せを祈りた...

MySQL における datetime と timestamp の違いと使い方

1. MySQL で現在の時刻を表現するにはどうすればよいでしょうか?実際、表現方法はいろいろありま...

JavaScriptは両端キューを実装する

この記事の例では、両端キューを実装するためのJavaScriptの具体的なコードを参考までに共有して...

Sparkの紹介とHadoopとの比較

目次1. SparkとHadoopの比較1.1 Haoopの欠点1.2 Hadoop MR に対する...

MySQLにおけるrow_numberの実装プロセス

1. 背景一般的に、データ ウェアハウス環境では、row_number 関数を使用して特定のディメン...

docker nginxコンテナの起動とローカルへのマウントの詳細な説明

まず、nginx コンテナ内の構造:コンテナを入力します: docker exec -it b511...

HTML テーブルの境界線を設定する際のヒント

HTML を初めて使用する多くの人にとって、テーブル <table> は最もよく使用され...

Vueは動的ルーティングの詳細を実装します

目次1. フロントエンド制御1. router.js ファイル内 (router.js にそれぞれ静...

ミニプログラムでマインドマップを描く方法

目次マインドマップとは何ですか? F6で描く方法アリペイ微信要約するマインドマップとは何ですか?マイ...

Web ベースの電子メール コンテンツの HTML フォーマット標準の概要

1. ページ要件1) 標準のヘッダーとフッターを使用するXML/HTML コードコンテンツをクリップ...