J'ai une page Web qui affiche une grande quantité de données du serveur. La communication se fait via ajax.
Chaque fois que l'utilisateur interagit et modifie ces données (par exemple, l'utilisateur A renomme quelque chose), il indique au serveur de faire l'action et le serveur renvoie les nouvelles données modifiées.
Si l'utilisateur B accède à la page en même temps et crée un nouvel objet de données, il en informera à nouveau le serveur via ajax et le serveur reviendra avec le nouvel objet pour l'utilisateur.
Sur la page de A, nous avons les données avec un objet renommé. Et sur la page de B, nous avons les données avec un nouvel objet. Sur le serveur, les données ont à la fois un objet renommé et un nouvel objet.
Quelles sont mes options pour garder la page synchronisée avec le serveur lorsque plusieurs utilisateurs l'utilisent simultanément?
Des options telles que le verrouillage de la page entière ou le vidage de l'état entier à l'utilisateur à chaque modification sont plutôt évitées.
Si cela peut vous aider, dans cet exemple spécifique, la page Web appelle une méthode Web statique qui exécute une procédure stockée sur la base de données. La procédure stockée renverra toutes les données modifiées et pas plus. La méthode Web statique transmet ensuite le retour de la procédure stockée au client.
Modification de la prime:
Comment concevez-vous une application Web multi-utilisateurs qui utilise Ajax pour communiquer avec le serveur mais évite les problèmes de concurrence?
C'est-à-dire un accès simultané aux fonctionnalités et aux données d'une base de données sans aucun risque de corruption de données ou d'état
Réponses:
Aperçu:
Salut Raynos,
Je ne parlerai d'aucun produit en particulier ici. Ce que d'autres ont mentionné est un bon ensemble d'outils à examiner déjà (peut-être ajouter node.js à cette liste).
D'un point de vue architectural, vous semblez avoir le même problème que celui des logiciels de contrôle de version. Un utilisateur enregistre une modification sur un objet, un autre utilisateur souhaite modifier le même objet d'une autre manière => conflit. Vous devez intégrer les modifications apportées aux objets par les utilisateurs tout en étant en mesure de fournir des mises à jour en temps opportun et efficacement, en détectant et en résolvant les conflits comme celui ci-dessus.
Si j'étais à votre place, je développerais quelque chose comme ceci:
1. Côté serveur:
Déterminez un niveau raisonnable auquel vous définiriez ce que j'appellerais des "artefacts atomiques" (la page? Les objets sur la page? Les valeurs à l'intérieur des objets?). Cela dépendra de vos serveurs Web, de votre base de données et de votre matériel de mise en cache, du nombre d'utilisateurs, du nombre d'objets, etc. Ce n'est pas une décision facile à prendre.
Pour chaque artefact atomique ont:
Un serveur ou un composant pseudo-serveur capable de fournir efficacement des journaux de modifications pertinents à un utilisateur connecté. Observer-Pattern est votre ami pour cela.
2. Côté client:
Un client javascript qui est capable d'avoir une connexion HTTP de longue durée avec ledit serveur ci-dessus, ou utilise une interrogation légère.
Un composant de mise à jour d'artefacts javascript qui actualise le contenu des sites lorsque le client javascript connecté notifie des modifications dans l'historique des artefacts surveillés. (encore une fois, un modèle d'observateur pourrait être un bon choix)
Un composant javascript de validation d'artefact qui peut demander la modification d'un artefact atomique, essayant d'acquérir un verrou mutex. Il détectera si l'état de l'artefact avait été modifié par un autre utilisateur quelques secondes auparavant (latence du client javascript et des facteurs de processus de validation) en comparant l'ID de version de l'artefact du côté client et l'ID de la version de l'artefact du côté du serveur actuel.
Un solveur de conflit javascript permettant une décision humaine qui-change-est-la-bonne. Vous ne voudrez peut-être pas simplement dire à l'utilisateur "Quelqu'un était plus rapide que vous. J'ai supprimé votre modification. Allez pleurer.". De nombreuses options de différences plutôt techniques ou de solutions plus conviviales semblent possibles.
Alors, comment ça roulerait ...
Cas 1: diagramme de type de séquence pour la mise à jour:
Cas 2: Maintenant pour l'engagement:
Cas 3: pour les conflits:
Quelques mots sur les performances et l'évolutivité
Interrogation HTTP vs "push" HTTP
mise à l'échelle du backend
mise à l'échelle du frontend
ajustements "créatifs"
Eh bien, j'espère que cela peut être un début pour vos propres idées. Je suis sûr qu'il y a beaucoup plus de possibilités. Je suis plus que favorable à toute critique ou amélioration de cet article, le wiki est activé.
Christoph Strasen
la source
Je sais que c'est une vieille question, mais je pensais que j'interviendrais.
OT (transformations opérationnelles) semble être une bonne solution pour vos besoins d'édition multi-utilisateurs simultanés et cohérents. C'est une technique utilisée dans Google Docs (et a également été utilisée dans Google Wave):
Il existe une bibliothèque basée sur JS pour l'utilisation des transformations opérationnelles - ShareJS ( http://sharejs.org/ ), écrite par un membre de l'équipe Google Wave.
Et si vous le souhaitez, il existe un framework Web MVC complet - DerbyJS ( http://derbyjs.com/ ) basé sur ShareJS qui fait tout pour vous.
Il utilise BrowserChannel pour la communication entre le serveur et les clients (et je pense que la prise en charge de WebSockets devrait être en cours - il y était auparavant via Socket.IO, mais a été retiré en raison des problèmes du développeur avec Socket.io) Les documents pour débutants sont un peu clairsemé pour le moment, cependant.
la source
J'envisagerais d'ajouter un tampon modifié basé sur le temps pour chaque ensemble de données. Ainsi, si vous mettez à jour des tables de base de données, vous modifierez l'horodatage modifié en conséquence. À l'aide d'AJAX, vous pouvez comparer l'horodatage modifié du client avec l'horodatage de la source de données - si l'utilisateur est déjà en retard, mettez à jour l'affichage. Similaire à la façon dont ce site vérifie périodiquement une question pour voir si quelqu'un d'autre a répondu pendant que vous tapez une réponse.
la source
Vous devez utiliser des techniques push (également connues sous le nom de Comet ou Ajax inverse) pour propager les modifications à l'utilisateur dès qu'elles sont apportées à la base de données. La meilleure technique actuellement disponible pour cela semble être l'interrogation longue Ajax, mais elle n'est pas prise en charge par tous les navigateurs, vous avez donc besoin de solutions de secours. Heureusement, il existe déjà des solutions qui gèrent cela pour vous. Parmi eux, on trouve: orbited.org et le socket.io déjà mentionné.
À l'avenir, il y aura un moyen plus simple de le faire, appelé WebSockets, mais on ne sait pas encore quand ce standard sera prêt pour les heures de grande écoute car il y a des problèmes de sécurité concernant l'état actuel de la norme.
Il ne devrait pas y avoir de problèmes de concurrence dans la base de données avec de nouveaux objets. Mais lorsqu'un utilisateur modifie un objet, le serveur doit avoir une logique qui vérifie si l'objet a été modifié ou supprimé entre-temps. Si l'objet a été supprimé, la solution est, encore une fois, simple: il suffit de supprimer la modification.
Mais le problème le plus difficile apparaît lorsque plusieurs utilisateurs éditent le même objet en même temps. Si les utilisateurs 1 et 2 commencent à modifier un objet en même temps, ils effectueront tous les deux leurs modifications sur les mêmes données. Disons que les modifications apportées par l'utilisateur 1 sont d'abord envoyées au serveur tandis que l'utilisateur 2 est toujours en train de modifier les données. Vous avez alors deux options: vous pouvez essayer de fusionner les modifications de l'utilisateur 1 dans les données de l'utilisateur 2 ou vous pouvez dire à l'utilisateur 2 que ses données sont obsolètes et lui afficher un message d'erreur dès que ses données sont envoyées au serveur. La dernière option n'est pas très conviviale ici, mais la première est très difficile à mettre en œuvre.
L'une des rares implémentations à avoir vraiment réussi pour la première fois était EtherPad , qui a été acquis par Google. Je pense qu'ils ont ensuite utilisé certaines des technologies d'EtherPad dans Google Docs et Google Wave, mais je ne peux pas le dire avec certitude. Google ouvre également EtherPad, donc cela vaut peut-être le coup d'œil, en fonction de ce que vous essayez de faire.
Ce n'est vraiment pas facile de faire cela simultanément en éditant des trucs, car il n'est pas possible de faire des opérations atomiques sur le Web à cause de la latence. Peut - être que cet article vous aidera à en savoir plus sur le sujet.
la source
Essayer d'écrire tout cela vous-même est un gros travail, et il est très difficile de bien faire les choses. Une option consiste à utiliser un framework conçu pour garder les clients synchronisés avec la base de données et entre eux en temps réel.
J'ai trouvé que le framework Meteor le faisait bien ( http://docs.meteor.com/#reactivity ).
"Meteor embrasse le concept de programmation réactive. Cela signifie que vous pouvez écrire votre code dans un style impératif simple, et le résultat sera automatiquement recalculé chaque fois que les données changent dont dépend votre code."
"Ce modèle simple (calcul réactif + source de données réactive) a une large applicabilité. Le programmeur est sauvé de l'écriture des appels de désabonnement / réabonnement et de s'assurer qu'ils sont appelés au bon moment, éliminant ainsi des classes entières de code de propagation de données qui autrement obstrueraient votre application avec une logique sujette aux erreurs. "
la source
Je ne peux pas croire que personne n'ait mentionné Meteor . C'est un cadre nouveau et immature bien sûr (et ne prend officiellement en charge qu'une seule base de données), mais cela prend tout le travail difficile et la réflexion sur une application multi-utilisateurs comme le décrit l'affiche. En fait, vous ne pouvez PAS créer une application de mise à jour en direct multi-utilisateurs. Voici un bref résumé:
Meteor est assez simple pour que je vous suggère au moins d'y jeter un œil pour des idées à voler.
la source
Ces pages Wikipédia peuvent aider à ajouter une perspective à l'apprentissage de la concurrence et de l'informatique simultanée pour la conception d'une application Web ajax qui extrait ou est poussé des messages d' événement d' état ( EDA ) dans un modèle de messagerie . Fondamentalement, les messages sont répliqués vers les abonnés du canal qui répondent aux événements de modification et aux demandes de synchronisation.
Il existe de nombreuses formes de logiciels collaboratifs Web simultanés .
Il existe un certain nombre de bibliothèques clientes d'API HTTP pour etherpad-lite , un éditeur collaboratif en temps réel .
django-realtime-terrain de jeu implémente une application de chat en temps réel dans Django avec diverses technologies en temps réel comme Socket.io .
AppEngine et AppScale implémentent l' API AppEngine Channel ; qui est distincte de l' API Google Realtime , illustrée par googledrive / realtime-terrain de jeu .
la source
Les techniques de push côté serveur sont la voie à suivre ici. Comet est (ou était?) Un mot à la mode.
La direction particulière que vous prenez dépend fortement de votre pile de serveurs et de votre flexibilité. Si vous le pouvez, je jetterais un coup d'œil à socket.io , qui fournit une implémentation multi-navigateur de websockets, qui fournit un moyen très simple d'avoir une communication bidirectionnelle avec le serveur, permettant au serveur de pousser les mises à jour vers les clients.
En particulier, regardez cette démonstration de l'auteur de la bibliothèque, qui montre presque exactement la situation que vous décrivez.
la source