JeuWeb - Crée ton jeu par navigateur
Opérations en Hors ligne - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Opérations en Hors ligne (/showthread.php?tid=1357)

Pages : 1 2 3 4 5 6 7


RE: Opérations en Hors ligne - christouphe - 28-04-2011

@jean-baptiste: C'est là que tu fais fausse route. Il ne faut pas mettre à jour TOUS les joueurs mais seulement ceux qui sont en interaction pour garder les données cohérentes (pillages ou autre).

Un joueur tranquille dans son coin qui ne se fait pas attaquer, tu n'as besoin de recalculer ses ressources que lors de sa reconnexion, et pas avant.


RE: Opérations en Hors ligne - Sephi-Chan - 28-04-2011

Plus qu'une affaire de performances, c'est une question d'architecture. Le synchrone fait moins bien que l'asynchrone, ça tient moins la charge.
Après, je n'ai pas connaissances d'outils connus qui permettent de mettre en place des choses comme des files de production d'unités, des flux de ressources entrantes et sortantes, etc. Ce doit être un besoin très rare dans l'industrie pour qu'on trouve si peu d'outils.

Ce serait génial qu'un ingénieur crée ce genre de système ! Smile Mais il faudrait coucher les besoins sur papier.


Sephi-Chan


RE: Opérations en Hors ligne - atra27 - 30-04-2011

En s'y mettant a plusieurs... un truc communautaire sa serai pas mal...

Des idées de cdcf?


RE: Opérations en Hors ligne - Sephi-Chan - 30-04-2011

Hélas, ça demande un peu plus que des connaissances avancées en développement Web.

Imagine un serveur qui pilote des files de production. Depuis notre script, on s'y connecte (socket TCP, donc programmation réseau), on lui envoie des commandes : crée la queue Q1, ajoute-y l'élement E1 qui commence à T1 et dont la production durera D1. Quand c'est fini, notifie-le moi (par socket ou par HTTP ? Les deux ?) en m'envoyant le nom de la file et l'élément terminé.

Ça implique d'avoir un daemon, donc un processus avec une longue durée de vie et dont la consommation en mémoire doit être très bien maîtrisée (pas de fuite).

Ça implique également de tenir la charge et être extensible (scalability) : faire évoluer 10 queues et 100 000, ce n'est pas pareil (bien sûr, le matériel importe). Ça doit éventuellement pouvoir être distribué (utiliser plusieurs machines).

Le logiciel serveur doit pouvoir recevoir des commandes (pour ajouter des éléments en queue, modifier les queues, suspendre temporairement un élément, etc.) et en émettre (signaler au client qu'une production est terminée).

Rien qu'avec ça, il y a de quoi occuper ! Smile

Il y a moyen de construire ce serveur à l'aide de composants existants et relativement accessibles : le daemon peut être réalisé avec des outils comme NodeJS (Javascript), Twisted (Python), EventMachine (Ruby) ou autre. Le stockage des queues peut-être assuré par Redis, MongoDb ou autre (éventuellement une base de données SQL, même si je doute que ce soit un choix pertinent).

Après, le point qui me paraît le plus obscur, c'est la progression de la file. C'est le point sur lequel je suis le moins à l'aise (je passe probablement à côté de plusieurs solutions aux problèmes).

Est-ce qu'on fait monter la file de manière synchrone de façon à pouvoir consulter sa progression en temps réel ? En ayant par exemple un processus par file (100 000 files = 100 000 processus ?) ? Ou plusieurs processus "workers" qui prennent chacun en charge plusieurs files ?

Ensuite, est-ce que ces processus se contentent alors d'augmenter l'état de progression de l'élément actif (s'il y en a un) de chaque file au fil du temps (plus pratique si on veut supporter des fonctionnalités comme l'arrêt ou le ralentissement temporaire de la vitesse de production) ? Ou bien ils font un bête sleep d'une durée équivalente à la durée de production de l'élément puis le marquent comme terminé (probablement plus performant) ?

Voilà, c'est là que j'aurais besoin de l'avis de personne qualifiées dans ce domaine : les différentes façon de compter le temps au sein d'un daemon. Les possibilités doivent être nombreuses mais je n'en entrevois qu'une partie dont j'ignore l'efficacité.

Le problème : je ne sais pas à qui demander de l'aide. :/


RE: Opérations en Hors ligne - niahoo - 30-04-2011

avec erlang il est possible d'arriver assez rapidement à un prototype.

quand l'application se lance, on crée un processus de type serveur qui écoute sur un port TCP ou des requêtes HTTP.

Quand on lui demande de créer une queue, il lance un nouveau processus de type queue qui va se mettre en attente d'éléments, et va stocker l'identifiant de ce processus dans un dictionnaire key/value qui associera une queue à son processus.
Il associe également à la queue (même dictionnaire ou un autre) des infos de la requête qui lui permettent de renvoyer les infos (priciplament élément terminé). les informations comme queue créée, élément ajouté sont renvoyées en réponse de la requête HTTP directement (possible en TCP ?). ces infos sont une adresse de callback, une commande à lancer, etc.

Quand on lui demande d'ajouter un élément à une queue, on lui envoie un identifiant d'élément, une durée, et la queue à laquelle ajouter cet élément.
Le serveur récupère l'identifiant de processus dans le dictionnaire grâce à l'identifiant de queue et lui envoie l'élément à ajouter et la durée.


Le processus queue entretient un état : occupé / disponible / ...
Quand on lui envoie un élément, il crée un identifiant interne et stocke le couple identifiant/élément à la fin de sa liste de tâches puis on lance une fonction de vérification.

fonction de verif: si l'état actuel est disponible ET si la file n'est pas vide, on passe en occupé, on chope le premier élément de la liste avec son identifiant et on envoie le tout à un timer. sinon on ne fait rien.

Quand un timer se termine, il renvoie au processus queue une info lui indiquant l'identifiant d'élément préalablement passée, et que l'élément concerné à fini sa production. Le processus queue relaie l'information au processus pricipal (qui stocke les couples queue/processus), supprime l'élément correspondant à l'identifiant de sa liste, passe en disponible et lance la fonction de vérification.

Le timer est un autre processus, donc il avance de namière concurrente avec les processus queue et le processus serveur global.

Le processus principal qui à reçu l'information de la réponse va utiliser les infos préalablement stockées (adresse de callback, une commande à lancer, etc.) pour notifier le propriétaire de la queue qu'un élément vient de se terminer.


Si on compte lancer 100 000 qeueues, et bien que des couple id/pid ne soient pas très lourds, vaut mieux faire un backup régulier de tout ça en base de données plutot que de tout garder en mémoire vive.

Idem pour les éléments en construction. Mais si toute la logique de la construction des éléments est gérée ailleurs que dans l'appli, elle ne fait vraiment qu'associer des identifiants à des processus et des timers à des identifiants, donc l'impact mémoire est très très petit.

On peut faire un backup en base de données régulièrement, par exemple sauvegarder la file d'une que à chaque fois qu'un élément se termine, et sauvegarder la liste des queues.

Ainsi, au démarrage de l'application, si la table des queues n'est pas vide, le serveur global relance immédiatement des queues avec leur nom enregistré, les queues une fois lancées vont voir dans la base si une file n'existe pas déjà. (Il faut pour cela communiquer aux queues leurs propres identifiants). Et si une file existe elle les rechargent.

Avec ça, même si le système entier crashe une fois par minutes, si les temps de production ne sont pas inférieurs à quelques secondes ça reste du 'soft real time'


____

Via le protocole HTTP, faire un client pour cette appli en PHP est une affaire de minutes. en ruby je ne sais pas mais je suppose que c'est aussi simple, sinon plus.

__________

J'écris tout ce flood pasque je réfléchis en même temps, j'ai prévu d'implémenter un truc du style pour mon propre jeu mais je ne sais pas s'il sera possible d'en faire un truc standalone.


RE: Opérations en Hors ligne - Sephi-Chan - 30-04-2011

Tout à fait Niahoo, on peut prototyper ce serveur assez simplement.
En revanche, j'aimerai savoir comment tu penses implémenter les timers (et leur callback) ?

Je pense essayer d'écrire un prototype avec Node et Redis.


RE: Opérations en Hors ligne - niahoo - 30-04-2011

Et bien je l'ai dit, pour les timers tu lances un processus timer qui, à la fin du timer, fait un callback vers le processus qui l'a lancé.


RE: Opérations en Hors ligne - Sephi-Chan - 30-04-2011

Ouais mais comment tu fais ça ?


RE: Opérations en Hors ligne - niahoo - 30-04-2011

heu ben pour moi ce serait, dans la fonction qui lance la construction.

Time = <le temps pour construire l'élément>,
IDElem = <l'id interne de mon élément>,
{ok, Tref} = timerConfusedend_after(Time, self(), {contruction_finished, IDElem}),
et là j'associe l'id interne de mon élément à Tref, (qui est une référence au timer) pour pouvoir l'annuler.


RE: Opérations en Hors ligne - atra27 - 01-05-2011

Quelqu'un prét a proposer une implémentation fonctionnelle?