Skalerbar chat

Tags:    php

Hej igen folkens ;)

Jeg har på det seneste siddet og knækket hovedet med en hjernevrider jeg har påkastet mig selv. Jeg har da selvfølgelig sat mig for at skrive en AJAX chat med PHP ! :)

Indtil nu lader jeg den blot opdatere hvert 2 sekund og når brugeren indsender en besked.

Jeg har så hurtigt ramt en mur. Jeg har valgt at bruge MySQL som backend da det umiddelbart virkede logisk.

Lad os starte med "showchat.php" :
Jeg har en query i toppen der opdaterer den nuværende loggede ind brugers "latestactive" field, så brugeren kan blive logget ud efter 10 sekunders inaktivitet (Det er jo en chat og der skal være fart på.) og så ellers så henter den de seneste 25 beskeder ud fra chatten og returnerer, hvis en session (chat-count) ikke er sat. Og derefter sætter den sessionen til det sidste id den spyttede ud, så næste gang behøves den kun tage beskeder derfra.
- Den opdaterer hvert 2. sekund.

Så har jeg også en "showusers.php"
Den laver noget lignende, den henter bare alle brugere hvor "login" er lige med "true" og så løber dem dem igennem og checker om hver brugers lastactive er inden for 10 sekunder, hvis de er bliver de printet, ellers bliver deres login = false.
- kører hvert 10 sek.



Jeg er ret sikker på jeg har kvajet mig i stor stil mange steder, men det er mit første forsøg på en skalerbar ajax applikation, så bær over med mig :S. Jeg kan trække 20 - 30 brugere før vi rammer 100% cpu på en 1,8GHz single core maskine med 1GB ram (lighttpd og MySQL på FreeBSD)

Jeg er allerede ret sikker på sessions trækker en del tid pga de bruger disken, og at mysql queriesne måske kan optimeres en smule. Jeg har også mistanke til min måde at vise brugere ikke er den bedste, men der er foreslag velkomne. Caching har jeg ikke rigtigt set som en mulighed fordi at en chat (sigter efter 100 bruger mindst på den her maskine - 200 - 300 på produktionsserveren) og det vil gå rigtigt stærkt med så mange i et rum.


Alt kritik og eventuelt hjælp, erfaring, opfordringer osv. er velkomne. Det er bare et hobby projekt det her, men skalerbarhed er altid rart at have lidt erfaring med :P





Må man spørge hvad sprog du brugte og hvordan du greb opgaven an? Altså om du brugte ajax klientside eller java / flash og holdte en TCP forbindelse åben?


Jeg brugte ikke en IRC server. Jeg desinede og kodede serveren fra bunden i Java, og lavede også en Java applet som så bliver brugt via JavaScript til at sende og modtage chat events. En konstant åben TCP forbindelse er den mest optimale, for med HTTP polling skal der oprettes en masse datastrukturer, og der skal sendes TCP handshake og HTTP headere og alt muligt hver gang der tjekkes. Og mange tjek vil være uden resultat fordi der intet er sket. Og hvis der sker meget, så er det ufedt, at der går to sekunder mellem hver opdatering.


Andet spørgsmål. Tror i man ville få bedre ydelse fra cgi?

Næppe.
CGI er ofte ret tungt, da der skal oprettes en ny process af webserveren. PHP og lignende er moduler, som indlæses af webserveren så de bliver en del af serveren. Meget bedre integration. Med CGI skal der oprettes en proces, og al bruger data (GET/POST/headere og andet) skal leveres af andre kanaler (environment variabler og input strømme) end man kan med et modul som PHP.

CGI er nok kun bedre, når selve behandlingen af dataene er ekstremt tungt så et fortolket sprog er for langsomt...medmindre der er en meget god JIT compiler, som JVM'en.



Tak for det uddybende svar ! :)
Jeg kunne godt forestille mig at forsøge mig med noget .NET server (så må jeg jo bare skaffe noget VPS hosting) og så en Flash client som kunne kommunikere med Javascript (har været i krav fra starten at jeg -vil- havde chatten i javascript / html / css fordi jeg netop vil udvikle et alternativ til alt det **** som der findes af chats idag rundt omkring :)



APE ser ret lovende ud, jeg vil kigge ind i det ! :)


Du kan eventuelt læse den her korte lille tegneserie de har lavet, der forklarer problemstillingen med dit nuværende setup, flere af disse er Robert også inde på, og måden APE løser det på: http://www.ape-project.org/comics/1/Chapter-I-common-let-s-push.html



APE ser ret lovende ud, jeg vil kigge ind i det ! :)


Du kan eventuelt læse den her korte lille tegneserie de har lavet, der forklarer problemstillingen med dit nuværende setup, flere af disse er Robert også inde på, og måden APE løser det på: http://www.ape-project.org/comics/1/Chapter-I-common-let-s-push.html



Haha man føler sig helt barnlig af at læse en tegneserie men den slog da pointen fast :)

Jeg tager et skud og smækker en Linux box op herhjemme og lader chatten kommunikere med den. Så hvis det virker så må jeg jo simpelthen flytte det til en VPS når der kommer tryk på! :)



Performancemæssigt kan dit webhotel snilt trække flere hundrede brugere - ingen problem - ellers gør du noget forkert.

Du kan sagtens bruge PHP, alt andet er noget vrøvl, det er ikke sproget det kommer an på, det er mere din arkitektur/tilgang til det

Du kan starte med at lave det uden AJAX, og så bare koble det på senere.

Hvis du lader hver klient sende et "heartbeat" hvert andet sekund eller lignende (det skulle være rigeligt) og hvis der er ændringer til chatten, får den enten dataene med tilbage, alternativt blot linke til dem på serveren (evt. en rss du bare loader igen).

Herefter er der to tilgange til det, du kan hente alt data ud når du skal vise det, eller generere RSS hver gang der sættes noget ind i databasen.

Dette burde være simpelt og ligetil at bygge dette således det kan skaleres...

P.S. performancemæssigt så er dette ikke anderledes end at have den samme mængde brugere af ens hjemmeside, og der kan dit webhotel forhåbentligt have mange tusinde.



Indlæg senest redigeret d. 22.12.2010 09:35 af Bruger #2730
Du kan sagtens bruge PHP, alt andet er noget vrøvl, det er ikke sproget det kommer an på, det er mere din arkitektur/tilgang til det

Vrøvl. Sproget er en vigtig del af arkitekturen.
PHP er langt fra ligeså optimeret som f.eks. Java da JVM'ens JIT compiler virkelig kan tricks, som PHP fortolkeren kun drømmer om...hvis den da er nået langt.

Derudover er oprettelsen af en ny TCP forbindelse, forsendelse og modtagelse af HTTP headere og deres parsing også langt fra gratis, hvor en dedikeret chat server kan springe alt det over.

Valget mellem at bygge sin protokol på HTTP eller på TCP er også en del af arkitekturen, hvor HTTP ligner SMS mens TCP ligner en telefonsamtale.

Hvilken foretrækker du?
SMS tilgangen
SMS til mutter: Har du noget at sige?
SMS fra mutter: Næ
vent to sekunder
SMS til mutter: Har du noget at sige?
SMS fra mutter: Næ
vent to sekunder....

Telefon tilgangen
Ring til mutter.
Vent på at mutter siger noget.

Hvilken tilgang skal du og mutter bruge mest energi på ?



Indlæg senest redigeret d. 22.12.2010 11:45 af Bruger #2695
Du kan sagtens bruge PHP, alt andet er noget vrøvl, det er ikke sproget det kommer an på, det er mere din arkitektur/tilgang til det

Vrøvl. Sproget er en vigtig del af arkitekturen.
PHP er langt fra ligeså optimeret som f.eks. Java da JVM'ens JIT compiler virkelig kan tricks, som PHP fortolkeren kun drømmer om...hvis den da er nået langt.

Derudover er oprettelsen af en ny TCP forbindelse, forsendelse og modtagelse af HTTP headere og deres parsing også langt fra gratis, hvor en dedikeret chat server kan springe alt det over.

Valget mellem at bygge sin protokol på HTTP eller på TCP er også en del af arkitekturen, hvor HTTP ligner SMS mens TCP ligner en telefonsamtale.

P.S Robert, ville du VIRKELIG vælge TCP tilgangen ? til en webapplikation/chat ?

Hvilken foretrækker du?
SMS tilgangen
SMS til mutter: Har du noget at sige?
SMS fra mutter: Næ
vent to sekunder
SMS til mutter: Har du noget at sige?
SMS fra mutter: Næ
vent to sekunder....

Telefon tilgangen
Ring til mutter.
Vent på at mutter siger noget.

Hvilken tilgang skal du og mutter bruge mest energi på ?


Pjat...!!! Hvis sprog og arkitektur hænger sammen vil det svare til at sige at et hus er afhængigt af mærket på det værktøj der bruges. Husk: Arkitektur != Funktionalitet

HEnrik vil kode en chat der skal køre i en browser, så kan vi vel godt være enige om at det i sidste ende er HTML.

Jeg forstår ikke at det skal gøres sværere end det er. Der skal hentes noget data som skal vises. Det er ligegyldigt om det er artikler, kommentarer eller en chat. Det er stadig det samme. Hvis du vil åbne en TCP og BLOKERE din browser, indtil der (måske) sker noget i den anden ende, så er det vist udenfor pædagogisk rækkevidde. Samtidig med det faktum at PHP er renderet på serveren, dvs. du vil oprette en TCP forbindelse fra din egen server til din egen server !!??!!

MEn valget af Netop AJAX giver jo mulighed for IKKE AT BLOKERE ved at lade browseren opføre sig som en browser (og samtidig flytte kaldet væk fra serveren), dvs. sende et HTTP request og modtage et svar. Det er ikke anderledes end hvis man klikker på "genindlæs" knappen i din browser, så opdaterer den alle dine chatmeddelelser igen. Den eneste forskel er at nu sker det "bagved" og der spares en masse indlæsning da ikke alt HTML der skal præsenteres skal transportes til klienten hver gang, det er kun den tekst der skal vises, dvs. meget få Kb.



Indlæg senest redigeret d. 22.12.2010 13:37 af Bruger #2730
P.S Robert, ville du VIRKELIG vælge TCP tilgangen ? til en webapplikation/chat ?

Absolut, og det er dét vi gør. Tror du selv, at vi på komogvind.dk kunne have 50.000 simultane chattere, hvis de hele tiden pollede vores webservere ?
Nope.

Pjat...!!! Hvis sprog og arkitektur hænger sammen vil det svare til at sige at et hus er afhængigt af mærket på det værktøj der bruges. Husk: Arkitektur != Funktionalitet

Nemlig. Arkitektur er IKKE funktionalitet, men valget af platform (herunder operativsystem, DBMS og programmeringssprog) er så absolut en del af arkitekturen.

Frank Buschmann kom med en af de bedste definitioner på, hvad arkitektur er: "Arkitektur er den del af designet, som er dyr at ændre."

HEnrik vil kode en chat der skal køre i en browser, så kan vi vel godt være enige om at det i sidste ende er HTML.

Ikke nødvendigvis. Det kunne køre fuldt ud i en Java applet eller Flash app.
På komogvind.dk har vi en applet som står for hele netværksdelen af chatten. Den leverer så events til en række JavaScript funktioner som så opdaterer DOM træet.

Jeg forstår ikke at det skal gøres sværere end det er. Der skal hentes noget data som skal vises. Det er ligegyldigt om det er artikler, kommentarer eller en chat. Det er stadig det samme. Hvis du vil åbne en TCP og BLOKERE din browser, indtil der (måske) sker noget i den anden ende, så er det vist udenfor pædagogisk rækkevidde.

Hvem snakker om at blokkere browseren ? Det gør man da så absolut ikke med en TCP forbindelse. HTTP bruger også TCP nedenunder, men indeholder meget mere end man har brug for i en chat. Og så har den en dum vane med at det kun er klienten, som kan tage initiativ til at snakke, så den er nødt til at polle.


Samtidig med det faktum at PHP er renderet på serveren, dvs. du vil oprette en TCP forbindelse fra din egen server til din egen server !!??!!

Igen...hvad snakker du om ?
Jeg opretter en forbindelse fra en Java applet på klienten tilbage til min chatserver. Appletten modtager data fra chatserveren som så leveres videre til JavaScript, som bestemmer hvad der så skal ske.

MEn valget af Netop AJAX giver jo mulighed for IKKE AT BLOKERE ved at lade browseren opføre sig som en browser (og samtidig flytte kaldet væk fra serveren), dvs. sende et HTTP request og modtage et svar. Det er ikke anderledes end hvis man klikker på "genindlæs" knappen i din browser, så opdaterer den alle dine chatmeddelelser igen. Den eneste forskel er at nu sker det "bagved" og der spares en masse indlæsning da ikke alt HTML der skal præsenteres skal transportes til klienten hver gang, det er kun den tekst der skal vises, dvs. meget få Kb.

komogvind.dk løsningen sker også bagved, men uden at der skal oprettes en ny forbindelse hvert andet sekund for hver bruger.
Vi sender og modtager INTET data som ikke er absolut nødvendigt.
Meget få kb.? Hvad med "ikke en eneste bit" udover hvad der rent faktisk skal vises.



God diskution den her :-)


Nemlig. Arkitektur er IKKE funktionalitet, men valget af platform (herunder operativsystem, DBMS og programmeringssprog) er så absolut en del af arkitekturen.

Frank Buschmann kom med en af de bedste definitioner på, hvad arkitektur er: "Arkitektur er den del af designet, som er dyr at ændre."


Det er ikke dyrt at ændre nogle af de ting du beskriver, det er nemt - eller det BØR det være, hvis man har struktureret sin kode ordentligt. Dvs, lagdeling og indkapsling af det. Eksempelvis i jeres komogvind kode, må der være et database lag, et forretningslag og måske endda et entitetslag. Det er dyrt at rette i entitetslaget, i forretningslaget, men at skrive noget sql om til at bruge en anden database er trivielt.


Ikke nødvendigvis. Det kunne køre fuldt ud i en Java applet eller Flash app.
På komogvind.dk har vi en applet som står for hele netværksdelen af chatten. Den leverer så events til en række JavaScript funktioner som så opdaterer DOM træet.


Så er du jo ude over hvad Henrik vil. Han skriver klart at han vil ud over alt det *@"& som andre chats indeholder og kun lave det i javascript/HTML/CSS. Det betyder at han IKKE vil have en Applet eller noget Flash. Løsningen skal passe til problemet, og det gør din ikke.


Hvem snakker om at blokkere browseren ? Det gør man da så absolut ikke med en TCP forbindelse. HTTP bruger også TCP nedenunder, men indeholder meget mere end man har brug for i en chat. Og så har den en dum vane med at det kun er klienten, som kan tage initiativ til at snakke, så den er nødt til at polle.


Hvis du i din PHP kode opretter en TCP forbindelse (ikke en applet eler lignende) så blokerer den! Husk vi snakker ikke applet, hold dig indenfor kravet.


Igen...hvad snakker du om ?
Jeg opretter en forbindelse fra en Java applet på klienten tilbage til min chatserver. Appletten modtager data fra chatserveren som så leveres videre til JavaScript, som bestemmer hvad der så skal ske.


Igen, du holder dig ikke indenfor kravet til applikationen, du opfinder krav nu for at kunne løse problemet med TCP forbindelse


komogvind.dk løsningen sker også bagved, men uden at der skal oprettes en ny forbindelse hvert andet sekund for hver bruger.
Vi sender og modtager INTET data som ikke er absolut nødvendigt.
Meget få kb.? Hvad med "ikke en eneste bit" udover hvad der rent faktisk skal vises.


igen, det er uden for kravene...

Ud over det er jeg enig i at hvis man skal have en meget skalerbar chat, eks. 50k brugere, så skal man bruge en dedikeret chat klient som eks. applet, flash, silverlight, xbap osv. og der skal implementeres callbacks (fx. et observer pattern, eller på anden måde callbacks - WCF dualhttp). PRoblemet med TCP er at du skal give lov i din firewall til at komme ud/ind (give din applet tilladelse til at køre) - det skal du ikke med HTTP. Der er fordele og ulemper. Jeg synes en applet er overkill for en 100 brugers chatløsning - og samtidig uden for kravet til det der skal løses.







Det er ikke dyrt at ændre nogle af de ting du beskriver, det er nemt - eller det BØR det være, hvis man har struktureret sin kode ordentligt. Dvs, lagdeling og indkapsling af det. Eksempelvis i jeres komogvind kode, må der være et database lag, et forretningslag og måske endda et entitetslag. Det er dyrt at rette i entitetslaget, i forretningslaget, men at skrive noget sql om til at bruge en anden database er trivielt.


Men det er tidskrævende (læs: dyrt) at ændre programmeringssproget, som derfor falder inden for arkitektens ansvar.

Så er du jo ude over hvad Henrik vil. Han skriver klart at han vil ud over alt det *@"& som andre chats indeholder og kun lave det i javascript/HTML/CSS. Det betyder at han IKKE vil have en Applet eller noget Flash. Løsningen skal passe til problemet, og det gør din ikke.


Han sagde også: "Jeg kan trække 20 - 30 brugere før vi rammer 100% cpu"

Og han sagde også: "Jeg kunne godt forestille mig at forsøge mig med noget .NET server (så må jeg jo bare skaffe noget VPS hosting) og så en Flash client som kunne kommunikere med Javascript"

Det lyder temmelig meget som den løsning, jeg beskrev. Altså er han klar på at ændre i kravene, og det skal man også være, hvis man møder modstand/begrænsninger fra teknikken.

Hvis du i din PHP kode opretter en TCP forbindelse (ikke en applet eler lignende) så blokerer den! Husk vi snakker ikke applet, hold dig indenfor kravet.

Jeg har aldrig snakket om TCP fra PHP.

Brian, lav mig et kilo guld. Kravet er, at du kun må bruge 14 gram sand.

Hvis der er grunde til, at krav ikke kan opfyldes, så må man jo genoverveje dem, og Henrik lyder ret meget på at være klar på at prøve en løsning, som bruger Flash som "middleware".

HTTP polling og databaseopslag skalerer til ét antal klienter. JavaScript->Java applet/Flash->Chatserver skalerer til uhyggeligt mange flere.

Igen, du holder dig ikke indenfor kravet til applikationen, du opfinder krav nu for at kunne løse problemet med TCP forbindelse

Igen. Hvis kravet er "mange" klienter, så må Henrik kigge efter andre løsninger.


PRoblemet med TCP er at du skal give lov i din firewall til at komme ud/ind (give din applet tilladelse til at køre) - det skal du ikke med HTTP.

Jo. Du skal da konfigurere din firewall til at tillade HTTP, så hvorfor ikke også en anden port ?

Jeg synes en applet er overkill for en 100 brugers chatløsning


Nu var kravet også lidt mere: "sigter efter 100 bruger mindst på den her maskine - 200 - 300 på produktionsserveren"

Det kan nok klares med HTTP polling, men han opnår 100% cpu ved 30 brugere.




Det kan nok klares med HTTP polling, men han opnår 100% cpu ved 30 brugere.


Det er det jeg siger må betyde at der laves noget "uhensigtsmæssigt". Det vil svare til at ens webside kun kunne have 30 samtidige brugere. Tingene bliver hurtigt overkomplicerede.

Skifte sprog = skifte hammer. For nu at blive i name dropping, så skrev Greg Larman, at kun ca 15% af et projekt er implementering, resten er afklaring design, arkitektur osv. Så jeg vil stadig sige at det er "forholdsvist" meget billigere at udskifte sproget end at skifte alt det andet (design arkitektur osv.) - eksempelvis er der mange virksomheder der omlægger deres systemer til .NET/Java - det er typisk fordi det kan betale sig.



t