web-dev-qa-db-ja.com

アプリケーションをステートレスに保つ方法

これは複雑な質問かもしれませんが、私は無国籍についてよりよく理解しようとしています。

私が読んだことに基づいて、Webアプリケーションはステートレスである必要があります。つまり、各リクエストは独立したトランザクションとして扱われます。その結果、SessionとCookieは回避する必要があります(どちらもステートフルであるため)。より良いアプローチはトークンを使用することです。トークンはサーバーに何も保存されていないためステートレスです。

私が理解しようとしているのは、セッション用に保持されているデータ(ショッピングカート内のアイテムなど)がある場合、Webアプリケーションはどのようにステートレスになるのでしょうか。これらは実際にはデータベースのどこかに保存されており、定期的に削除されていますか? Cookieの代わりにトークンを使用している場合、これはどのように機能しますか?

そして、関連する質問として、主要なWebサイト(Amazon、Google、Facebook、Twitterなど)は実際にはステートレスですか?トークンまたはCookie(またはその両方)を使用していますか?

100
user253058

"Webアプリケーションはステートレスである必要があります"として理解する必要があります"Webアプリケーションはステートを保持する十分な理由がない限りステートレスである必要があります"。 「ショッピングカート」は、設計によるステートフルな機能であり、それを否定することはかなり逆効果です。ショッピングカートパターンの要点は、リクエスト間でアプリケーションの状態を保持することです。

couldショッピングカートを実装するステートレスなWebサイトとして想像する代替案は、ショッピングカートを完全にクライアント側に保ち、AJAXは、ユーザーがチェックアウトを行うと、呼び出してサーバーに一度に送信します。しかし、ユーザーが複数のブラウザタブを使用することを許可しておらず、実際に誰かが実際にそうするのを見たことはありません。 t誤ってタブを閉じたときに状態を保存するもちろん、localstorageを使用するなどの回避策はありますが、サーバーではなくクライアント上でのみ状態を再取得できます。

ページビュー間でデータを保持する必要があるWebアプリケーションがある場合は、通常、セッションを導入することでそれを行います。リクエストが属するセッションは、Cookieまたはすべてのリンクに追加するURLパラメータのいずれかによって識別できます。 Cookieは、URLをより使いやすくし、ユーザーが誤ってURLをセッションIDと共有するのを防ぐため、推奨されます。ただし、フォールバックとしてURLトークンを持つことは、Cookieを非アクティブにするユーザーにとっても重要です。ほとんどのWeb開発フレームワークには、これをすぐに実行できるセッション処理システムがあります。

サーバー側では、セッション情報は通常データベースに保存されます。サーバー側のインメモリキャッシングはオプションです。応答時間を大幅に改善できますが、異なるサーバー間でセッションを転送することはできません。したがって、フォールバックとして永続的なデータベースが必要になります。

主要なWebサイト(Amazon、Google、Facebook、Twitterなど)は実際にはステートレスですか?トークンまたはCookie(またはその両方)を使用していますか?

ログインできますか?その後、タブを閉じてサイトに再度アクセスしても、まだログインしていますか?もしそうなら、彼らはセッション間であなたの身元を維持するためにクッキーを使用しています。

97
Philipp

Webアプリケーションがステートレスであることは事実です。ただし、セッション変数、Cookie、およびトークンがすべてクライアント(Webブラウザー)に格納されている場合は、これらに違反しません。これらはリクエストのパラメータにすることができます。

簡略化したモデルは次のとおりです。

Web Browser (has state) <-> Web Server (stateless) <-> Database (has state)

これはSoftware Engineering Stack Exchangeで機能します。私が入力しているこの回答は、私のWebブラウザーの状態の一部です。それが唯一の場所である限り、私以外は誰もアクセスできません。しかし、私がPost your Answer私のブラウザはそれをWebサーバーに送信します。 Webサーバーは、独自の状態を使用せずに投稿を処理します。私は自分のブラウザとデータベースから私が誰であるかを学習します。投稿のチェックとデータベースへの追加が完了すると、Webサーバーはすぐに自分のことを忘れてしまいます。

それがステートレスの意味です。サーバーはこれを記憶する責任はありません。それはその仕事ではありません。

これには多くの利点があります。 Webサーバーにメモリリークがある場合、そのメモリフットプリントが増大してはならないため、検出可能です。 Webサーバーがクラッシュした場合、私の身元はそれと一致しません。誰かがサービス拒否攻撃を行おうとすると、Webサーバーはセッション間で状態を割り当てないため、Webサーバーの状態リソースを使用して攻撃を実行することはできません。これはすべて、Webサーバーを安定させることを目的としています。このように、実行を開始すると、実行を継続します。

確かに、私はデータベース内のリソースを消費していますが、これらのリソースはまず、データベースを野生の羊毛質のWebから保護するために頼りになる安定したもの、つまりステートレスなビジネスルールを適用するWebサーバーによって、私の許容量と照合されます。

59
candied_orange

ステートフル性は必ずしも悪いことではありませんが、ステートフルアプリとステートレスアプリの違いを理解する必要があります。つまり、ステートフルアプリは現在のセッションに関する情報を保持し、ステートレスアプリは保持しません。ユーザーアカウントの一部として永続的に保存される情報は、セッションに保存される場合とされない場合がありますが、ユーザーアカウントに関連する情報を保存するだけでは、アプリケーションはステートフルになりません。ステートフル性では、サーバーが、クライアントブラウザーが維持しているものを超えて、現在のユーザーのセッションに関する情報を維持する必要があります。たとえば、クライアントは認証され、JSESSIONID Cookieが与えられ、リクエストごとにサーバーに送信されます。サーバーがこのJSESSIONIDに基づいてアプリケーションのセッションスコープにデータの保存を開始すると、ステートフルになります。

無国籍

ステートレスとは、サーバーとクライアントがユーザーセッションに関する現在の情報を維持していないことを意味します。クライアントとサーバーは、リクエスト間の認証を提供するためになんらかの形式のトークンを使用できますが、他の現在の情報は保存されません。そのようなソリューションの典型的な使用例は、ほとんどのユーザー(新しい消費者)が情報を消費するが、サイトに戻る情報を生成しないニュースサイトです。このような場合、サイトは現在のユーザーセッションに関する情報を保持する必要はありません。サイトは引き続きCookieを使用してユーザーを識別し、そのユーザーによるサイトの使用に関する情報を格納しますが、記録されたすべてのものはトランザクションである可能性があるため、それでもステートレスと見なされる場合があります。ユーザーがクリックしたリンク。サーバーによって記録される可能性がありますが、ユーザーセッションでは維持されません。

サーバーのステートフル性

サーバーでは、ステートフルアプリが現在のユーザーに関する状態情報を保存します。このアプローチでは通常、Cookieを使用してユーザーのシステムを識別し、リクエスト間でサーバー上で状態を維持できるようにします。アプリケーションのコンテキストに応じて、セッションは認証される場合と認証されない場合があります。ステートフルサーバーアプリには、ユーザーの状態情報をサーバーにキャッシュして、検索とページの応答時間を高速化するという利点があります。マイナス面としては、セッションスコープに情報を保存するのはコストがかかり、大規模な場合は非常に多くのリソースを消費します。また、ハッカーがセッション識別子をハイジャックしてユーザーセッションを盗むための潜在的な攻撃ベクトルも作成します。ステートフルサーバーアプリには、予期しないサービスの中断からユーザーセッションを保護するという課題もあります。サーバー障害。この問題の一般的な解決策は、サーバーマシンのクラスター全体でセッションをクラスター化することですが、ここでも、大規模な場合、すべてのマシンですべてのセッションをクラスター化することはすぐに非現実的です。

クライアントのステートフル性

JavaScriptとsessionStorageのような最新のブラウザーテクノロジーを使用して、アプリケーションはユーザーセッションに関する状態情報をユーザーのデバイスに簡単に保存できるようになりました。全体として、アプリケーションはまだステートフルと見なされますが、状態を維持するジョブはクライアントに移されました。このアプローチには、サーバー上の状態を維持するよりも(Webアプリのメンテナーにとって)大きな利点があり、各ユーザーは事実上、自分の状態を維持しており、サーバーインフラストラクチャに負担がかかりません。 Webスケールでは、この種のアーキテクチャの選択は、ハードウェアと電気のコストに大きな影響を与えます。サーバー上で状態を維持するために、文字通り年間数百万ドルの費用がかかる可能性があります。クライアントの状態を維持するシステムに移行すると、年間数百万ドルを節約できます。

トークン対Cookie

Cookieは、クライアントデバイス/ブラウザの識別子として機能します。あらゆる種類の物を格納するために使用できますが、通常、CFMLアプリのCFID/CFTOKENなどの何らかの形式の識別子を格納します。 Cookieは、ユーザーのブラウザーに長期間存続するように設定できるため、ブラウザーセッション間でアプリの認証を維持するなどのことが可能になります。 Cookieをメモリのみに設定して、ユーザーがブラウザを閉じるとCookieが期限切れになるようにすることもできます。

トークンは通常、サーバー上で生成され(暗号化を使用して情報をスクランブルします)、クライアントに渡され、後続のリクエストでサーバーに返される、ユーザーに関する特定の種類の情報です。それらは、リクエストとレスポンスのヘッダーで渡される場合があります。これは、単一ページアプリケーションでは一般的なパターンです。理想的には、リクエスト/レスポンスごとに新しいトークンが生成されるので、トークンが傍受されて攻撃者によって後で使用されることはありません。

単一ページのアプリとクライアントの状態

SPAを使用すると、状態情報がクライアントブラウザにロードされ、そこで維持されます。状態が変化したとき。ソーシャルメディアアカウントに更新を投稿すると、クライアントはその新しいトランザクションをサーバーに中継します。この場合、サーバーはその更新をデータベースのような永続的なデータストアに保存し、更新に基づいてサーバーと同期する必要がある情報(クライアントのIDなど)をクライアントに中継します。

クライアントに状態を保存するこのパターンは、いくらか使いやすいアプリケーションを使用しながらサーバーから切断できるという点で、オンライン/オフラインエクスペリエンスに利点をもたらします。 Twitterはこの例の良い例であり、Twitterサーバーアプリから切断されている場合でも、Twitterフィードに読み込まれているクライアント側を確認できます。このパターンは、サーバーとクライアント間の同期にも複雑さをもたらします。これは、それ自体が全体の主題です。ソリューションの複雑さは、クライアントの状態を維持できることのトレードオフです。

クライアントのステートフル性により、Webアプリは従来のデスクトップアプリのように感じ、動作します。デスクトップアプリとは異なり、通常、ブラウザーのクライアントセッションに読み込まれるすべてのアカウント情報はありません。そうすることは多くの場合非現実的であり、悪い経験を生み出すでしょう。 Gmailボックス全体をブラウザにロードしようとしていると想像できますか?代わりに、クライアントは、表示しているラベル/フォルダーや、表示しているそのフォルダー内のメールのリストのどこにあるかなどの情報を保持します。維持する状態情報と必要に応じて要求する状態のバランスをとることは、このパターンのもう1つのエンジニアリング上の課題であり、これもまた、実用性と優れたユーザーエクスペリエンスの提供との間のトレードオフを表しています。

ショッピングカートなど

ショッピングカートのような詳細については、それは本当にソリューションに依存します。ショッピングカートは、サーバー上のデータベースに保存することも、サーバーのセッションスコープにのみ保存することも、クライアントに保存することもできます。ログインしたユーザー用の永続的なショッピングカートと匿名ユーザー用の「一時的な」カートがありますが、これらのカートはある程度永続的です。

Googleのようなもの、つまり実際には同じブランドの下に存在するさまざまなアプリケーションの集まりについて話すとき、それらはおそらく共通のアーキテクチャを共有しておらず、それぞれがユーザーのニーズに最も適合する方法で構築されています。サイトの構築方法を学びたい場合は、ブラウザーで開発者ツールを開いて見てください。 Cookieを確認し、ネットワークトラフィックを監視して、動作を確認します。

この答えが少し混乱している場合は申し訳ありませんが、ステートフルネスは複雑なテーマです。

16
Robert Munn

セッションとCookieを回避する必要はありません。ステートレスWebアプリケーションでそれらを使用できます。

JavaとRuby on Rails。の間には大きな違いがあります。Javaアプリはセッションを使用してセッションをメモリに保存しますキーはCookieに保存されます。これはユーザーの状態とショッピングカートをすばやく取得できます。ただし、セッションでは常に同じサーバーにアクセスする必要があります。

Railsアプリは、ユーザーIDを署名済みの暗号化されたCookieに保存します。改ざんすることはできません。ページをロードすると、Webアプリはデータベースから状態、ユーザー、およびショッピングカートをフェッチします。これは遅いですが、重要なのは任意のインスタンスをヒットできます!これにより、インスタンスを自由に再起動、スケーリング、シャットダウンできます。とても便利。また、Redisのようなメモリ内の共有キャッシュデータベースを使用すると、処理速度を上げることができます。または、ショッピングカートが十分に小さい場合は、Cookieに保存することもできます。

したがって、巧妙な手法でステートレスを実現し、自由にスケーリングできる機能を追加できます。

6
Chloe

ステートレスについて言及する場合-例RESTful HTTPサービス-サーバー側での状態の保存を回避しようとしています。せいぜい、データベースやバックエンドのその他の永続ストレージに状態を保存しないことも含まれます。 明確にするために、私は一般にデータではなく状態について話しています。一部の人は物事を混同しているようです。

ステートレス通信には、特にスケーラビリティと可用性に関していくつかの利点があります。

より良いアプローチはトークンを使用することです。トークンはサーバーに何も保存されていないためステートレスです。

そのとおりです(特定の認証および承認プロトコルの場合)。トークンは(それ自体ではなく)、ユーザーの認証またはアクションの承認に必要なすべての情報をリクエスト内に提供できます。例として [〜#〜] jwt [〜#〜] を見てください。

私が理解しようとしているのは、セッション用に保持されているデータ(ショッピングカート内のアイテムなど)がある場合に、Webアプリケーションをどのようにステートレスにすることができるのでしょうか。これらは実際にはデータベースのどこかに保存されており、定期的に削除されていますか? Cookieの代わりにトークンを使用している場合、これはどのように機能しますか?

ショッピングカートの例について。セッションやCookieを使用せずに、すべてのカートアイテムをクライアント側に保存しても問題ありません。 smashingmagazine.com で例を見つけることができます。しかし、Cookieを使用してステートレスショッピングカートを実現することもできます(少なくとも、品揃えがそれほど大きくなく、4 KBのストレージで十分な場合)。

誤解しないでください。それは、ショッピングカートをステートレスに実装する必要があるという意味ではありません。 Amazonや他の大きなオンラインショッピングプラットフォームでは、ステートフルなショッピングカートの実装を使用しています。これは、スケーラビリティなどの技術的な非機能要件に合わせるよりも、ユーザーエクスペリエンスと使いやすさが重要であるためです。

通常、トークンはカートアイテムなどの情報の保存には使用されません。これらは、ステートレスな認証と承認に使用されます。

そして、関連する質問として、主要なWebサイト(Amazon、Google、Facebook、Twitterなど)は実際にはステートレスですか?トークンまたはCookie(またはその両方)を使用していますか?

認証にCookieとトークンのどちらを使用しているか尋ねる場合、答えは両方を使用することです。ユーザーの場合、ほとんどがテクニカルクライアントのCookieで、ほとんどがトークンが使用されます。

5
Paul Wasilewski

protocolはステートレスです。

ただし、このプロトコルを使用するアプリケーションがステートレスである必要があるとは限りません。

ここでは、違いをよく説明するいくつかの関連するStackOverflow回答を示します。

5
sideshowbarker