ステートフルアプリと非ステートフルアプリ[終了]


9

ステートフルアプリと非ステートフルアプリについて学習してきましたが、このトピックについてはまだ少し混乱しています。

たとえば、ユーザーがsocket.io経由で接続するとすぐにランダムルームに割り当てられるNodeで実行しているアプリがあるとします。これらは4の部屋であり、永続的なものではありませんが、ハッシュマップとしてグローバル変数に格納されます。私はdb(クエリが多すぎる)やredis(高すぎる)を使用していません。

これはステートフルアプリの例ですか?


5
ステートレスの場合、ハッシュマップに格納するものは何もありません。
candied_orange

回答:


17

Webアプリケーションのコンテキストでは、データを外部(データベースなど)に保存するのではなく、一時的な状態をメモリに維持する場合、サーバーをステートフルと呼びます。

ステートフルアプリケーションには、次のような多くの問題があります。

  • 特定のサーバーにセッションを固定せずに複数のサーバーを実行することはできません
  • サーバーを再起動すると状態が失われます

したがって、サーバー側の状態を回避することをお勧めします(ここでも、外部的にデータベースに保存されている場合を除きます)。

Webアプリバックエンドは、RESTの原則を使用できるため、通常、セッション状態を保存する必要はありません。状態はクライアントとサーバー間で転送されます。この状態は、URL、Cookie、HTTP本文などで表されます。HTTPはステートレスなプロトコルであるため、これは必要です(意味論的には、必ずしもその技術的基盤ではありません)。

Webソケットでは、クライアントがサーバーとの長時間のセッション/接続を維持しており、その接続には状態が含まれるため、これらの原則は少し崩れます。これは避けられませんが、Webソケットの使用がステートレスなバックエンドの設計に影響を与えるかどうか、およびその程度を制御できます。

  • どの接続がどのイベントにサブスクライブされるかを制御するインメモリデータ構造を維持することは、まったく問題ありません。

  • そのインメモリデータ構造がその情報の「真の情報源」である場合、問題があります。

    • サブスクリプションが一時的であると想定されている場合は、すべて問題ありません。
    • クライアントが再接続したときに同じサブスクリプションを再確立する場合は、この状態を別の場所に保存する必要があります。たとえば、データベースのサーバー側、またはCookieまたはLocalStorageを介したクライアント側。

一般に、次のいずれかに該当する場合は、内部サーバーの状態を維持できます。

  • 状態は外部に保存されます
  • 状態はリクエスト間で共有されません
  • 状態は、データベース接続など、再利用可能な高価なリソースの取得です
  • 状態は、信頼できるデータソースのキャッシュですが、キャッシュの無効化や結果整合性などの困難な問題が発生します

1
ここでの「一時的」は実装というよりはコンセプトのようなものなので、メモリにいる必要はないと思います。データベースまたはファイルシステムを使用してセッションデータを格納するセッションの実装は多数ありますが、ステートレスとは言えません。
tia

「したがって、サーバー側の状態を回避することがベストプラクティスです(ここでも、外部的にデータベースに格納されていない限り)」-ここで「ベストプラクティス」という用語を再考します。たぶん、ビジネスが状態の維持などのコストよりも接続の切断を好む状況があるかもしれません。それは実際にはケースごとの長所と短所に依存します。
ロンクライン、

6

クライアントからの着信要求を処理するために必要な状態をサーバーに保存している場合、サーバーはステートフルです。別の言い方をすれば、クライアントからのリクエストを処理するために保存し、アクセスする必要がある状態です。したがって、ハッシュマップは状態なので、サーバーはステートフルです。

現在、ステートフルではないリッチな機能を実行する実際のWebアプリはほとんどありません。結局のところ、ユーザーがログインし、ログインしたクライアントの要求に応じて要求を処理する場合、定義上、ある程度、特定のクライアントに関連するサーバーに状態を保存しており、サーバーはステートフルです。 、たとえログイン情報だけでも。

そのため、サーバーの状態がゼロになることにあまり夢中にならないでしょう。重要なのは、サーバーにどのくらいの状態があるか、この状態を保存してアクセスするのに(処理、ストレージなどの観点から)どれだけ費用がかかるか、そしてこの状態でもアプリを水平にスケーリングできるかどうかです。また、サーバー上ではなく、クライアント内で実際に状態を維持します。簡単な例として、「次のページ」ボタンを持つクライアントアプリがあるとします。クライアント側の状態またはサーバー側の状態のいずれかで「次のページ」を実装できます。

クライアントの現在のページのサーバー側の状態がある場合は、「次の」ページを表示するコマンドをサーバーに送信するだけです。サーバーはそのクライアントの状態を確認し、ページを増分してから、次のページのデータを返します。

または、現在のページをクライアントに保存することもできます。クライアントが次のページを必要とする場合、クライアントは現在のページ番号を取得し、1ずつインクリメントし、次に表示したい特定のページ番号に対する一般的な要求を行います。

これらの実装のうち、スケールが適切だと思いますか?ユーザーが別のページを表示する2番目のタブを開いたときに実装する方が簡単ですか?水平方向にスケーリングする方が簡単です。これらすべてに対する答えは、現在のページをサーバーに保存せず、クライアントに保持し、ページNに対する一般的なリクエストをサーバーに送信するだけです。クライアント側でその状態を維持すると、個別および水平方向のスケーリングが容易になり、同じクライアントの複数のビューがサポートされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.