Bon alors je sais que dans la théorie, l'AJAX doit être utilisé dans des objectifs de requêtes (j'envoie une requête au serveur, et j'attends une réponse) alors que socket.io correspond plus a un dialogue unilatéral (le client envoie une info au serveur, ou le serveur au client, mais il n'y a pas nécessairement de réponse attendue) ... mais dans les faits, sont-ils quand même interchangeables ? et que valent-ils point de vu performance ?
Disons que j'ai un forum en PHP, qui tourne bien, avec notamment un système de MP, des notifs lorsqu'un réponse a un post vient d’être soumise, et une liste de users connectés. Le tout fonctionne avec un AJAX, qui verifie les MP, les réponse, et les users toutes les 30 secondes. Est-il envisageable d'avoir, en parallèle, nodeJS qui tourne sur le serveur, et de le faire communiquer avec la bdd ou PHP pour avoir les notifs et la users list en temps réel ?
Si ca se fait, y a-t-il une différence en termes de performances pour le client ? le serveur ?
Ceux qui en ont fait l'expérience, je suis curieux d'avoir vos avis ...
EDIT: je vais ajouter les sockets PHP a ma question ... quelqu'un a-t-il essayé ?
J'ai fait quelques recherches et je vais donc mettre à jour ma réponse.
Les websockets backend sont en effet une solution intéressante, mais pas pour PHP. (cf : http://stackoverflow.com/questions/15220501/websockets-php. Cela est pratique pour des frameworks MVC Java ou Scala par exemple.
Pour utiliser du push avec PHP il est donc plutôt conseillé de coder l'appli en PHP et de rajouter la partie push via NodeJS et Socket.io. Il s'agit d'une conclusion que j'ai tiré à partir de plusieurs réponses de Stackoverflow mais je n'ai malheureusement plus les liens.
Il est préférable de ne pas utiliser les websockets seuls, en effet, il y a encore une bonne partie des navigateurs qui ne prennent pas en charge cette fonctionnalité. Un système comme Socket.io (mais ce n'est pas le seul), propose des fallbacks et permet donc une utilisation du push sur un plus grand nombre de navigateurs.
Voici aussi une autre idée d'implémentation qui apporterait moins de refactoring mais qui fait plus appel au javascript pour la récupération/edition des informations :
client(s) <------> application PHP <-------> Base de données
(navigateurs, ^
smartphones, |
...) |
^ |
|--------NodeJS--------
Vous créez toutes les actions dans votre framework PHP de manière classique. Au chargement de la vue, vous allez en même temps vous connecter au serveur NodeJS pour enregistrer votre navigateur sur la page actuelle et dire que vous allez pouvoir écouter les changements.
Lorsque vous allez éditer par exemple, au lieu de faire une redirection avec envoi du formulaire, vous allez envoyer les informations en AJAX. Dans la fonction de callback, vous allez pouvoir envoyer un événement à NodeJS pour dire qu'il y a eu une modification de réalisée.
De manière générale, il faut bien définir les rôles de chaque élément. A mon sens, le framework PHP est le seul qui doit avoir accès à la base de données, c'est aussi le seul qui doit posséder l'intelligence des Models.
NodeJS va servir de dispatcher, une sorte de facteur, dans le sens où il va récupérer les messages d'événements venant d'un navigateur pour les propager aux autres connectés.
Le dernier point va concerner la fiabilité du push. En effet, lorsque vous allez vous connecter avec votre navigateur, vous allez définir un bail de connexion au serveur. Ce bail va être à régénérer à un intervalle de temps fixe. Seulement, il se peut que vous soyez déconnecté d'Internet et que vous vous reconnectiez juste après, auquel cas vous allez créer un nouveau bail. Dans ce cas, vous allez avoir deux baux pour le même utilisateur. Le nombre de personnes connectés vu par le serveur n'est pas le nombre de personnes réellement connectés. De plus, on ne peut être sûr qu'un client a bien reçu l'information venant du serveur.
Il y a deux moyens de palier à ce problème :
A vous de voir la sensibilité de l'information, si elle n'est pas primordiale pour une exécution à l'instanté, vous pouvez l'envoyer directement, sinon il vaut mieux envoyer un flag.
Comme toujours, il s'agit d'une réflexion sur une implémentation possible, ce n'est pas du tout la seule.
Je réfléchis exactement au même problème que toi pour la refonte de ce forum. J'ai pas encore fait d'essaie donc je peux pas te faire de retour mais je pense que nodeJS sera plus performant que l'AJAX vu qu'avec l'AJAX tu fais bcp d'appel pour rien :(
Bonjour,
il va falloir clarifier le fonctionnement du web avant de pouvoir répondre à ta question.
Actuellement, le dialogue client/serveur se fait sur le protocole HTTP en version 1.1. Lorsque le client fait une requête (soit en chargeant une page, soit en envoyant une information), il y a création d'une socket pour la communication. Le serveur va ensuite répondre et clôturer la socket. Ce fonctionnement a pour résultat que le serveur ne sait jamais quels clients sont connectés à lui.
AJAX est un moyen de faire des requêtes via JavaScript, ce qui permet de réaliser des interactions client/serveur sur une même page web. Cela permet une meilleur expérience utilisateur et de gagner en performance car il n'y a pas de rechargement de fichiers statiques (images, fichiers, js, css, ...). Mais AJAX fonctionne de la même manière : Le client se connecte, envoie sa demande, le serveur répond et clôture la socket.
Socket.io permet de garder les sockets ouvertes afin de permettre au serveur d'envoyer des informations à ses clients sans demande préalable de leur part.
Le client va se connecter et "s'inscrire" comme étant connecté. Lorsque le serveur va recevoir une action d'un client (suppression d'un post dans ton forum par exemple), et va propager cet événement à tous ses clients connectés pour qu'ils mettent à jour leurs données. C'est aussi de l'AJAX quelque part car AJAX signifie Asynchronous JavaScript And Xml donc on a bien affaire à du chargement de données asynchrone.
Si le client ne fait pas d'acquittement, le serveur ne saura jamais si les données ont été reçues ou non. Exemple, si on fait un chat et qu'un client envoie un message, le serveur va le propager à tous ceux qui sont dans le chat. Si les clients ne font pas d'acquittement, le serveur ne garantit pas que le message ait bien été reçu côté client.
En terme de performance, le push est bien plus puissant, plus performant mais aussi plus compliqué à mettre en oeuvre, notamment du fait que les protocoles pour le web ne possèdent pas ces fonctionnalités nativement car elles n'existaient pas lors de la création du web.
Pour le dialogue NodeJs, application PHP tu as plusieurs possibilités :
1) supprimer l'application PHP pour tout coder avec Node.JS
2) utiliser NodeJS en "middleware", c'est à dire que les requêtes ne seront plus effectuées à l'application PHP directement mais à l'application NodeJS qui, elle, va se charger de faire l'appel à ton code PHP. NodeJS va dans ces cas là va être un genre de hub qui récupère et distribue les informations.
Voici le schéma de fonctionnement. Chaque rôle est ainsi bien défini.
client(s) <-----> NodeJs <------> application PHP <-------> Base de données
(navigateurs,
smartphones,
...)
J'espère que cela a pu éclaircir tes doutes et tes questions.
Salut prbaron, tu aurais des liens qui détaillent ton dernier point ?
Je comprends tout à fait le principe, mais techniquement je ne vois pas comment mettre ça en place.
Merci :)
@alex-d c'est très simple si NodeJs est sur le même serveur que php on peut exécuter des commandes dans le shell via le module exec.
Par exemple :
var exec = require('child_process').exec;
exec('echo lol', function(err, stdout, stderr) {
console.log(stdout);
});
Donc tu fais appel à ton script comme ceci et pour le passage de donnée j'ai jamais testé mais tu peux essayer de faire passer du base64 en argument (mon doute se situe sur la limite de caractère qui peuvent entrer dans un ligne de shell :D
@prbaron Ça va pas être un peu long ?
@darkHexagon, je ne sais pas je n'ai pas encore pu tester. L'avanatage c'est que du coup ton code PHP devient une api, donc tu peux gérer un canal push pour des clients mobiles.
NodeJS est réputé pour être assez rapide, le framework PHP ne renverrait que du JSON donc rapide aussi. Le plus long est d'envoyer le code HTML.
Le deuxième avantage c'est que tu découpes ton système, pour pouvoir faire différents tests, la logique en PHP, le dispatcher en JavaScript.
http://fr.slideshare.net/mgiglesias/going-crazy-with-nodejs-and-cakephp.
Voici un exemple d'implémentation mais ça n'est pas forcément le seul.
Requis :
Prenons un exemple d'une liste de todo synchronisées entre plusieurs utilisateurs. Ces utilisateurs partagent la même liste. Lorsque l'un utilisateur ajoute un todo, les autres doivent le voir en instantané.
Nous allons créer 2 sous domaines sur notre serveur.
Lorsque le client1 va aller (après s'être loggué) sur www.todo.com/lists/index/1, il va faire un appel au serveur nodejs qui va :
1 ) enregistrer le client dans sa base de clients connectés
2 ) faire un appel à api.todo.com/lists/1 et récupérer le résultat au format html.
idem pour le client2.
Lorsque le client1 va faire un post www.todo.com/todos/add/new, il va envoyer les données en POST à nodejs qui va faire la requête à api.todo.com/todos/add/new avec un json de ce format :
{
"list" : "1",
"user_id" : "1"
"message" : "Créer ma super application",
"done" : false,
"deleted" : false
}
l'application PHP répond avec un code d'erreur, nodejs va propager à tous les clients connectés.
PS : ce fonctionnement n'est que le produit d'une recherche et d'une réflexion, il n'a pas fait l'objet de tests.
Merci prbaron pour ces infos completes et pertinantes. Effectivement ca précise pas mal les possibilités.
L'utilisation de node pour bridger le client et l'appli PHP est intéressante ... mais demande manifestement un peu de refonte.
Je regardais hier soir et il semble que l'emploi des sockets en PHP pourrait etre une alternative demandant moins refactoring. En particulier il y a Ratchet, qui est un utilisable avec symfony 2 (enfin c'est utilisable avec n'importe que framework [ou absence de framework] PHP, mais il est installable via composer). Alex-D tu as pas essayé ? ... de façon générale il y a des utilisateurs des sockets php parmi nous ?
(@prbaron: je te valide pas ta réponse tout de suite pour garder le thread non-résolu, mais promis je le ferai ^^)
Bonjour,
Sujet super interessant, il serait agreable d'avoir une mise en prod de ce concept car je pense que beaucoup de dev voudrait connaitre cette technique ;)
Cordialement
Merci encore de ce regard éclairé.
Pour ma part j'avais regardé du coté des sockets PHP. Ratchet, par exemple, s'intègre comme un charme a une application brute codée a l'arrache comme avec une appli développée avec symfony. Le tchat (sans interaction avec le reste de l'application) et le push sont deux choses différentes, et les deux fonctionnent très bien, mais je n'ai pas fais de tests intenses, ni vraiment sur du long terme (max quelques heures). Je n'ai aucun problème pour faire communiquer le reste de l'application avec le script de push, et l'intégration globale avec la bdd, en particulier, tourne comme une montre.
Suite a ton post il samble bien quil faille passer par du JS coté serveur, donc. Mais la façon (très concrètement) de coder l'intégration des deux est encore floue pour moi ... il faudra que je me penche sur le sujet.
En tous cas je suis déçu que les sockets PHP ne soient pas une bonne solution ... j'étais tout content de mon truc, moi :( ...
Petit déterrage de topic, je viens de poster la question sur stackOverflow : http://stackoverflow.com/questions/23410079/architecture-for-a-complete-application-with-push-for-browser-and-native-applica, je suis en train de coder une application pour faire une démo de tout ce que j'aurai appris.
Je reviens vers vous dès qu'il y en a un peu plus !
Hello,
re déterrage de topic. Voici enfin le tutoriel : http://pierrebaron.fr/blog/push-notification-php-nodejs/.
Incroyable, j'étais justement en train de réflechir à te demander des nouvelles il y a qques heures ... Après 1 an de silence on se retrouve sur ce topic en même temps à quelques heures près ...
enfin bref, je regarde ton truc et te tiens au jus.