8
votes

Nibernate Session Management?

Tout d'abord, laissez-moi donner une brève description du scénario. J'écris un jeu simple où tout le travail est fait du côté serveur avec un client léger pour les joueurs pour y accéder. Un joueur se connecte ou crée un compte et peut ensuite interagir avec le jeu en se déplaçant autour d'une grille. Lorsqu'ils entrent dans une cellule, ils doivent être informés des autres joueurs de cette cellule et de la même manière, d'autres acteurs de cette cellule seront informés de ce joueur qui le pénétrait. Il y a beaucoup d'autres interactions et actions pouvant avoir lieu, mais cela ne vaut pas la peine de partir en détail sur eux car il s'agit simplement de la même chose. Lorsqu'un joueur se déconnecte ensuite dans ou si le serveur descend et revient, tout l'état de jeu doit persister, bien que si le serveur se bloque, peu importe si je perds 10 minutes de changements.

J'ai décidé d'utiliser NHibernate et une base de données SQLite, alors j'ai beaucoup lu sur NHibernate, à la suite des tutoriels et écrivez quelques-uns d'applications, et je suis parfaitement confus quant à la façon dont je devrais y aller!

La question que j'ai est: Quelle est la meilleure façon de gérer mes sessions? Juste de la petite somme que je comprends, toutes ces possibilités sautent-moi:

  • avoir une seule session qui a toujours été ouverte que tous les clients utilisent
  • avoir une seule session pour chaque client qui se connecte et le rince périodiquement
  • Ouvrez une session à chaque fois que je dois utiliser l'une des entités persistées et la fermer dès que la mise à jour, l'insertion, la suppression ou la requête est complète
  • a une session pour chaque client, mais gardez-la déconnectée et ne le reconnectez que lorsque je dois l'utiliser
  • comme ci-dessus, mais gardez-le connecté et ne le déconnectez que après une certaine période d'inactivité
  • Gardez les entités détachées et ne les attachent que toutes les 10 minutes, disons, pour commettre les modifications

    Quel type de stratégie devrais-je utiliser pour obtenir des performances décentes étant donné qu'il pourrait y avoir de nombreuses mises à jour, des insertions, des suppressions et des requêtes par seconde de centaines de centaines de clients à la fois, et ils doivent tous être cohérents? < / p>

    Une autre question plus petite: comment devrais-je utiliser des transactions de manière efficace? Est-ce que c'est bien pour chaque changement d'être dans sa propre transaction ou est-ce que cela va bien performer lorsque j'ai des centaines de clients essaient de modifier les cellules dans la grille? Devrais-je essayer de déterminer comment réduire les mises à jour similaires et les placer dans une seule transaction, ou cela va être trop compliqué? Est-ce que j'ai même besoin de transactions pour la plupart?


0 commentaires

4 Réponses :


0
votes

Je viserais à garder tout en mémoire, puis à modifier le journal ou à prendre des instantanés périodiques hors ligne.


1 commentaires

J'ai déjà réfléchi à cette solution et cela va être beaucoup plus compliqué, dupliquant essentiellement une grande partie de la fonctionnalité de la fiabilité qu'une base de données me donne. C'est pourquoi j'ai décidé d'aller avec une base de données en premier lieu, plutôt que d'écrire toutes les données aux fichiers plats ou à quelque chose.



10
votes

J'utiliserais une session par demande sur le serveur et une transaction par session. Je ne voudrais pas optimiser la performance avant que l'application soit mature.

Réponse à vos solutions:

  • Avoir une session unique qui a toujours été ouverte que tous les clients utilisent: vous aurez des problèmes de performance ici car la session n'est pas en sécurité et que vous devrez verrouiller tous les appels à la session.
  • Vous avez une session unique pour chaque client qui se connecte et le rinçait périodiquement: vous aurez des problèmes de performance ici car toutes les données utilisées par le client seront mises en cache. Vous verrez également des problèmes avec des données rassisées du cache.
  • Ouvrez une session à chaque fois que je dois utiliser l'une des entités persistées et la fermer dès que la mise à jour, l'insertion, la suppression ou la requête est terminée: vous n'aurez aucun problème de performance ici. Un inconvénient est possible des problèmes de catastrophe ou de corruption de problèmes, car les déclarations SQL connexes ne sont pas exécutées dans la même transaction.
  • Demandez à une session pour chaque client, mais gardez-la déconnectée et ne le reconnectez que lorsque je dois l'utiliser: NHibernate a déjà une gestion de connexion intégrée et qui est déjà très optimisée.
  • comme ci-dessus, mais conservez-le connecté et ne le déconnectez que après une certaine période d'inactivité: entraînera des problèmes car la quantité de connexions SQL est limitée et limitera également la quantité d'utilisateurs de votre application.
  • Gardez les entités détachées et ne les attachez que toutes les 10 minutes, disons, pour commettre les changements: causera des problèmes en raison de données stables dans les entités détachées. Vous devrez suivre les changements vous-même, ce qui vous permet de vous retrouver avec un morceau de code qui ressemble à la session elle-même.

    Il serait inutile d'aller dans plus de détails maintenant, car je répéterais simplement les manuels / tutoriels / livres. Lorsque vous utilisez une session par demande, vous n'aurez probablement pas de problèmes dans 99% de l'application que vous décrivez (et peut-être pas du tout). La session est une classe légère non threadsafe, que pour vivre très courte. Lorsque vous voulez savoir exactement comment la session / la gestion de la connexion / de la gestion de la mise en cache / de la transaction, je recommande de lire un manuel d'abord et de poser des questions plus détaillées sur les sujets incertains.


4 commentaires

Je n'essaie pas de l'optimiser; J'essaie simplement de comprendre ce que les différentes méthodes sont de le faire, de ce qu'elles sont généralement bonnes ou pas bonnes pour, dans quelle mesure elles échouent et fonctionnent, etc. avant de se rendre à un. Il s'agit de m'assurer que je ne fais rien de stupide et de choisir une solution raisonnablement judicieuse. Non-réglage de la performance. Donc, quant à votre réponse, qu'entendez-vous par «demande» - quelle «demande»? Vous voulez dire chaque fois qu'un joueur fait quelque chose?


Oui avec demande, je veux dire "chaque fois qu'un joueur fait quelque chose" ou "chaque appel du client au serveur"


Après avoir lu les modifications que vous avez ajoutées plus tard, j'ai une question sur quelque chose que vous avez dit. En ce qui concerne avoir une session unique par client, je pensais que NHibernate garantit que des méthodes telles que l'ISession.Find ne renverra jamais les données obsolètes. Deuxièmement, vous semblez être décourageant à l'aide de la reconnexion / déconnexion car "NHibernate a déjà une gestion de connexion intégrée", mais le manuel utilise à l'aide d'un exemple de concurrence appelé "longue session avec la version automatique".


1. Vous pouvez empêcher de renvoyer des données obsolètes de plusieurs manières, mais vous ne pouvez pas profiter de la mise en cache alors. Vous ne devriez pas utiliser ISession.Find dans des scénarios normaux. 2. La gestion de la connexion dans le manuel Il n'ya pas de connexions de base de données, mais des connections de session pour gérer des objets détachés avec une session de vie en ne les détachant pas, mais en recréant à la place. 3. Je ne comprends pas pourquoi vous envisagez de longues sessions de vie dans le scénario de jeu en premier lieu.



1
votes

Lire le ' iSessionFactory ' sur cette page de la documentation de NHibernate. L'ISession S est censé être une seule-filetée (c'est-à-dire non sur le thread-coffre-fort) qui signifie probablement que vous ne devriez pas le partager à travers les utilisateurs. IsessionFactory doit être créé une fois par votre application et ISession S doit être créé pour chaque unité de travail. N'oubliez pas que la création d'un ISession S ne donne pas nécessairement à ouvrir une connexion de base de données. Cela dépend de la configuration de la stratégie de mise en commun de la connexion de votre session.

Vous voudrez peut-être aussi consulter la documentation de Hibernate sur Session et transaction .


1 commentaires

Les liens sont morts.



0
votes

avoir lu via Nibernate Meilleures pratiques avec ASP.NET , là sont de très bons conseils ici pour un début. Comme mentionné, il est déjà très prudent avec une isession car il n'est pas threadsafe, alors gardez cela à l'esprit.

Si vous avez besoin de quelque chose d'un peu plus complexe, jetez un coup d'œil sur le Nibernate.burrow Projet de contributions. Il indique quelque chose comme "le véritable burrow de puissance fournit est qu'une conversation de terrier peut s'étendre sur plusieurs demandes HTTP".


0 commentaires