web-dev-qa-db-ja.com

MVCのセッション変数のベストプラクティスと推奨代替手段はありますか

さて、だれかがこれが「重複した」質問であると判断しようとする前に、まず始めに。私はSOに関する同様の質問に関する投稿のほとんどをレビューしましたが、これらのすべてを組み合わせたとしても、まだ決定的であるか、またはこの。

しかし、私は(投稿に基づいて)答えは要件の範囲に基づいていると最終的に決定したと言うことができます。しかし、これを考慮しても、意見はあまりにも多様であるため、私はこれをどのように扱うべきかを決定できません。

私の当面の要件は、1つのコントローラーからの変数データを多くのビューにわたって保持する必要があることです。具体的には、ショッピングカートのアイテム数を処理するコントローラーと対応するビューがあり、複数のビューにわたってそのデータを保持したいと考えています。私は_layoutビューがこのための最も論理的な選択だと考えています。

これで、_layoutビューから取得したSession変数に値を割り当てることで、このタスクを正常に完了しました。そのため、ユーザーがサイト内の任意の場所をナビゲートした場合でも、ショッピングカート内のアイテムの数は、サイトを離れるかチェックアウトが完了するまで保持されます。この場合、変数はコードでクリアされます。

私が読んだ投稿は、Cookieを優先してセッション変数から離れ、データベースにデータを保存することに偏っているように見えました。または、私がそれらを使用することを提案する意図的な目的のために、セッション変数は完全に使用しても良いと述べています。

私が読んだ他のことは、情報がサーバーに保存されているため、サイトのトラフィックが多い場合、セッション変数が全体的なパフォーマンスを妨げる可能性があることを示唆しています。

私は個人的にこの種の情報をデータベースに保存し、その後データベースにアクセスすることを正当化することはできません。これはサイトのパフォーマンスにも影響を与え、一時データの保存には少々やり過ぎだと思います。 TempData、ViewData、およびViewBagはデータの永続化では機能しないため、要件IMOの論理的な選択ではありません。

Session変数に適した別の選択肢がある場合(これが機能している場合)、それが何であるかを知りたいと思います。

最高の推奨事項を提供しようとする取り組みにおいて矛盾しているように見える2つの投稿は、少し混乱させられます。

短所: ASP.NET MVCでセッション状態の使用を避けるのは良い習慣ですか?はいの場合、理由と方法は?

長所: ASP.NET mvcでセッション変数を使用しても大丈夫、または(カートなど)いくつかのより良い代替手段があります

この質問(多くの異なるバリエーションで提示されていますが)には、私が結論付けることができる決定的な答えがないようです。

やりすぎずにこれを達成するためのより好ましい方法があれば、それが私が探している答えです。

Global.ascxアプリケーション開始セクションと連携してMVCフィルターの使用をどこかで読みましたが、これはおそらくコントローラーレベルで設定された変数と同じくらい静的変数としては適切ではないようです。

誰かがトピックに関する多くの多様な意見を押しつぶして(より良いWordがないため)、質問に対してより決定的な答えを提供できますか?多様な意見が彼らの場所を持っていると確信しており、私はそれらを信用しようとはしていません。しかし、決定的でおそらく全会一致の答えを持っている方が良いでしょう。次に、他の投稿を並べ替えて、アプリケーションに最適なものを判断します。

もちろん、この質問に決定的な答えがない場合、それを教えてください。他の投稿から自分の答えを導き出そうとします。

ありがとう

================================================== =========

回答に対する更新された応答の提供

キャッシュとCookieは応答の一般的な好みのようですが、同期が潜在的な問題になる可能性があるため、キャッシュを複数のWebサーバーで使用するのに理想的な候補ではないというステートメントにも注意しました。

ティムにクレジットを与えて、データベースストレージが最適化されており、ユーザーは後で戻って、中断したところから続行するオプションがあると述べています。

これは素晴らしい点ですが、確率について先見性を保ちます。一部のユーザーがデータベースに不要なデータを残して戻らない可能性があることを考えると、おそらく合理的です。

そのため、DBを最適化してクリーンな状態に保つには(「私にとって」同等の関連性があります)、これらの状況に対応するために設定された時間しきい値に基づいてこれらのレコードを自動的に期限切れにするメンテナンスタスクを実装する必要があります。メンテナンスタスクは疑う余地のないオプションではありませんが、一時的なストレージとして機能するという目的のためだけに、タスクにもう少し作業が追加されると思います。

それにもかかわらず、私はティムの勧告を尊重し、それが私の最初の意見にある程度反論する価値があると信じています。データベースは一時データを保存するための実行可能なオプションではないようです。そのため、おそらくチェックアウト後に、ショッピングカートなどのシナリオを想定して、データベースにデータを格納することが妥協策になると思います。前に述べたように、データはその後のアクセス時に永続的に追跡されるため、トランザクションの記録があります。しかし、さらに重要なことは、データベースに永続化するのに実際の関連性があるのは、これらのトランザクションのデータであることです。

また、セッションはデータベースよりも高速ですが、ただし、SessionStateBehavior属性を活用するなど、他のメカニズムによってある程度緩和できる警告があるにもかかわらず、単なる一例に過ぎません。

しかし...私は、エリックがDunning-Kruger Effectでポイントを家に追い込んだと思います。ただし、ここで提示された回答の内容と説明から。私は、回答した個人の専門知識が疑わしいとは真剣に疑っています。それにもかかわらず、私は全会一致の意見を得るという事実が私の側の合理的な期待よりも幾分高いかもしれないという事実に同意する傾向があります。

より具体的に探していたのは、さまざまなシナリオに快適に対応できるテクニックの一般的なコンセンサスでした。言い換えれば、私の特定のシナリオに対応するだけでなく、潜在的に重いトラフィックがある大規模な環境にスケーラビリティの要素を提供するものです。このようにして、プログラミングの変更は完全に軽減されるか、せいぜい最小限に抑えられます。

==================================================

フィードバックに基づく要約:

  1. セッション変数は、より小さなケースのシナリオに対応し、適切な場合に対応するように見えますが、エリックが非常に簡潔に述べたように、他の顕著な矛盾の中で持続性の懸念がある可能性があります。したがって、このオプションはスケーラブルなモデルには明らかに適合しません。

  2. キャッシングはセッション変数よりも望ましいですが、以前に指摘したように、Webサーバーファーム環境の潜在的な同期の複雑さのために、「最適な」スケーラブルオプションである必要はありません。それにもかかわらず、オプション。

  3. データベースストレージはスケーラブルですが、一時的な揮発性ストレージの目的では、定期的なクリーンアップが必要になるため、データベースの観点から見た場合、おそらく最もエレガントなオプションではありません。個人的には、私のキャリアの早い段階でデータベースの概念に強固な基盤を持っていることは、多くの開発者がおそらく同意するものではないでしょう。ただし、この目的でデータベースを使用すると、プログラマーの観点からはWeb開発で十分な場合があります。ただし、DALおよびDB開発の観点から、これは(私にとって)効率的なバックエンドを実施するために追加のDBタスクを強制する可能性があります。

  4. Cookieは、セッション変数とキャッシュの「望ましい」要素を組み合わせた素晴らしいオプションのようです。

==================================================

結論

答えに基づいて; COOKIESとCACHINGは、事後も持続性が必要な場合、データベースストレージと組み合わせて、全体的にベストプラクティスを提供するための一般的に適切な提案と思われます。提示されたもののスケーラビリティの潜在的に良い候補として。

2つの間の最終的な選択は、ストレージを必要とするデータの量と種類に基づいているようです(例えば、機密と非機密、およびクライアントが自分の側でデータを変更する懸念があるかどうか);クッキーがクライアントによって無効にされる可能性があるという事実に関するクッキーの特別な考慮事項に加えて。

明らかに、提供された回答から明確に指摘され、結論付けられたすべてのソリューションに適合するサイズはありませんが、スケーラビリティの観点からです。私は間違っているかもしれませんが、これらは利用可能な最良の選択肢のようです。

すべての応答が良好だからです。私はすべての投稿を有用であるとかなり評価し、Erikの答えを全体的にスケーラブルなソリューションとして受け入れます。ティムの回答も非常によく整理されており、簡潔だったと思うので、受け入れられた回答を複数選択できるといいのですが。

Guptaの回答も良かったのですが、以前の投稿を繰り返すのではなく、提案された回答をさらに詳しく説明したかったのです。

みんなありがとう!

45
Mark

大規模なグループのメンバーについて、満場一致で意見を述べることはありません。それはただの人間性です。その一部は Dunning-Kruger Effect に由来します。これは、誰かが対象について知らないほど、その対象の専門知識を過大評価する可能性が高いと述べています。言い換えれば、多くの人々は自分が何かを知っていると思うが、それは彼らがそれを知らないということだけを知っているからだ。その一部は、人々が異なる経験をしており、セッションに問題がない人もいれば、さまざまな状況にある人、またはその逆の人もいます...

そのため、答えが要件に大きく依存することを示唆する研究をバックアップするには、要件が何であるかを理解する必要があります。これがトラフィックの多いサイトで、Webファームに負荷分散されたサーバーがある場合は、できるだけセッションから遠ざけてください。もちろん、サーバーファーム環境(セッションサーバー、分散キャッシュサーバーなど)でさまざまな方法でセッションを共有することは可能ですが、セッションを回避することは、できる限りほとんど常に高速になります。

サイトが単一のサーバーであり、それ以上成長する可能性が低い場合。また、トラフィックパターンが比較的低い場合は、セッションが便利なオプションになる可能性があります。ただし、セッションは信頼性の低いストレージであり、いつでも消えてしまう可能性があることに常に注意する必要があります。アプリプールがリサイクルされると、セッションは終了します。キャッチされない例外がワーカープロセスにバブルアップすると、セッションが終了する場合があります。 IISが十分なメモリがないと考えると、設定されたタイムアウト値に関係なく、セッションがなくなる可能性があります。また、セッションが終了したという信頼できる通知を常に受け​​取ることはできません。 Session_Endイベントを発生させます。

別の問題は、セッションがシリアル化されることです。言い換えれば、IISは、一度に複数のスレッドがセッションに書き込むことを防ぎます。また、書き込み可能からオプトアウトしなかった場合、スレッドの実行中にセッションをロックすることでこれを行います。セッションのロック:これは、場合によっては深刻な問題を引き起こし、他の場合は単にパフォーマンスを低下させる可能性があります。そのメソッドで変更しない場合は、さまざまなメソッドを読み取り専用セッション属性でマークすることでこれを軽減できます。

最終的に、セッションを使用することを選択した場合は、可能な限り小さな短命のものにのみ使用し、不可能であれば、セッションが失われた場合にデータを「再生成」する方法で構築してください。たとえば、カートの例にあるアイテムの数を使用して、値があるかどうかを最初に確認し、ない場合は値を取り出してデータベースからロードするメソッドを作成できます。セッションから直接アクセスするのではなく、常にこのメソッドを使用して変数にアクセスします...この方法で、セッションが失われた場合、変数をリロードします。

しかし、これを言って...カート内のアイテムの数については、すべてのロードでCookieがページに渡されるので、この情報にはCookieを使用することを一般的に好むでしょう、これは小さな個別のデータ単位です。一般に、ユーザーが変更できないようにする機密データにはSessionを選択します。カート内のアイテムの数がそのルールに合わないのは当然です。

25

いつ

データベースは高度に最適化されています。ショッピングカートの数のような単純な値は、データベースによるキャッシュに適した候補であり、(できれば)完全に安価に計算できます。それは問題ではないかもしれません。

ただし、他のメカニズムを除外している場合は、小さなユーザーごとの値がセッションの実行可能な候補になります。

Cacheは、サイト全体の値、または一意のキーを持つユーザー固有の値に適しています。ただし、複数のWebサーバー間でキャッシュを同期することは困難です。プロセス外のセッション状態は、単一の場所(データベースまたは状態サーバー)に保存されるため、同期されたままになります。

もちろん、同期を維持するためのさまざまなオプションを備えた多くのサードパーティのキャッシュの選択肢があります。

カウントが一時的に保存される場所に関係なく、ショッピングカート自体をデータベースに保存して、ユーザーが後で戻って中断したところから続行できるようにする必要があると思います。

性能

プロセス外のセッション状態を使用する場合(たとえば、負荷分散環境および/またはセッションの耐久性を高めるため)、それはwillデータベースまたはコールをヒットしますプロセス外サービスですが、大きなオブジェクトグラフをシリアル化しない限り、呼び出しは比較的安価です。

セッションはリクエストごとに1回ロードされます。後続の読み取りアクセスは非常に高速です。

セッションへの書き込みは、負荷がなくてもパフォーマンスに悪影響を与える可能性があります。どうして?最新のアプリケーションのほとんどは非同期呼び出しを使用し、複数の非同期呼び出しがセッションを読み書きするHTTPハンドラー(ページ、コントローラーなど)にヒットすると、ASP.Netはセッションをロックしてアクセスをシリアル化します。これを避けるために、[SessionState( SessionStateBehavior.ReadOnly )]でコントローラーを飾ることができます

設計

これで、_layoutビューから取得したSession変数に値を割り当てることで、このタスクを正常に完了しました。

これは、懸念事項が混ざり合っているように見えます。つまり、基礎となるストレージメカニズムを認識できるビューを持っているようです。純粋主義の観点から、この値をビューモデルに設定するか、少なくともViewBagに入れます。実用的な観点からは、この方法で取得された1つまたは2つの値はおそらく何も害はありませんが、さらに大きくなるように注意してください。

Global.ascxアプリケーション開始セクションと連携してMVCフィルターの使用をどこかで読みましたが、これはおそらくコントローラーレベルで設定された変数と同じくらい静的変数としては適切ではないようです。

静的変数は完全に正当な用途がありますが、それらを完全に理解しないと、深刻な問題を引き起こす危険があります。

ASP.Netの静的変数に関する私の回答を参照してください。

10
Tim Medora

別の将来のセッションの代替:-

セッションで何かを保持すると、ASP.NET MVCの主要なルールに違反します。これらのオプションをセッションの代替として使用できます。

Asp.net(MVC)セッションがオブジェクトのボクシング解除を行う場合、サーバーに少し負荷がかかります。このアイデアを試してください

  1. キャッシュ:-セッションにリストまたは大きなデータのようなものを保存する方が、キャッシュに適しています。ユーザーセッションではなく有効期限をいつでも制御できます。

  2. アプリがJSON/Ajaxデータに依存している場合、html5で提供される何らかの機能(WebSQL、IndexDBなど)を使用できます。 Cookieを使用しないため、サーバーのワークロードを節約できます。

3
Anirudha Gupta