2009-07-19 25 views
7

まず、シナリオの簡単な説明をします。私はシンプルなゲームを書いていますが、プレイヤーがアクセスするためのシンクライアントを使って、サーバー側でほとんどすべての作業が完了しています。プレイヤーはログインしたり、アカウントを作成したりして、グリッドの周りを移動してゲームと対話することができます。彼らがセルに入ると、そのセルの他のプレイヤーに知らされるべきであり、同様に、そのセルの他のプレイヤーには、そのプレイヤーがそれに入ることが知らされるでしょう。他にもたくさんのインタラクションやアクションがありますが、その詳細については詳しく説明する必要はありません。プレーヤーがログアウトして戻ったり、サーバがダウンして復帰したりすると、すべてのゲーム状態が持続するはずですが、サーバがクラッシュしても10分ほどの変更が失われても問題ありません。NHibernateセッション管理?

私はNHibernateとSQLiteデータベースを使用することに決めました。そこで、NHibernateでチュートリアルやサンプルアプリケーションを書いて、多くのことを読んできました。

質問:私のセッションを管理するにはどうすればよいですか?ちょうど私が理解して、少量から、これらすべての可能性は私に飛び出し:

  • は常に、すべてのクライアントが
  • 接続し、定期的にフラッシュクライアントごとに単一のセッションを持っているを使用することを開いています、単一のセッションを持っていますそれは
  • 私は永続化されたエンティティのいずれかを使用して、更新、挿入、削除、またはクエリが完了すると直ちに閉じる必要があるたびにセッションを開く
  • クライアントごとにセッションを持ちますが、私がそれを使用する必要があるときにそれを再接続する
  • サムE上記のように、それが接続され続けるとのみ変更をコミットするために、たとえば、それらを10分ごとに付けるだけ
  • は実体が外れて保管する非アクティブの一定期間の後に、それを切断し、

戦略のどのような種類べき一度に何百ものクライアントから毎秒多くの更新、挿入、削除、およびクエリが発生する可能性があることを考えれば、まともなパフォーマンスを得るために使用します。

もう少し小さい質問:効率的な方法でトランザクションをどのように使うべきですか? 1回の変更がすべて自分のトランザクションになるのはいいですか、何百ものクライアントがグリッド内のセルを変更しようとしているときにうまく実行できませんか?同様のアップデートを一括して一括処理する方法を理解して、単一のトランザクション内に配置するか、それとも複雑になるのでしょうか?ほとんどの場合、トランザクションが必要なのでしょうか?

答えて

8

私はサーバーへの要求ごとにセッションを使用し、セッションごとに1つのトランザクションを使用します。私はアプリが成熟する前にパフォーマンスを最適化しません。あなたのソリューションへ

回答:

  • は、常にすべてのクライアントが使用することを開いています、単一のセッションを持っている:セッションはスレッドセーフではなく、あなたがにすべてのコールをロックする必要がありますので、あなたはここにパフォーマンスの問題を持っていますセッション。
  • 接続して定期的にフラッシュするクライアントごとに1つのセッションがあります。クライアントで使用されるすべてのデータがキャッシュされるため、ここでパフォーマンスの問題が発生します。また、キャッシュから失効したデータに関する問題も表示されます。
  • 永続化されたエンティティのいずれかを使用して、更新、挿入、削除、またはクエリが完了するとすぐにセッションを開く必要があります。ここではパフォーマンスの問題は発生しません。関連するSQL文が同じトランザクション内で実行されないため、同時実行性またはデータの問題が発生する可能性があります。
  • クライアントごとにセッションがありますが、接続を切断しておき、使用する必要があるときに再接続するだけです.Hibernateにはすでにビルドイン接続管理があり、すでに非常に最適化されています。
  • 上記と同じですが、一定時間使用しないと接続を解除するだけです.SQL接続の量が制限され、アプリケーションのユーザー数が制限されるため問題が発生します。
  • エンティティを分離したままにして、変更をコミットするために10分ごとに添付します。分離されたエンティティの失効したデータのために問題が発生します。変更内容を自分で追跡する必要があります。その結果、セッション自体のようなコードが完成します。

私はマニュアル/チュートリアル/ブックを繰り返すので、今はもっと詳しく説明することは無意味です。リクエストごとにセッションを使用する場合、記述するアプリケーションの99%で問題が発生することはほとんどありません(おそらくまったくないかもしれません)。セッションはスレッドセーフなクラスではなく、非常に短いライブです。セッション/接続/キャッシュ/トランザクション管理の仕組みを正確に知りたいときは、最初にマニュアルを読んでから、不明な主題に関する詳細な質問をすることをお勧めします。

+0

私はそれを最適化しようとしていません。私は、いろいろな方法が何をしているのか、それが一般的に良いか悪いのか、どれくらいうまく調整して実行しているのかなどを把握しようとしています。それは、私が馬鹿なことをしないで、合理的に賢明な解決策を選ぶことを確実にすることです。パフォーマンスチューニングではありません。 あなたの答えは、 "要求"とは何を意味しますか? "要求"は何ですか?プレイヤーが何かするたびにあなたは意味しますか? – IRBMe

+0

リクエストありあり「プレイヤーが何かするたびに」または「クライアントからサーバーに電話するたびに」 – Paco

+0

あなたが後で追加した編集内容を読んでいると、あなたが言ったことに関する1つの質問があります。クライアントごとに1つのセッションを持つことに関しては、NHibernateは、ISession.Findのようなメソッドが失効したデータを返すことはないと考えました。第二に、 "NHibernateはすでにビルドイン接続管理を持っている"ので、Reconnect/Disconnectを使用していないようですが、マニュアルでは "自動バージョン管理の長いセッション"という並行処理の例で使用しています。 – IRBMe

0

私はすべてをメモリに保存し、ジャーナルを変更するか定期的にオフラインのスナップショットを取ることを目指します。

+0

私はすでにこのソリューションについて考えていましたが、データベースが提供する信頼性のために多くの機能を本質的に複製しています。そのため、すべてのデータをフラットファイルなどに書き込むのではなく、最初にデータベースを使用することにしました。 – IRBMe

1

NHibernateのドキュメントのpageの 'ISessionFactory'を読んでください。 ISessionはシングルスレッド(つまりスレッドセーフではない)であることを意味します。これはおそらく、ユーザー間で共有するべきではないということを意味します。アプリケーションごとにISessionFactoryを1回作成し、各作業単位ごとにISessionを作成する必要があります。 ISessionを作成しても必ずしもデータベース接続が開かれるとは限りません。それはあなたのSessionFactoryの接続プーリング戦略がどのように構成されているかによって異なります。

また、HibernateのドキュメントSession and Transactionを参照してください。

0

NHibernate Best Practices with ASP.NETを読んだことがありますが、ここには非常に良いヒントがあります。すでに述べたように、スレッドセーフではないので、ISessionには非常に注意が必要です。そのことを覚えておいてください。

さらに複雑なものが必要な場合は、NHibernate.Burrow contribプロジェクトをご覧ください。 「Burrowの会話は複数のHTTPリクエストにまたがることがBurrowが提供する本当のパワー」のようなものです。