web-dev-qa-db-ja.com

もし REST アプリケーションはステートレスであることが想定されています、セッションをどのように管理しますか

明確化が必要です。私はRESTについて読んでいて、そしてRESTfulなアプリケーションを構築してきました。ウィキペディアによると、REST自体はRepresentational State Transferとして定義されています。だから私は、誰もが語り続けるこのステートレスなgobbledeygookをすべて理解しているわけではありません。

ウィキペディアから

特定の時点で、クライアントはアプリケーション状態間で移行しているか、または「休止」している可能性があります。休止状態にあるクライアントは、そのユーザーと対話できますが、負荷は発生せず、一連のサーバーまたはネットワーク上のクライアントごとの記憶域を消費することもありません。

彼らはただセッション/アプリケーションレベルのデータストアを使用しないと言っているのですか?

RESTの目的の1つは、投稿内のページング要求を非表示にして要求のページ番号をGET URIの一部にするのではなく、URIアクセスを一貫して使用できるようにすることです。私には理にかなっています。しかし、クライアントごとのデータ(セッションデータ)をサーバー側に格納するべきではない、と言っても過言ではないようです。

私がメッセージのキューを持っていて、私のユーザーがメッセージを読みたかったが、彼がメッセージを読んだりしている間、彼のセッションの間中送信される特定の送信者メッセージをブロックしたいですか?これをサーバー側の場所に格納して、ユーザーがブロックしていないメッセージ(またはメッセージID)のみをサーバーから送信するようにするのは意味がありませんか。

新しいメッセージリストを要求するたびに、ブロックするメッセージ送信者のリスト全体を本当に送信する必要がありますか。私に関係のあるメッセージリストは、そもそも公に利用可能なリソースではないでしょう。

繰り返しますが、これを理解しようとしているだけです。誰かお願いします


更新:

スタックオーバーフローの質問が見つかりましたが、その答えにはまったく解決できません。 RESTで状態を管理する方法 重要なクライアントの状態はすべてのリクエストですべて転送されるべきです。Ugg ..オーバーヘッドが非常に多いようです...これは正しいですか。

485
Zak

ステートレス性とは、すべてのHTTPリクエストが完全に独立して発生することを意味します。クライアントがHTTP要求を行うと、サーバーがその要求を満たすために必要なすべての情報が含まれます。サーバーは以前の要求からの情報に依存することはありません。その情報が重要であるならば、クライアントはその後の要求でそれを再び送らなければならないでしょう。無国籍も新しい機能をもたらします。負荷分散されたサーバー間でステートレスアプリケーションを配布する方が簡単です。ステートレスアプリケーションはキャッシュも簡単です。

実際には2種類の状態があります。クライアント上に存在するアプリケーション状態とサーバー上に存在するリソース状態。

Webサービスは、実際にリクエストを行っているときにのみ、アプリケーションの状態を気にする必要があります。それ以外の時間は、あなたが存在していることさえ知りません。つまり、クライアントが要求を出すたびに、サーバーが処理する必要があるアプリケーションの状態をすべて含める必要があります。

リソース状態はすべてのクライアントで同じであり、その適切な場所はサーバー上です。写真をサーバーにアップロードすると、新しいリソースが作成されます。新しい写真は独自のURIを持ち、将来のリクエストのターゲットになる可能性があります。 HTTPを通じてこのリソースを取得、変更、削除することができます。

これが無国籍とさまざまな国家の意味を区別するのに役立つことを願っています。

262
Srikar Doddi

基本的な説明は次のとおりです。

サーバーにクライアントセッション状態がありません。

ステートレスとは、serverクライアントセッションに関する状態を保存しないことを意味しますサーバー側。

clientセッションはクライアントに保存されます。サーバーはステートレスです。つまり、すべてのサーバーがいつでもクライアントにサービスを提供でき、セッションアフィニティまたはスティッキーセッションはありません。関連するセッション情報はクライアントに保存され、必要に応じてサーバーに渡されます。

これは、Webサーバーが通信する他のサービスが、ショッピングカートなどのビジネスオブジェクトに関する状態を維持することを妨げるものではなく、クライアントの現在のアプリケーション/セッション状態に関するものだけではありません。

クライアントのアプリケーションの状態は決してサーバーに保存されるべきではなく、clientそれを必要とするあらゆる場所へ。

ここで、STinRESTの由来、State Transfer。サーバーに保存させる代わりに、状態を転送します。 これは、数百万の同時ユーザーにスケールする唯一の方法です。数百万のセッションが数百万のセッションである以外の理由がない場合。

セッション管理の負荷はすべてのクライアントにわたって償却され、クライアントはセッション状態を保存し、サーバーはステートレスな方法で多くのオーダー以上のクライアントにサービスを提供できます。

数万人の同時ユーザーでonlyだけが必要だと思うサービスであっても、サービスをステートレスにする必要があります。数万はまだ数万であり、それに関連する時間とスペースのコストがあります。

ステートレスは、一般にHTTPプロトコルとWebが動作するように設計された方法であり、全体的にシンプルな実装であり、一連のセッション状態を維持するためのサーバー側ロジックの代わりに単一のコードパスを使用します。

いくつかの非常に基本的な実装原則があります。

これらは実装ではなく原則であり、これらの原則を満たす方法は異なる場合があります。

要約すると、 5つの主要原則 は次のとおりです。

  1. すべての「もの」にIDを与える
  2. 物事をリンクする
  3. 標準的な方法を使用する
  4. 複数の表現を持つリソース
  5. ステートレスに通信する

REST dissertation には、認証または承認については何もありません。

なぜなら、RESTfulな要求とそうでない要求を認証することと何の違いもないからです。認証は、RESTfulな議論とは無関係です。

特定の要件に合わせてステートレスアプリケーションを作成する方法の説明は、StackOverflowのtoo-broadです。

RESTに関連する認証と承認の実装はさらにtoo-broadであり、実装に関するさまざまなアプローチはインターネット上で詳細に説明されています。

これに関するヘルプ/情報を求めるコメントは、No Needed Neededとしてフラグを立てる必要があります。

478
user177800

彼らはただセッション/アプリケーションレベルのデータストアを使用しないと言っているのですか?

いいえ、彼らはそれを些細な方法で言っているのではありません。

彼らは「セッション」を定義しないと言っています。ログインしないでください。ログアウトしないでください。要求に資格情報を入力してください。各要求は独立しています。

あなたはまだデータストアを持っています。あなたにはまだ認証と承認があります。セッションを確立し、セッション状態を維持するための時間を無駄にしないでください。

要は、各要求(a)は完全に独立しており、(b)実際の作業なしに、巨大な並列サーバーファームに自明に割り当てられるということです。 ApacheまたはSquidは、RESTfulなリクエストを盲目的かつ成功裏に渡すことができます。

私がメッセージのキューを持っていて、私のユーザーがメッセージを読みたかったが、彼がメッセージを読んだりしている間、彼のセッションの間中送信される特定の送信者メッセージをブロックしたいですか?

ユーザーがフィルタを希望する場合は、各リクエストにフィルタを指定するだけです。

サーバがユーザによってブロックされていないメッセージ(またはメッセージID)のみを送信するようにするのは意味がありませんか?

はい。 RESTful URIリクエストにフィルタを指定します。

新しいメッセージリストを要求するたびに、ブロックするメッセージ送信者のリスト全体を本当に送信する必要がありますか。

はい。この「ブロックするメッセージ送信者のリスト」の最大サイズはどれくらいですか? PKの短いリスト?

GETリクエストは非常に大きくなる可能性があります。必要に応じて、一種のクエリのように聞こえてもPOSTリクエストを試すことができます。

73
S.Lott

あなたは絶対に正しい、サーバーとの完全にステートレスなやりとりをサポートすることはクライアントに追加の負担をかけます。ただし、アプリケーションの規模を検討する場合、クライアントの計算能力はクライアント数に正比例します。したがって、多数のクライアントに拡張することは、はるかに現実的です。

特定のクライアントとのやり取りに関連する情報を管理するためにサーバーに多少の責任があるとすぐに、その負荷が急速に増大してサーバーを消費する可能性があります。

それはトレードオフです。

34
Darrel Miller

RESTは非常に抽象的です。それはいくつかの良い、単純な、現実世界の例を持つのを助けます。

たとえば、Tumblr、Instagram、Facebook、Twitterなど、すべての主要なソーシャルメディアアプリケーションを取り上げます。それらはすべて、あなたがより遠くまであなたがより遠くにスクロールすると、より多くのコンテンツを見ることができ、さらに時間をずらして永遠にスクロールするビューを持っています。ただし、スクロールされた場所を失った瞬間にアプリがリセットされ、トップに戻ります。アプリを終了した場合、アプリを再度開くと、再び一番上に戻ります。

その理由は、サーバがあなたのセッション状態を保存しなかったからです。残念ながら、あなたのスクロール位置はクライアントのRAMに格納されていました。

幸い、再接続時にログインし直す必要はありませんが、これはクライアント側にも保存されているログイン証明書の有効期限が切れていないためです。アプリを削除して再インストールすると、サーバーがIPアドレスとセッションを関連付けなかったため、再度ログインする必要があります。

サーバーにはログインセッションがありません。これらはRESTに準拠しているからです。


上記の例ではWebブラウザはまったく含まれていませんが、バックエンドでは、アプリはHTTPSを介してホストサーバーと通信しています。私のポイントはRESTはクッキーやブラウザなどを含む必要はないということです。クライアントサイドのセッション状態を保存するにはさまざまな方法があります。

しかし、Webブラウザについて少し話してみましょう。これはRESTのもう1つの大きな利点をもたらします。

サーバーがセッション状態を保存しようとした場合、個々のクライアントをどのように識別するのでしょうか。

多くの人が共有ルーターで同じアドレスを使用している可能性があるため、IPアドレスを使用することはできません。それでは、どうですか?

それは多くの理由でMACアドレスを使用することはできません、あなたが異なるブラウザとアプリで同時に複数の異なるFacebookアカウントにログインすることができるからです。あるブラウザは別のブラウザのふりをすることが簡単にでき、MACアドレスも偽装するのと同じくらい簡単です。

サーバがあなたを識別するためにクライアント側の状態を保存する必要がある場合、リクエストを処理するのにかかる時間よりも長くRAMに保存する必要があります。そうしないと、データをキャッシュする必要があります。サーバはRAMとキャッシュの量が限られていますが、プロセッサの速度は言うまでもありません。サーバー側の状態は、指数関数的に3つすべてに追加されます。さらに、サーバーがセッションに関する状態を保存しようとしている場合は、現在ログインしているブラウザやアプリごとに、また使用するデバイスごとに別々に保存する必要があります。


それで... RESTがスケーラビリティのためにとても重要である理由をあなたが今見ることを望みます。なぜサーバー側のセッション状態がサーバーのスケーラビリティになるのかを理解し始めることができれば幸いです。


人々が混乱するのは、「状態」はデータベースに格納されている情報のようなものであると考えることです。いいえ、それはあなたがそれを使用しているときにサーバのRAMにある必要があるあらゆる情報を指します。

25
CommaToast

ここでの基本的な問題は Session State の混同です。 RESTは State をサーバーに保存しないことを指定しますが、ユーザーを保存することを妨げるものはありません Session

サーバー上で State を管理することは、サーバーがクライアントがしていること(アプリケーションのどのセクションでどのページを表示しているか)を正確に知っていることを意味します。そしてこれはあなたがする必要がないことです。

私はあなたがセッションストレージを最小サイズに保つべきであると言う他の人々に同意します。これは常識ですが、実際にはアプリケーションにも依存します。したがって、要するに、キャッシュされたデータとのセッションを維持してサーバーの負荷を軽減しながら要求を処理し、クライアントが使用する一時的な認証/アクセストークンを提供することで認証を管理することができます。セッション/トークンが期限切れになるたびに、新しいものを生成してそれを使用するようにクライアントに依頼します。

誰かがクライアントがトークンをうまく生成するべきであると主張するかもしれません。私はそれが両方の方法で機能すると言っています、そしてそれはアプリケーション、そして誰がAPIを操作しようとしているかによって異なります。

また、機密性の高いセッションデータをサーバーに保持するのが正しい方法です。たとえば「isFreeGift」という名前のフィールドを含むショッピングカートを保管することをクライアントに信頼することはできません。そのような情報はサーバーに保存する必要があります。

Santanu Dey が彼の答えに提供しているビデオリンクは役に立ちます。あなたがいないならそれを見てください。

ちょっとしたメモ:いくつかの操作はサーバに大きな負荷をかける可能性があるという事実を無視しているように思われます。これは、消費電力、ハードウェア消費、およびコスト(CPUサイクルによってレンタルされたサーバーの場合)の点で関連性があります。たとえ彼らが電気代やメンテナンス代を払っていない一部のレンタルサーバー上の最新のCPU上で操作が非常に素早くできるとしても、優れた開発者は彼らのアプリケーションを最適化することに怠惰ではありません。

質問が数歳であることにもかかわらず、私は私の答えがまだ役に立つことを願っています。

12
Sam Sirry

ステートレスとは、サービスの状態が後続の要求と応答の間持続しないことを意味します。各要求には独自のユーザー資格情報があり、個別に認証されています。しかしステートフルでは、各リクエストは以前のリクエストから認識されます。すべてのステートフル要求はセッション指向です。つまり、各要求は前の要求で行われた変更を認識して保持する必要があります。

銀行業務アプリケーションは、ステートフルアプリケーションの一例です。ユーザーが最初にログインしてからトランザクションを実行してログアウトする場所。ログアウト後にユーザーがトランザクションを実行しようとした場合、ユーザーはそれを実行できません。

はい、httpプロトコルは基本的にステートレスプロトコルですが、ステートフルにするためにHTTP cookieを使用しています。そのため、デフォルトではSOAPです。しかし、それは同様にステートフルにすることができます、あなたが使用しているフレームワークに依存します。

HTTPはステートレスですが、それでもさまざまなセッショントラッキングメカニズムを使用することで、Javaアプリケーションでセッションを維持できます。

はい、RESTまたはSOAPのいずれであってもWebサービスでセッションを維持できます。サードパーティのライブラリを使用して実装することも、独自のライブラリを使用して実装することもできます。

http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soapから取得しました

11
Ata ul Mustafa

このプレゼンテーションを見てください。

http://youtu.be/MRxTP-rQ-S8

このパターンによると - 本当に必要なときにいつでも状態を管理するための一時的な休息のリソースを作成します。明示的なセッションを避けます。

5
Santanu Dey

ステートレスとステートフルの主な違いは、毎回データがサーバーに渡されることです。ステートレスの場合、クライアントはすべての情報を提供する必要があるため、各要求で多くのパラメータを渡す必要があります。ステートフルでは、clietはこれらのパラメータを一度渡し、クライアントによって再度修正されるまでそれらはサーバによって維持されます。

IMO、APIはステートレスであるべきであり、それは本当に素早くスケールアップすることを可能にします。

3
psuhas

クライアント側でクライアントセッションを管理する必要があります。これは、リクエストごとに認証データを送信する必要があることを意味します。おそらく、認証データをID、アクセス許可などのユーザー情報とペアにするサーバー上のメモリ内キャッシュが必要です。

このREST ステートレス性の制約 は非常に重要です。この制約を適用しなければ、あなたのサーバー側のアプリケーションは スケール うまくいきません。なぜなら、すべての単一のクライアントセッションを維持することは アキレスのかかと になるからです。

2
inf3rno

全体の概念は異なります... RESTFulプロトコルを実装しようとしている場合は、セッションを管理する必要はありません。その場合、リクエストごとに認証手順を実行することをお勧めします(ただし、パフォーマンスの面では追加のコストがかかります - パスワードのハッシュ化は良い例です。大したことではありません...)。セッションを使用している場合 - 複数のサーバーに負荷を分散させる方法を教えてください。 RESTFulプロトコルはセッションをまったく排除することを目的としています - あなたはそれらを本当に必要としていません...それが "ステートレス"と呼ばれる理由です。セッションが必要になるのは、リクエストが行われた後でCookie以外のものをクライアント側に保存できない場合のみです(古い、Javascript/HTML5非対応のブラウザを例として取ります)。 「フル機能」のRESTFulクライアントの場合、アプリケーションがまだロードされるまでbase64(login:password)をクライアント側(メモリ内)に格納するのが通常安全です。サードパーティのスクリプト...

RESTFulサービスではCookie認証を無効にすることを強くお勧めします... Basic/Digest認証をチェックしてください - これはRESTFulベースのサービスには十分なはずです。

0
user3857922

ここでステートレスとは、リクエストの状態またはメタデータがサーバー側で維持されないことを意味します。サーバー上で各要求またはユーザーの状態を維持することで、パフォーマンスのボトルネックが発生します。サーバーは、特定の操作を実行するために必要な属性を指定して要求されたばかりです。

セッションを管理したり、ユーザーにカスタマイズエクスペリエンスを提供したりするには、メタデータやユーザーの好みの状態、過去のリクエスト履歴を維持する必要があります。これは、クッキー、隠し属性、またはセッションオブジェクトを管理することによって実行できます。

これにより、アプリケーション内のユーザーの状態を維持または追跡できます。

お役に立てれば!

0
Sourabh Bhavsar

RESTはステートレスで、リクエスト間の状態を維持しません。クライアントCookie /ヘッダーは認証のようなユーザー状態を維持するために設定されています。クライアントのユーザ名/パスワードが第2部OTP生成などの第3部認証メカニズムによって検証されたとします。ユーザが認証されると - ヘッダ/クッキーはサービスエンドポイントが公開されて残り。 IPのようなユーザーの特定の情報はキャッシュに保持され、その後リストされたリソースに対して同じIP(MACアドレス)から要求が来た場合はユーザーは許可されます。そしてキャッシュは特定の時間維持され、時間が経過すると無効になります。そのため、キャッシュを使用することも、DBエントリを使用してリクエストの情報を永続化することもできます。

0
Amit

スプーンはありません。 all _自分のものを何度も何度もサーバーに送信する」ような無国籍を考えないでください。とんでもない。データベース自体is結局のところ一種の状態です、あなたは登録ユーザーなので、クライアントサイドの情報のセットはサーバーサイドなしでは有効になりません。技術的には、あなたは決して真のステートレスになることはありません。

しかし、あなたができること、そして本当の意味をなすことは、Webサーバーのフットプリントを最小限に抑えることです。 PHPのような言語では、すべてをセッションストレージに単純に詰め込むことが非常に簡単になります。これを行うことはできますが、Webサーバーが多数ある場合は、それらの間で共有されているもの(NFS、Redis、Memcachedなど)を使用する必要があります。それは負荷分散のためです - あなたはあなたの次の要求で別のウェブサーバーに行くかもしれません。そして、それらの間に共有ストレージが存在しなければならない一方で(大抵彼らはあなたがログインしているか否かを知らさなければならないからです)、あなたはそれを代替データベースとして使うべきではありません。そうではありません。

それで、あなたは言っている、セッションストレージを最小限に保ちますか?

繰り返しますが、それはあなたの決断です。パフォーマンス上の理由でデータをそこに保存することができます(データベースはほとんど常にRedisより遅いです)。情報を重複して保存したり、独自のキャッシュを実装したりすることができます。それらの上に。また、もしそれらが大きな負荷のもとで壊れると(そしてそうなるでしょう)、あなたは貴重な情報を失います。 RESTの考え方では、この場合に起こるのはクライアントが再び同じ(!)要求を送信し、それが今度はサービスを受けることです。

そのときどうする?

ここでは万能の解決策はありません。私は無国籍のレベルを選択し、それと一緒に行きたいと思います。セッションはある人々に愛され、他の人々に嫌われるかもしれませんが、彼らはどこにも行きません。リクエストがあるたびに、できるだけ多くの情報を送信します。しかし、ステートレス性をセッションがない、または毎回ログインすると解釈しないでください。 どういうわけかサーバーはあなたのことを知っていなければなりません; PHPセッションIDは1つの良い方法です、手動で生成されたトークンは別の方法です。

考えて決めましょう。デザインのトレンドを考えさせないでください。

0
dkellner

あなたがRESTfulなサービスを開発するとき、ログインするためにあなたはあなたのユーザーが認証されることを必要とするでしょう。考えられるオプションは、ユーザーがアクションを実行するたびにユーザー名とパスワードを送信することです。この場合、サーバはセッションデータをまったく格納しません。

もう1つのオプションは、サーバー上でセッションIDを生成してそれをクライアントに送信することです。したがって、クライアントはセッションIDをサーバーに送信し、それを使用して認証することができます。誰かがそのデータを手に入れた場合、ユーザー名とパスワードが変更されるまでユーザーを偽装することができるため、これは毎回ユーザー名とパスワードを送信するよりもはるかに安全です。その場合、セッションIDさえ盗まれる可能性があり、ユーザーが偽装される可能性があると言うかもしれませんが、その通りです。ただし、この場合、ユーザーの偽装は、セッションIDが有効な間にのみ可能です。

ユーザー名とパスワードを変更するためにRESTful APIがユーザー名とパスワードを期待している場合、誰かがセッションIDを使用してユーザーを偽装したとしても、ハッカーは実際のユーザーをロックアウトできません。

セッションIDは、ユーザーを識別してセッションIDに時間を追加するものの一方向ロック(暗号化)によって生成できます。これにより、セッションの有効期限を定義できます。

サーバーはセッションIDを格納する場合と格納しない場合があります。もちろん、サーバーがセッションIDを保存していると、質問で定義されている基準に違反します。ただし、セッションIDを特定のユーザーに対して検証できることを確認することだけが重要です。セッションIDを保存する必要はありません。電子メール、ユーザーID、およびお気に入りの色などのユーザー固有のプライベートデータを一方向に暗号化する方法を想像してみてください。これが最初のレベルで、暗号化文字列にユーザー名の日付を追加してウェイ暗号化その結果、セッションIDを受信したときに、ユーザーがどのユーザー名であると主張しているか、およびセッション時間が正しいかどうかを判断できるように、2番目のレベルを復号化できます。これが有効な場合は、暗号化をもう一度実行して文字列と一致するかどうかを確認することで、暗号化の最初のレベルを検証できます。それを達成するためにセッションデータを保存する必要はありません。

0
Lajos Arpad