Avatar billede steffen Nybegynder
10. marts 2010 - 17:37 Der er 21 kommentarer

Parallel afvikling af requests i den samme session i PHP?

Jeg vil gerne høre om der er nogen har en opskrift til at tillade at to scripts kan udføres simultant i den samme session?

Det ser ud til at PHP har implicit session locking pr. default, og jeg synes ikke jeg har held af at implementere nogle af de metoder der burde kunne slå denne sessionslåsning fra.

Men for at demonstrere hvad jeg er ude efter, så prøv at 1) oprette dette script (det udskriver 60 lodrette streger med et sekunds mellemrum):

<?php
print "[";

for($i = 0; $i < 100; $i++){
  $spaces.="<!-- bufferme -->";
} // for

//and then

for($i = 0; $i < 60; $i++){
  for($ii = 0; $ii < 200000; $ii++){
    //do something slow here
  } // for
  sleep(1);
  print "$spaces|";
  flush();
} // for

print "]";

?>

Dernæst, 2) åbn to browsertabs i din browser og 3) kald scriptet fra begge.

Hvis det virker som jeg håber at kunne demonstrere, så køres kun ét af scriptene ad gangen.

Jeg har prøvet forskellige ting, fx at overskrive save_handler med session_set_save_handler (http://theserverpages.com/php/manual/en/function.session-set-save-handler.php), men det giver ikke rigtigt nogen effekt, låsningen synes effektiv lige meget hvad jeg gør. Dvs. scriptet to browsertabs bliver afviklet "i serie" - først den ene, og når den så er færdig, så først dernæst påbegynder den anden.

Jeg har fundet et par sider på nettet der tilsyneladende omhandler problemet:

http://thwartedefforts.org/2006/11/11/race-conditions-with-ajax-and-php-sessions/

http://www.tonymarston.co.uk/php-mysql/client-clones.html

http://blog.perplexedlabs.com/2009/10/05/php-custom-session-handler/

Men altså ingen af dem med en opskrift jeg har været heldig med at kunne få til at du.

Så mit spørgsmål er egentligt bare: Hvilke linier mangler i mit script for at jeg kan køre to instanser af scriptet samtidigt, i to tabs i min browser (dvs. i samme session)?
Avatar billede Slettet bruger
10. marts 2010 - 18:21 #1
Hmm... Jeg har aldrig stødt på dette problem før, men kan forestille mig, at det faktisk er en funktion ("It's a feature, not a bug"). Ellers kunne to scripts jo prøve at modificere samme sessionsvariabel på samme tid, og derved skabe fejl og sikkerhedsproblemer.

if($isadmin) { $_SESSION['userlevel']++}

Den eneste måde at afhjælpe det på, jeg lige kan finde er, selv at lave en session handler med alt hvad der hører med, men det er besværligt og helt ligeså usikkert som PHPs sessions ville have været med funktionen indbygget.
Avatar billede steffen Nybegynder
10. marts 2010 - 19:34 #2
"Den eneste måde at afhjælpe det på, jeg lige kan finde er, selv at lave en session handler ..."

Super! Det lyder spændende - hvordan gjorde du?

Selv om jeg overrider phps default session handler med session_set_save_handler(), gør det ikke rigtigt nogen forskel for mig. Og jeg har efterhånden prøvet en hel del forskellige måder, skulle jeg hilse at sige :-)

Kan du lokkes til at paste det kode du fik til at køre i parallel, i samme session?
Avatar billede Slettet bruger
10. marts 2010 - 21:19 #3
Jeg tror ikke PHP's session-handle er muligt at manipulere til dette, lige meget hvor meget man prøver (med mindre man selvfølgelig er C++-hacker, men så kan man jo alt).
Til gengæld kan man lave sin helt egen session handler, selvom det er besværligt. Jeg har desværre ikke lavet en kode til dette, men kan da hurtigt forklare en grundlæggende model:

1) Definer funktioner til læsning og skrivning af sessioner, samt  i database
2)Tjek om brugeren har sat en session-cookie og:
2a) Tjek om dette id er udløbet. Hvis ikke, læs id'ets variabler fra databasen eller
2b) Opret et nyt, ubrugt session-id
3) Send en session cookie til brugeren. Dette gøres under alle omstændigheder for at sikre, at den ikke udløber
4) Fyld en global variabel med sessionsvariablerne
5) Brug de prædefinerede funktioner til at ændre på sessionsvariablerne
Avatar billede steffen Nybegynder
10. marts 2010 - 22:52 #4
Som jeg lige læser din kommentar #3, så handler den om at implementere en session handler fra scratch.

Men jeg vil i egentligt bare gerne se helt bort fra sessioner, dvs. se væk fra cookies, headers, synkroniseret tilgang til variable, http-protokol-spindsfindigheder osv osv .... alt det man normalt skal vride hovedet af led for at tage højde for :-)

Mit spørgsmål handler stadig bare om noget parallel afvikling af noget php-kode, så simpelt som muligt, i to tabs i en browser.
Avatar billede Slettet bruger
10. marts 2010 - 23:31 #5
Jeg forstår ikke helt dit spørgsmål, og især ikke, hvorfor sleep() skal blandes ind i det. Sleep laver netop en masse rod med (klient)sessioner. I praksis vil du heller aldrig have brug for funktionen.

Ønsker du alligevel at få dit script til at virke, kan du prøve at indsætte funktionskaldet session_write_close(); før dit sleep-kald. Det burde fjerne den sammenhæng du ser.
Avatar billede steffen Nybegynder
10. marts 2010 - 23:43 #6
Jeg har også læst at session_write_close(); skulle virke mange steder, men jeg har ikke haft held af det - har du en kodestump du har kunnet få til at du?

For mig gør det ingen forskel om jeg erstatter sleep med andre konstruktioner heller - har du kunnet konstatere en forskel?
Avatar billede repox Seniormester
11. marts 2010 - 09:31 #7
Du har jo egentlig allerede i dine artikler fundet svaret; race conditions giver ballade og der skal derfor tages højde for dem.
Det eneste du opnår ved at implementere en af de strukturer som er nævnt i artiklen er en 'løsere' form for kontrol at tilgangen til en session. Det er jo ikke nødvendigvis en god ting - udover at det aldrig vil kunne løse dit 'problem', for fuldstændig som kimsey0 er inde på, så er det en feature - ikke en bug. Det er en feature som sikrer dig at du ikke laver race conditions i dine applikationer.

For at tage udgangspunkt i dit eget script, så sker der faktisk det at i det samme du starter scriptet (i din første tab), session_start() initialiseres, så låses din session til den pågældende tråd (script). Den resource frigives først i det øjeblik scriptet afsluttes. Når den resource er frigivet vil du opleve at scriptet (fra den anden tab) starter. Meget logisk og ganske korrekt.
Avatar billede steffen Nybegynder
11. marts 2010 - 10:29 #8
Jeg kan nu godt lide "friheden til at vælge selv" - jeg har ikke nogen session_start() i mit script - og hvis du antyder at den fyres af automatisk, så vil jeg egentligt bare gerne vide hvordan jeg overtaler php til at lade være :-)
Avatar billede repox Seniormester
11. marts 2010 - 10:38 #9
Du misser pointen lidt... udgangspunktet var dit eget script; selvom du ikke bruger sessions i scriptet vil sessions fungere som jeg beskriver.

Det du oplever med at dit specifikke script ikke vil eksekvereres af flere processer samtidig kan jeg ikke nikke genkendende til.
Jeg kan have adskille 'tabs' åbne og se at scriptet kører som forventet - altså samtidig uden jeg skal vente på at nogle af processerne bliver færdige for at den næste proces kan startes.

Dit spørgsmål gik mere på behandlingen af sessions; i tilfælde af du ville anvende sessions i scriptet måtte du vente på at din session blev frigivet til at blive skrevet i på ny.
Avatar billede repox Seniormester
11. marts 2010 - 10:40 #10
Og for lige at knytte en kommentar til konceptet om "friheden til at vælge selv" i forhold til race conditions, så hænger verden jo sammen på den måde at selvom jeg godt kan lide idéen om at flyve som supermand, så er der nogle naturlove der gør at jeg ret basalt ikke er i stand til det. Samme koncept gør sig også gældende inden for programmering; der er nogle ting du ikke kan, grundet det omkringliggende miljøs begrænsninger.
Avatar billede steffen Nybegynder
11. marts 2010 - 11:05 #11
"Det du oplever med at dit specifikke script ikke vil eksekvereres af flere processer samtidig kan jeg ikke nikke genkendende til."

Ydrk - det lyder rigtigt spændende! Er det på en php-instans jeg kan nå fra nettet? Et php-info dump fra den ville jeg helt sikkert sætte meget pris på hvis du vil af med det.

Ang. "friheden til at vælge selv" tænker jeg mere på at jeg bare gerne selv vil have lidt indflydelse på hvor jeg gerne vil have mutual exclusiveness og jeg ikke vil, ikke andet. Og at høre at du har en opsætning der kører i to tabs samtidigt, giver allerede temmeligt meget blod på tanden i den retning :-)
Avatar billede repox Seniormester
11. marts 2010 - 11:26 #12
Du kan se scriptet eksekveres på min server her:
http://err0r.dk/test/spm904132.php

En video af min test her:
http://rapidshare.com/files/361872845/spm904132.avi

Min phpinfo() kan ses her:
http://err0r.dk/test/phpinfo.php
Avatar billede steffen Nybegynder
11. marts 2010 - 13:25 #13
Øijs, det var jo lækkerier.

Fik afprøvet scriptet på et par hosts mere, og fandt en der opførte sig ligesådan (yay!). Og det viser sig at forskellen lå i en php setting - om "session.auto_start" er sat til "on".

Den er nu slået fra ... og nu virker det søreme :-)

- i ie, safari og andre - men ikke i firefox. Heller ikke mod dit site, herfra. Og det er tilsyneladende lige meget om jeg har pipelining settings slået til eller fra osv.

Hvilken opførsel får du i firefox? (Mange tak for den fine video i øvrigt, det var jo luksus at gå videre på :-)).
Avatar billede steffen Nybegynder
11. marts 2010 - 13:27 #14
Er gået i google-mode på firefox'en - har fundet et par links der lyder lidt til at det er en opførsel andre er stødt i på firefox før - men har ingen forklaring/løsning endnu:

http://www.bigresource.com/Tracker/Track-php-2tit55Ew/

http://www.bigresource.com/Tracker/Track-php-at1BjJsj/
Avatar billede repox Seniormester
11. marts 2010 - 13:50 #15
Videoen jeg havde lavet var optaget fra Firefox (findes der andre? ;) )

Som du selv konstaterer, så opstår 'problemet' først når der er tale om brugen af sessions. De to artikler du har fundet omhandler også race conditions i session handling - hvis man lige læser mellem linierne...

At din firefox så ikke behandler min test som jeg selv oplevede den, kan jeg ikke svare dig på. Det kan have noget at gøre med den måde Firefox håndterer sin forbindelse på. Jeg anvender Firefox 3.6.
Avatar billede steffen Nybegynder
11. marts 2010 - 14:24 #16
Hmmm, dumdidum - hvad i alverden kan det nu være, der gør forskellen der, det vil jeg sgu gerne lige holde fast i ...

Jeg har lige prøvet i både firefox 3.5.8 og 3.6 på Windows, men  uden held. Har prøvet både med og uden safemode. Med "gamle"  indstillinger og med "rene" (oprettede en ny bruger i Windows for hver version og prøvede med den).

"c:\Program Files\Mozilla Firefox\firefox.exe" --safe-mode

Har du noget i din prefs.js der kunne afsløre om du har en speciel magisk setting der et sted? Dvs. i

c:\Users\<user>\AppData\Roaming\Mozilla\Firefox\Profiles\<profile>.default\prefs.js

respektivt

c:\Documents and Settings\<user>\Application Data\Mozilla\Firefox\Profiles\<profile>.default\prefs.js ?

Eller måske et plugin der skubber på? (FasterFox eller lign).

Jeg kører selv med nedenstående indstillinger lige nu, mest fordi pipelining netop skulle medføre at requests blev parallelle - men "nr. 2" tab opretter ikke engang en tcp-forbindelse til serveren når den bliver sat i gang :-/

user_pref("network.http.keep-alive", false);
user_pref("network.http.max-connections", 60);
user_pref("network.http.max-connections-per-server", 30);
user_pref("network.http.max-persistent-connections-per-proxy", 12);
user_pref("network.http.max-persistent-connections-per-server", 12);
user_pref("network.http.pipelining", true);
user_pref("network.http.pipelining.maxrequests", 30);
user_pref("network.http.pipelining.ssl", true);
user_pref("network.http.proxy.pipelining", true);

Hvad for noget Windows afvikler du i øvrigt i? Har prøvet ovenstående eksperimenter i XP og i 64 bit win 7, uden forskel.
Avatar billede repox Seniormester
11. marts 2010 - 14:41 #17
Jeg har adskillige udvidelser i min firefox, men ikke nogen der skal øge perfomance. Som udgangspunkt har jeg aldrig cache slået til (det er livet sq for kort til), men det er nok også det eneste jeg kunne forestille mig kunne have det mindste at sige.

Kører Win 7 x64 UK Pro.

Jeg er ikke sikker på at jeg forstår hvorfor du vil fokusere på netop det at klienterne ikke behandler kaldet ens; laveste fællesnævner er jo netop nu at det ikke altid kan lade sig gøre, selvom forholdene - serverside - er til det. Burde det så ikke være dit udgangspunkt? Du kan jo på ingen måde bestemme over klienten alligevel, ej heller være sikker på om problemet er det samme hos alle klienter?
Avatar billede steffen Nybegynder
11. marts 2010 - 14:45 #18
Tjoe, det kan vi godt blive enige om, at der er flere måder at komme til Mekka på her. Men derfor er det nu alligevel interessant for mig, om ikke andet så af princip for bare at prøve at forstå browserforskellene nu.

Virker de to tabs simultant når du kører safe mode?

"c:\Program Files\Mozilla Firefox\firefox.exe" --safe-mode

Kom til at tænke på, hvis ikke du har alt for hemmelige ting i din prefs.js (eller kan genskabe "evnen" for en ny bruger / ny profil), kan du måske lokkes til at uploade sådan en virkende en?
Avatar billede steffen Nybegynder
11. marts 2010 - 15:43 #19
Øijs, det viser sig at min udgave af firefox serializerer requests mod det samme url internt, og at det faktisk bare er det der driller nu:

Dvs. at hvis bare jeg ændrer lidt i url'erne:

http://err0r.dk/test/spm904132.php
http://err0r.dk/test/spm904132.php?instans=2
http://err0r.dk/test/spm904132.php?instans=3

osv, så kan jeg køre alle dem jeg vil nu.

Med andre ord "Jubiiii!! :-)"

Sæføli er jeg nu lidt nysgerrig efter om ikke jeg kan overtale firefox til at lade være med at tænke for mig der også - hvis jeg beder om den samme url to gange, så er det jo _fordi_ jeg vil se indholdet to gange .... nu, tak! ... men det kan godt vente til en anden dag med at finde ud af om det kan overrules et sted :-)

Mange tak for tålmodig hjælp og støtte, det er meget værdsat!
Avatar billede repox Seniormester
11. marts 2010 - 19:38 #20
Så kom jeg lige lidt tilbage igen; jamen, det var da alligevel rart at der kom lidt forklaring hvad det gik ud på - men det er jo nok firefox' måde at cache på, hvorfor jeg ikke oplevede det samme som dig, da den som udgangspunkt konsekvent er slået fra hos mig - så det må jo konsekvent være en ny forespørgsel hver gang.

Jeg har nu - til samme URL som tidligere, tilføjet nogle headere der skulle fortælle browseren den ikke må cache resultatet og at resultatet i forvejen er forældet.

Prøv lige igen, uden at rette URL'en (du skal naturligvis lige tømme din cache først).
Avatar billede repox Seniormester
19. marts 2010 - 10:03 #21
Fik du løst problemet?
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester