Ik ben bezig aan een simpele ajax chat en er kunnen zelfs images verstuurd worden.
Maar ik vraag me nu af is zo een ajax chat niet vrij belastend voor de server omdat er elke seconde data wordt opgehaald?
Mijn chat werkt dus via een timer.
Stel dat ik dit had gemaakt met php sockets was dit dan minder zwaar voor de server?
Bij sockets staan de connecties constant open, lijkt mij dat dat meer kost.
Ajax chats zijn meestal niet extreem server-belastend, maar als die plaatjes op jouw server staan, zou ik wel zorgen dat je ze goed cached.
Ben echter geen expert op dat gebied, dus ben ik benieuwd naar verdere reacties.
Het ligt er heel erg San hoe je het maakt. Als je iedere seconde een reageer doet naar een PHP script, dat door Apache verwerkt moet worden dan is dat aardig belastend. Stel dat je server apache met PHP als cgi module gebruikt, dan kan je met een behoorlijke server niet meer dan ong. 20 mensen aan.
Maar als je apache hierin vervangt door iets dat niet constant PHP hoeft te initialiseren en de berichten en het script gewoon in het geheugen houdt, kom je al een stuk verder. Ik denk dat je al aardig wat requests per seconde kan afvangen met een servertje geschreven in node.js.
Als je dan toch al die kant op gaat, kan je ook de verbindingen open houden. Open verbindingen zelf kosten niet zoveel, een verbinding opbouwen is een stuk intensiever. Naja, niet in het geval van apache omdat die een hele PHP omgeving per verbinding in het geheugen houdt, maar met bode.js kost het maar een paar bytes per verbinding. Dan zou je long-pooling kunnen doen: je doet een requests voor nieuwe berichten naar je server, en je server geeft pas antwoord wanneer er nieuwe berichten zijn.
Jelmer, zou je misschien een klein voorbeeld kunnen geven van dat laatste?
Ik zit namelijk met hetzelfde probleem als OP, met een timer, die om de seconde mijn logfile opnieuw ophaald met Ajax.
Hierdoor wordt de inhoud van de chat om de seconde opnieuw geladen, en kan ik bijvoorbeeld niet op mijn gemak inhoud selecteren, zoals links en dergelijke. Zeer ambetant.
Zijn er nog andere oplossingen voor deze situatie misschien?
Jelmer, zou je misschien een klein voorbeeld kunnen geven van dat laatste?
Jelmer, indien je dit ziet, antwoord dan zelf maar he ..
Ik denk dat dit zo ongeveer de bedoeling is.
Even het Ajax deel tonen.
Dus ... om de seconde kijk je naar de server; je ziet of de laatste id op de server overeenkomt met die waarde die je zelf in javascript opslaat.
Zolang de id's overeenkomen, is er geen nieuwe post.
In het andere geval zijn er wel nieuwe posts
Zoek dan die posts op en verander je de update de laatste id in javascript.
Dat geeft zoiets: (code zegt meer dan 1000 woorden ...)
(function() {
// settings
var interval = 1000;
var posts = $('#posts');
// hou het laatste id bij. Om de zoveel tijd gaan we controleren of dit id nog overeen komt met de laatste id op de server
var lastId = 0;
getLastId();
/**
* deze functie doet maar 1 ding: het stuurt een Ajax request naar de server met als GET variabele: var lastId
*/
function getLastId() { //
$.ajax ({
url: 'posts.php?action=lastid&id=' + lastId,
success: function(data) {
// data is een bericht van de server; antwoord van het Ajax request.
// data is de last id die op de server gevonden wordt.
data = Number(data);
if (data !== NaN && Number(data) == lastId) {
setTimeout(getLastId, interval); // Geen nieuw id gevonden. Een seconde later nog eens proberen
}
else {
// er is een verschil tussen de id op de server en die bij de client
// nu gaan we de data volledig halen.
// We sturen de last id van bij de client toch op naar de server. Eventueel haal je enkel de nieuwe posts op (alle posts met id > lastId)
$.ajax({
url: 'posts.php?action=posts&id=' + lastId,
success: function(data) {
// data is hier de posts; volledig, in HTML formaat
// we steken die in de juiste div
posts.html(data);
// en uiteraard opnieuw de message loop op gang trekken
setTimeout(getLastId, interval);
}
});
// we zetten op deze plaats de id lokaal op de nieuwe waarde.
lastId = data;
}
} // / success
});
}
})();
posts.php
<?php
switch(isset($_GET['action']) ? $_GET['action'] : '') {
case 'lastid':
$id = 24; // dummy waarde; je haalt dit uit de DB
// "SELECT id FROM my_table ORDER BY id DESC LIMIT 1" ...
echo $id;
break;
case 'posts':
echo $allPosts = ' bla bla bla ' . time(); // posts ophalen uit data.
break;
}
?>
Als je posts.php aanpast, werkt deze code.
Ondertussen kan je al eens controleren met de dummy-waarden:
Terwijl een venster open staat:
- verander $allPosts ( val bla bla naar iets anders ) en sla posts.php op;
Er gebeurt niets.
- verander nu $id, van 24 naar iets anders.
Binnen de seconde wordt dit gedetecteerd en en wordt een verzoek gedaan om de nieuwe posts (nu dus in $allPosts) te halen.
Dit is dus nog heel ruw; er is nog een hoop dat beter kan.
(PS: nu ik dit lees ... de naam en commentaar van/bij getLastId is nogal ongelukkig, als je met anonieme functies werkt ...)
Hmm, Kris, dat is al een mooi voorbeeld!
Ik ga het zelf eens onder de loep nemen.
Maar is het ook mogelijk om nog steeds met een logfile te werken? (En bijvoorbeeld steeds de id vanvoor te zetten ofzo?)
Bij elke nieuwe post sla je de laatste id op in een tekstfile. Het lezen van die id kan dus verder gebeuren via die tekstfile. Lezen van een tekstfile belast apache niet en er zijn geen DB connecties.