IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

[AJAX] multithreads et sessions PHP ne font pas bon ménage !


Sujet :

JavaScript

  1. #1
    Membre à l'essai
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Octobre 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Eure et Loir (Centre)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Octobre 2006
    Messages : 23
    Points : 17
    Points
    17
    Par défaut [AJAX] multithreads et sessions PHP ne font pas bon ménage !
    Bonjour, bonjour, bonjour tout le monde !!

    Voilà, je viens vous parler d'un problème que je rencontre actuellement avec AJAX multithreads (mode asynchrone en fait).

    Voici ce qui se passe:
    Des éléments de mon site envoient plusieurs requêtes XMLHTTPRequests en parallèle, vers un même script PHP qui récupère les variables de session de l'utilisateur courant. Il arrive de temps à autre que la fonction "session_start" plante car elle n'a pas le droit d'ouvrir le cookie de session... car il y a un lock dessus :-(

    Donc, j'imagine que ce problème survient quand 1 session_start survient trop rapidement après un autre session_start pour le même utilisateur.

    Du coup, j'ai le sentiment que le mariage AJAX et sessions PHP ne font pas bon ménage. Est-ce que je me trompe ? Est-ce que quelqu'un a déjà eu ce problème ? L'a-t-il résolu ? Voici quelques questions que je me pose.

    Je n'ai rien trouvé sur ce sujet... alors si quelqu'un a déjà rencontré ce problème, qu'il n'hésite pas à partager ses griefs avec moi ;-), Et s'il a trouvé une solution: MERCI de m'en faire part !!


    Merci en tout cas de m'avoir lu ;-)

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2005
    Messages : 147
    Points : 165
    Points
    165
    Par défaut
    >Donc, j'imagine que ce problème survient quand 1 session_start survient trop rapidement après un autre session_start pour le même utilisateur.

    c'est ça, php lock les sessions et le problème existe également avec les frames.

    ce qui m'étonne c'est que tu dises que ça plante, l'expérience que j'en ai serait plutôt que php attend sagement que la session se libère (php5.x), ajax ou pas ajax.

    pour améliorer les choses il est possible de libérer la session dès que tu as fini de la manipuler plutôt que d'attendre la fin du script :

    http://fr2.php.net/manual/fr/functio...rite-close.php

    ce type de problème avec les frames :
    http://fr3.php.net/manual/fr/functio...tart.php#70235

  3. #3
    Membre à l'essai
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Octobre 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Eure et Loir (Centre)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Octobre 2006
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Et bien en fait, en terme de plantage, ça n'est pas exactement ça... c'est plutôt que mon script continue, mais sans les variables de sessions, du coup... j'ai des warning d'accès à des méthodes d'objet qui ne sont pas des objets, etc. ;-)

    En tout cas, merci beaucoup pour ce tuyau, j'vais voir si ça rétablit les choses ;-)

    Je te tiendrai au courant, si tu veux ^^

  4. #4
    Membre à l'essai
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Octobre 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Eure et Loir (Centre)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Octobre 2006
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Bon, alors en définitive, session_write_close ne résoud pas complètement mon problème, même s'il l'a énormément amélioré.
    Tout ceci vient du fait que le script qui pose problème fait un session_start, récupère l'objet "Site Internet", puis, gère la requête de l'utilisateur, retourne le résultat, puis.... l'objet est à nouveau sauvegardé dans les variables de session. Donc forcément, je ne peux pas faire un session_write_close avant la fin du traitement, qui malheureusement peut prendre un peu de temps.

    Du coup, voici comment j'ai résolu TOTALEMENT mon problème:

    une table sessions (session_id, session_status) dans la base de donnée. Le session_id est stocké désormais dans mon objet site et toute requête construite depuis l'interface client, envoie ce fameux session_id au script serveur. Du coup, je peux récupérer le statut du cookie stocké dans la base de donnée.
    S'il est "locked", alors je fais une boucle qui fait patienter le script 500ms avant de revérifier si le lock a été libéré (toujours dans la base de données).

    C'est une solution qui ralentit quelque peu les traitements, c'est certain, mais qui au moins, à le mérite de ne jamais planter. De plus, si jamais votre base de données est inaccessible (serveur down)... on peut gérer le problème sans soucis et avertir l'utilisateur que le serveur ne semble pas répondre. Il faut bien penser aussi à ne pas boucler indéfiniment, et prévoir une sortie avec message d'erreur également.

    Voici le code utilisé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    require_once("../functions.inc.php");
    //Début de l'inclusion de toutes les classes nécessaires avant le début de la session
    require_once("../config.inc.php");
    $classes_dir = getAbsolutePath()."classes";
    if(is_dir($classes_dir))
    {
    	$dh= opendir($classes_dir);
    	while ($fichier = readdir ($dh))
    	{
    	    if ($fichier != "." && $fichier != ".." && !is_dir($fichier) && stripos($fichier, ".class.php") > 0)
    		{
     
    	        require_once(getAbsolutePath()."classes/".$fichier);
    	    }
    	}
    	closedir ($dh);
    }
    else
    {
     
    }
    //fin de l'inclusion des fichiers .class.php
     
    //Récupération des paramètres de la requête utilisateur
    $object = $_POST["object"];
    $id     = $_POST["id"];
    $invoke = $_POST["invoke"];
    $params = $_POST["params"];
    $session_id = $_POST["session_id"];
     
     
    //début du traitement du script avec gestion du lock de session
    if($session_id != "")
    {
    	dbConnect();
    	$query = "select session_id, session_status from sessions where session_id = '".$session_id."'";
    	$resId = runQuery($query);
    	$resCount = resCount($resId);
    	if($resCount > 0)
    	{
    		$session = moveNext($resId);
    		if($session["session_status"] == "locked")
    		{
    			$query = "select session_id, session_status from sessions where session_id = '".$session_id."'";
    			while($resCount > 0 && $session["session_status"] == "locked")
    			{
    				usleep(500);
    				$resId = runQuery($query);
    				$resCount = resCount($resId);
    				if($resCount > 0)
    				{
    					$session = moveNext($resId);
    				}
    			}
    		}
    		$query = "update sessions set session_status='locked' where session_id='".$session_id."'";
    	}
    	else
    	{
    		$query = "insert into sessions (session_id, session_status) values ('".$session_id."', 'locked')";
    	}
    	runQuery($query);
    	session_start();
    	$internetSite = $_SESSION["site"];
     
    	echo $internetSite->updateSite($object, $id, $invoke, $params);
    	$_SESSION["site"] = $internetSite;
    	session_write_close();
    	$query = "update sessions set session_status='unlocked' where session_id='".$session_id."'";
    	runQuery($query);
    }
    Je n'ai pas fini le script... mais dans l'idée, ça sera ça que j'utiliserai...

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2005
    Messages : 147
    Points : 165
    Points
    165
    Par défaut
    >Et bien en fait, en terme de plantage, ça n'est pas exactement ça... c'est plutôt que mon script continue, mais sans les variables de sessions, du coup... j'ai des warning d'accès à des méthodes d'objet qui ne sont pas des objets, etc.

    bizarre, je n'ai pas du tout ce comportement, le script bloque à session_start() et attend.

    mais dit moi si je me trompe.
    ta solution revient à effectuer des requêtes synchrones vu que tu vas traiter un script avant d'en entamer un second.

    si c'est le cas il existe la solution d'un pool de requête ajax à mettre en place côté client et qui me semble un peu plus simple.
    l'idée serait de mettre en attente une requête tant que la précédente n'est pas terminée.

    sinon il existe aussi une autre méthode pour traiter les sessions qui ne produit aucun lock (donc à chacun de gérer les problèmes d'intégrité), mais necessite la compilation de php avec "with-mm=DIR" (elles seront gérées en mémoire partagée) :

    http://www.zend.com/tips/tips.php?id=164&single=1

    +

  6. #6
    Membre à l'essai
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Octobre 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Eure et Loir (Centre)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Octobre 2006
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Oui, en effet, c'est quasiment du synchrone, sauf si lors de mon script, je libère la session avant la fin de l'éxécution totale du script en cours. On pourrait très bien imaginer que dans mon script, que je récupère l'objet Site Internet, que j'appelle les différentes méthodes qui conviennent, que je sauvegarde l'objet, libère la session et continue de faire d'autres traitement de présentation ou que sais-je... du coup, mon script 1 n'est pourtant toujours pas terminé que mon script 2 peut néanmoins débuter.

    Autre différence avec le mode synchrone de l'objet XMLHTTRequest, ce dernier bloque le navigateur côté client tant qu'il n'a pas reçu la notification de fin de traitement côté serveur.... empêchant alors toute navigation.... ça a souvent tendance à freezer le navigateur, ce qui est à proscrire. Quitte à empiler des actions dans un stack quelconque, j'péfère autant que ça se fasse côté serveur.

    Maintenant, je reste néanmoins tout à fait d'accord avec toi sur le fait que OUI, c'est bien du synchrone.

    Merci pour les infos concernant la récupération partagé des cookies de sessions. Mais malheureusement, puisque mon projet est destiné à être hébergé sur un serveur mutualisé classique... je ne sais pas si je pourrais trouver l'environnement adéquat qui me permettrait de faire ça.

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2005
    Messages : 147
    Points : 165
    Points
    165
    Par défaut
    Autre différence avec le mode synchrone de l'objet XMLHTTRequest, ce dernier bloque le navigateur côté client tant qu'il n'a pas reçu la notification de fin de traitement côté serveur.... empêchant alors toute navigation.... ça a souvent tendance à freezer le navigateur, ce qui est à proscrire. Quitte à empiler des actions dans un stack quelconque, j'péfère autant que ça se fasse côté serveur.
    ok, mais j'aurais besoin d'explications sur le freeze dont tu parles (si tu veux bien ).

    comme le sujet m'interresse j'ai mis en ligne une démo de gestion d'un pool xhr :
    http://fassnet.net/spool/

    c'est simple (trois boutons => trois actions qui correspondent à un sleep de temps différent en php), et j'ai mis en parallèle les demandes et les réponses des requêtes.

    si je pars de la page alors qu'il y a une requête en cours, la connection stop (testé grâce à l'écriture dans un fichier) et il peut résulter une erreur de la part d'xhr.

    pour l'instant le seul reproche que je peux faire à cette méthode concerne la difficulté de gérer les tokens de spoof.

    comme je l'ai dit l'exemple est simple, mais je ne vois pas pourquoi il y aurait un freeze de la part du navigateur.

    +

  8. #8
    Membre à l'essai
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Octobre 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Eure et Loir (Centre)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Octobre 2006
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Attends, j'comprends pas bien ton exemple...

    Est-ce que tu utilises les requêtes xhr en mode parallèle, avec une gestion d'attente côté serveur?

    Utilises-tu des sessions ?


    En fait, lorsque je me suis intéressé à AJAX la première fois, j'ai tout de suite été attiré par ces nouveaux forum en PHP, qui ne nécessitaient pas de rechargement de la page. C'est typiquement le genre d'application qui illustre bien le côté pratique d'envoi d'information vers le serveur et de récupération d'information sans rechargement d'une page. Seulement, il se trouve que de temps à autre, j'avais des blocages du navigateur. En cherchant un peu, j'me suis rendu compte que toutes les requêtes xhr étaient gérées de façon synchrones.... et puis, j'ai changé ça en asynchrone et là... je n'avais plus de freeze du tout.

    Enfin, bon... j'suis pas un expert, donc j'me trompe certainement !

  9. #9
    Membre expert
    Avatar de FremyCompany
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    2 532
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 2 532
    Points : 3 289
    Points
    3 289
    Par défaut
    J'ai jamais fait de PHP, mais bon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $continue=true;
    while ($continue) {
    try {
        session_start();
        $continue=false;
    } catch ($ex) { sleep(100); }
    }
    Fremy
    Pour vos développements Web et une navigation agréable, le tout gratuit :
    1) IE 8 + IE7Pro (Si vous ne connaissez pas IE7Pro, essayez !)
    2) FF 3 + Web Developper Toolbar + AdBlockPlus + FireBug + GreaseMonkey

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2005
    Messages : 147
    Points : 165
    Points
    165
    Par défaut
    Est-ce que tu utilises les requêtes xhr en mode parallèle, avec une gestion d'attente côté serveur?
    Utilises-tu des sessions ?
    non pour les deux, la majorité se passe côté client, le serveur envoie juste une chaîne de caractères après un sleep().
    je me suis dit que t'avais trouvé une solution à ton problème alors j'ai un peu dévier de la question initial

    j'utilise un tableau côté client qui stock les objet xhr au fure à et à mesure pour les envoyer dès que le précédent a fini.

    pour les sessions je pourrais les utiliser que ça ne changerais pas grand chose.

    >Enfin, bon... j'suis pas un expert, donc j'me trompe certainement !

    ou tu as certainement raison, alors je cherche à comprendre...


    @fremy
    php n'est pas objet à la base, donc ses fonctions ne retournent pas d'exceptions à part certains objet depuis la v5 .
    session_start ne retourne même pas false en cas de lock (mais apparemment cette fonction ne réagit pas chez moi comme chez tanhys...)

  11. #11
    Membre à l'essai
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Octobre 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Eure et Loir (Centre)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Octobre 2006
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par tthierry
    session_start ne retourne même pas false en cas de lock (mais apparemment cette fonction ne réagit pas chez moi comme chez tanhys...)
    Exactement !! J'suis en V5, et d'ailleurs, dans les docs, ils spécifient bien que "session_start" retourne TOUJOUR true, que la fonction ait réussi ou non.... ce que je trouve un peu léger mais bon... peut-être que ça changera avec la V6 ;-)

    Sinon, pour en revenir aux objets xhr... j'utilise aussi un tableau dans lequel je mets toutes mes requêtes les unes derrière les autres... ça me permet effectivement de bien traiter, toutes les requêtes tranquillement !



    Enfin, bon... dans tous les cas, j'dirais ceci: mieux vaut quand même éviter les traitements côté client... on ne sait jamais ;-)

  12. #12
    Membre expert
    Avatar de FremyCompany
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    2 532
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 2 532
    Points : 3 289
    Points
    3 289
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while (!$varDeSession) {
       // ... 
    }
    Fremy
    Pour vos développements Web et une navigation agréable, le tout gratuit :
    1) IE 8 + IE7Pro (Si vous ne connaissez pas IE7Pro, essayez !)
    2) FF 3 + Web Developper Toolbar + AdBlockPlus + FireBug + GreaseMonkey

  13. #13
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2005
    Messages : 147
    Points : 165
    Points
    165
    Par défaut
    >J'suis en V5

    tu testerais pas tes scripts sous windows ?

    si c'est le cas est ce que via ton hébergeur session_start() attend ou passe comme tu l'as déja indiqué ?

  14. #14
    Membre à l'essai
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Octobre 2006
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Eure et Loir (Centre)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Octobre 2006
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par tthierry
    >J'suis en V5

    tu testerais pas tes scripts sous windows ?

    si c'est le cas est ce que via ton hébergeur session_start() attend ou passe comme tu l'as déja indiqué ?
    Oui, en effet, pour l'instant, je développe tout ça chez moi, sous Windows ;-)

    Je verrai effectivement si cela passe ou attend chez mon hébergeur ;-)

Discussions similaires

  1. [DisplayTag] Tri et pagination ne font pas bon ménage
    Par tiboudchou dans le forum Taglibs
    Réponses: 4
    Dernier message: 31/03/2010, 12h22
  2. rich:calendar, DIV et IE ne font pas bon ménage
    Par chotana dans le forum JSF
    Réponses: 1
    Dernier message: 20/04/2009, 17h16
  3. C++ et VB6 ne font pas bon ménage!
    Par Tuizi dans le forum C++
    Réponses: 6
    Dernier message: 18/07/2008, 10h03
  4. Le wifi et Club Internet ne font pas bon ménage!
    Par Ylias dans le forum La taverne du Club : Humour et divers
    Réponses: 5
    Dernier message: 20/08/2007, 10h30
  5. Réponses: 2
    Dernier message: 12/08/2007, 15h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo