Acest articol își propune să vă arate cum puteți începe să utilizați Node pentru a adăuga caracteristici în timp real pe site-ul dvs. bazat pe PHP. În primul rând, ne vom uita un pic mai mult la ceea ce face Node o potrivire bună pentru aplicațiile în timp real, înainte de a continua să demonstrăm cum să construiți un flux de știri în timp real și să îl încorporați în site-ul dvs.
Thread-based vs Event-based
în mod tradițional PHP este servit cu Apache și modulul mod_php. Dacă executați comanda ‘ top ‘ pe serverul web bazat pe Unix, veți vedea probabil un număr mare de procese Apache care deservesc clienții web. În această configurare, fiecare cerere de client generează de obicei un nou proces Apache până când toată memoria RAM disponibilă este epuizată. Recent, nginx și php-FPM au apărut ca cea mai eficientă metodă de servire a site-urilor PHP, dar chiar și în această configurare fiecare client este deservit de un proces PHP diferit. Punctul cheie aici este că, de la început până la sfârșit, o cerere de client utilizează un proces PHP pe întreaga durată. Dacă durează mult timp pentru a procesa fiecare solicitare, resursele serverului pot fi utilizate foarte repede.
în nod, un singur proces nod servește de obicei fiecare client într-o buclă de eveniment. Pentru procese de lungă durată, costisitoare, cum ar fi accesarea sistemului de fișiere, a unei baze de date sau a unui API la distanță, se recomandă utilizarea apelurilor prin metode asincrone în loc să le blocheze. Acest lucru se realizează prin utilizarea de callback-uri care sunt declanșate atunci când o acțiune cum ar fi accesarea sistemului de fișiere a terminat. Aceasta înseamnă că un proces cu un singur nod poate continua să proceseze cereri noi în timp ce operația costisitoare este rulată în fundal. Când operațiunea costisitoare este completă, se întoarce în coada de buclă de evenimente pentru a fi procesată în continuare de nod.
în esență, Node poate fi privit ca un mediu similar pentru construirea de aplicații, cum ar fi Twisted Python sau EventMachine în Ruby. Node are, de asemenea, un server HTTP încorporat, gata de producție, astfel încât nu are nevoie de un server separat pentru a-l rula, cum ar fi Apache sau Nginx, îmbunătățind în continuare cerințele sale de resurse slabe (restricționând orice scurgeri de memorie).
var http = require('http');http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn');}).listen(1337, '127.0.0.1');console.log('Server running at http://127.0.0.1:1337/');
exemplul de cod de mai sus arată cum puteți scrie un server web obligatoriu „hello world” în doar câteva linii de cod. Prima linie demonstrează utilizarea sistemului de module cunoscut sub numele de CommonJS pe care nodul îl folosește pentru a include module separate. Funcția require este încorporată și, în acest caz, importă modulul HTTP Node pentru utilizare în aplicație. A doua linie creează un nou obiect server web. Observați că primul parametru al metodei createServer este o funcție anonimă. Majoritatea metodelor din nod acceptă o funcție de apel invers ca parametru, iar aceasta este cheia construirii aplicațiilor bazate pe evenimente.
următoarea linie de execuție este linia 5, care folosește metoda înlănțuirea pentru a apela metoda listen la valoarea returnată a metodei createServer (valoarea returnată este instanța modulului HTTP). Metoda listen determină serverul să înceapă să accepte cereri HTTP pe portul 1337 pe localhost. Ultima linie scrie un mesaj consolei pentru a spune că serverul a început. Numai atunci când se face o solicitare către server se numește funcția anonimă, care setează codul de stare HTTP la 200 OK și setează antetul de tip conținut. Mesajul ‘Hello World’ este în cele din urmă scris organismului de răspuns HTTP pe linia 4.
De ce ar trebui să folosesc nodul.js atunci?
Modelul Node bazat pe evenimente este potrivit în special pentru aplicații în timp real, cum ar fi jocuri, fluxuri de știri și aplicații de chat. În plus, vă permite, de asemenea, să utilizați aceeași limbă pe frontend și backend. JavaScript devine din ce în ce mai popular, deoarece sunt construite aplicații client-side mai bogate, iar browserele web devin mai rapide la executarea JavaScript. A comuta între limbi poate fi frustrant.
WordPress Spezial
Alles rund um WordPress im Entwickler Spezial Vol. 10-ab 18.11.2016 sunt Handel.
WordPress este un sistem de blog simplu. În diesem Sonderheft Besch inktigen sich zahlreiche Spezialisten mit allen wichtigen Fragen rund um das verbreitetste CMS im Web; und dabei geht es nicht nur um klassische Themen, sondern auch um Affiliate Marketing, E-Commerce u.v.m.
În al doilea rând, are suport bun pentru WebSockets. În timp ce este posibil să se sprijine WebSockets în PHP, natura asincron Node și serverul său HTTP încorporat face o potrivire mai bună. WebSockets sunt o modalitate de a menține o conexiune persistentă la browser pentru a împinge rapid datele către client. În comparație cu soluțiile anterioare, cum ar fi long polling sau comet, WebSockets implică o latență mult mai mică, deoarece nu există cheltuieli generale de instanțiere a unei conexiuni HTTP de fiecare dată când trebuie trimise unele date. Dezavantajul WebSockets este că este o caracteristică HTML5, și, ca atare, nu este la fel de bine susținută în browsere ca simplu vechi Ajax este. Cu toate acestea, este posibil să reveniți cu grație la tehnici alternative, cum ar fi sondarea îndelungată în browserele care nu acceptă WebSockets.
la Conferința Internațională PHP din acest an puteți afla mai multe despre integrarea nodurilor.js cu PHP!
Conferința Internațională PHP este prima conferință PHP din lume și a fost un reper pentru expertiza pragmatică de top în tehnologiile PHP și web de mai bine de un deceniu . La IPC, experți de renume internațional din industria PHP se întâlnesc cu utilizatori și dezvoltatori PHP din companii mari și mici. Check out prețurile noastre Early Bird pentru reduceri mari!
iată câteva sesiuni de evidențiere de la IPC:
- realizarea unghiulară.JS cerere accesibil
Dirk Ginader (Google) - TypeScript – a face dezvoltarea JavaScript mai productiv și Robust
Rainer Stropek (Software architects gmbh) - cum să se pregătească pentru PHP 7
Sebastian Bergmann (thePHP.cc)
țineți minte totuși, Node este o platformă imatură în comparație cu PHP. Creat inițial în 2009, este încă la început și nu a ajuns încă la versiunea 1.0 – dacă asta contează pentru dvs. S-ar putea să descoperiți că API-urile pe care le utilizați se schimbă în viitor sau să nu puteți găsi un cadru care are același set de caracteristici ca și Cadrul PHP preferat. Într-adevăr, din experiența mea, bibliotecile și cadrele terțe disponibile tind să constea din pachete mult mai mici de funcționalități pe care trebuie să le puneți împreună.
există, de asemenea, un risc mai mare de scurgeri de memorie care să vă oprească aplicația. Procesele nodului rulează de obicei continuu, în timp ce procesele PHP tind să fie respawnate periodic pentru a nega efectul scurgerilor de memorie.
partea integratoare
fluxul de știri va fi integrat cu un site web PHP de bază care gestionează conectările și sesiunile utilizatorilor, folosind o configurare comună a php-fpm și nginx. Vom folosi JavaScript pentru a comunica cu o aplicație nod pe partea de server și actualiza dinamic fluxul de știri fără a reîncărca pagina. În primul rând, o scurtă deoparte pe sesiuni.
dacă nu faceți deja acest lucru, ar trebui să utilizați o zonă de stocare centralizată pentru sesiunile dvs. (figura 1). Memcached poate fi folosit cu ușurință pentru această sarcină prin utilizarea construit în sesiune salva handler în extensia PECL memcached. Dacă doriți posibilitatea de a reporni serverul care vă stochează sesiunile fără a pierde date, atunci Redis este un pariu bun. Oricum, o stocare centralizată a sesiunii vă permite să încărcați echilibrul aplicației pe mai multe servere web. De asemenea, vă permite să partajați date de sesiune cu aplicații construite cu alte limbaje de programare.
Figura 1: Arhitectura sesiunii partajate.
cu toate acestea, există o mică problemă de analiză a datelor sesiunii. Mai jos este afișat formatul de serializare implicit al unei sesiuni PHP:
not|a:2:{i:0;s:4:"easy";i:1;a:1:{s:2:"to";s:5:"parse";}}
poate părea că puteți folosi manipularea șirurilor pentru a o analiza, dar ar putea exista cazuri de margine care sunt dificil de rezolvat. Ar fi frumos dacă sesiunea ar fi serializată în formatul JSON mult iubit:
{"this":{"is": "easier", "to": "parse"}}
mult mai bine. Este destul de ușor să vă scrieți propriul serializator de sesiuni care va converti orice stocați în $_SESSION în format JSON, consultați versiunea mea.
alternativ, poate doriți să luați în considerare msgpack care poate fi configurat pentru a serializa sesiunile, ca în codul de mai jos, care demonstrează, de asemenea, cum să utilizați memcached ca handler de salvare a sesiunii.
există o bibliotecă terță parte disponibilă pentru Node care poate serializa și deserializa msgpack, disponibilă în NPM (Node Package Manager, conține un număr mare de module care pot fi utilizate în aplicația dvs. cu doar o simplă instalare npm ). Vom analiza acum construirea fluxului de știri folosind Node și încorporarea acestuia într-o aplicație PHP.
PHP App
aplicația PHP se ocupă pur și simplu login-uri de utilizator și sesiuni. Sesiunile sunt stocate în memcached, dar ar putea fi destul de ușor stocate în redis. Codul de mai jos prezintă fragmente ale aplicației simple one page (pentru sursa completă accesați github.com/lboynton/phphants-march-php).
// // <!]>
prima linie a scriptului include fișierul Composer autoloader, ceea ce înseamnă că toate dependențele sunt autoloaded automat, evitând necesitatea separării includ sau necesită linii (Nota Editorului: Pentru mai multe despre compozitor, consultați Jeffersson Nathan de O. Articolul lui Chaves). În acest caz, session save handler este singura bucată de cod extern care este necesară. Cu toate acestea, este foarte ușor să includeți orice pachete terțe disponibile pe packagist sau în altă parte la o dată ulterioară, utilizând Composer, care va fi, de asemenea, adăugat automat la autoloading. Liniile 3 și 4 au stabilit o conexiune la memcached, în timp ce handler-ul de salvare a sesiunii este inițializat și înregistrat cu PHP în liniile 5-14. Utilizatorii sunt conectați pur și simplu specificând numele de utilizator ca parametru GET, deși într-un sistem real acest lucru ar trebui înlocuit cu un sistem de autentificare mai funcțional.
pe partea JavaScript, vom folosi unele biblioteci terțe părți : jQuery, subliniere.js și Socket.IO client, care este partea de browser a modulului nod pe care îl vom folosi pentru a împinge datele către browser. Io.conectați metoda de apel creează o conexiune la aplicația nod, care ar putea utiliza unul dintr-un număr de transporturi, cum ar fi websockets sau Ajax, în funcție de suportul browser-ului. Priza.on method stabilește un handler de evenimente care va reda o știre pe pagină ori de câte ori un eveniment de știri este declanșat de partea serverului.
notă: Aplicația folosește Composer pentru instalarea session save handler și Bower, un manager de pachete pentru instalarea activelor din partea clientului. Pentru a instala Bower, rulați ‘NPM-g install bower’. Apoi, pentru a instala activele, faceți ‘bower install’. Alternativ, actualizați etichetele de script și foile de stil cu versiuni locale.
aplicația este servită folosind nginx. Iată fișierul de configurare nginx:
upstream node { server localhost:3000;}server { listen 8080; server_name php-node-demo.localhost; root /home/lee/public_html/php-node-demo; index index.php; location / { try_files $uri $uri/ /index.php?$args; } location ~ .php$ { include fastcgi_params; fastcgi_index index.php; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } location ~ /socket.io { proxy_pass http://node; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }}
liniile 1-3 definesc un server din amonte care rulează aplicația Node. Orice cerere se încheie în .php va fi trimis la php-fpm (liniile 15-20), în timp ce orice cereri cu /socket.io în URL – ul va fi trecut la aplicația nod (liniile 22-27). Liniile 25 și 26 îi spun lui nginx să accepte comutarea protocolului și să permită ca websockets să fie proxy la nod. Aceasta înseamnă că aplicația PHP și aplicația Node sunt rulate pe același port, în ceea ce privește clientul.
nod.js App
nodul.js app pur și simplu se ocupă de orice cereri de client pentru fluxul de știri. Fragmente din acesta sunt afișate mai jos (a se vedea github.com/lboynton/phphants-march-node pentru sursa completă).
io.set('authorization', function(handshake, callback) { var cookies = cookie.parse(handshake.headers.cookie); mcClient.get('sessions/' + cookies.PHPSESSID, function(error, result) { if (error) { callback(error, false); } else if (result) { handshake.session = JSON.parse(result); callback(null, true); } else { callback('Could not find session ID ' + cookies.PHPSESSID + ' in memcached', false); } });});io.sockets.on('connection', function(socket) { var session = socket.handshake.session; sockets = socket;);function getNews() { redis.blpop('news', 0, function(err, data) {news = JSON.parse(data);if (typeof news.to !== 'undefined') { if (typeof sockets !== 'undefined') {sockets.emit('news', news.content); }} else { io.sockets.emit('news', news.content);}process.nextTick(getNews); });}
soclu.io este o bibliotecă care furnizează un singur API pentru efectuarea comunicării WebSocket între client și server. Aceasta susține, de asemenea, rezervă grațios atunci când WebSockets nu sunt disponibile în browser-ul, și alte caracteristici utile într-un protocol de mesagerie, cum ar fi batai de inima, timeout și suport de deconectare care nu este acceptat din cutie cu Html5 WebSocket API.
primul fragment configurează autorizarea pentru cererile care Socket.io primește. Când apare o nouă solicitare, aceasta va analiza cookie-urile din cerere și va încerca să recupereze o cheie memcached care corespunde valorii cookie-ului PHPSESSID (numele implicit pentru cookie-ul de sesiune PHP). Dacă este găsit, acesta va stoca valoarea analizată a cheii memcached în date.sesiune care poate fi accesată ulterior.
următorul fragment configurează ce ar trebui să se întâmple atunci când Socket.io declanșează evenimentul ‘conexiune’. Acest eveniment este declanșat în timpul conexiunii inițiale de la client, odată autorizat. Datele sesiunii care au fost preluate anterior din memcached pot fi acum menționate prin soclu.variabilă strângere de mână. Când Clientul se conectează, instanța socket este asociată cu numele de utilizator al clientului, astfel încât mesajele să poată fi trimise utilizatorilor individuali.
ultimul fragment conține o funcție de verificare a știrilor noi într-o coadă redis. Folosește comanda BLPOP în redis, ceea ce înseamnă că, dacă coada este goală, se va bloca până când unele date vor fi adăugate la coadă înainte de ao deschide. Când unele date pot fi scoase din coadă, acestea sunt analizate ca JSON înainte de a determina dacă conținutul ar trebui trimis fiecărui client conectat sau doar unui singur utilizator. Conținutul știrilor este trimis la soclul corect apelând metoda emit () pe soclul care a fost asociat cu utilizatorul anterior în handler-ul evenimentului de conectare.
în cele din urmă, procesul nodului.metoda nextTick () este apelată cu funcția getNews ca argument. Aceasta înseamnă că funcția getNews va fi apelată data viitoare când se execută bucla de evenimente și va continua să verifice coada redis pentru date până când aplicația este oprită.
pentru a instala, utilizați npm pentru a descărca dependențele necesare. Apoi rulați aplicația cu aplicația node.js.
acum ar trebui să puteți deschide un browser web și să navigați lahttp://localhost:8080/?username=bob și să vedeți aplicația News feed. Acum deschideți oa doua filă sau fereastră de browser cu un nume de utilizator diferit, de exemplu http://localhost:8080/?username=sally.
actualizarea fluxului
actualizarea fluxului este pur și simplu un caz de împingere a unei noi știri în coadă. Conectați-vă la interfața redis CLI folosind comanda redis-cli. Acesta este un shell interactiv pentru redis, permițându-vă să trimiteți comenzi direct la server. Eșantionul de cod de mai jos arată cum să împingeți la coadă:
rpush news '{"content": "Testy test", "to": "bob"}'
în fereastra browserului web pe care ați deschis-o pentru utilizator bob ar trebui să vedeți elementul de știri glisând în jos din partea de sus a paginii. Alternativ, puteți împinge știri atât bob, sally și orice altultoți clienții conectați prin excluderea parametrului „to”, după cum urmează:
rpush news '{"content": "Everyone should see this"}'
într-o aplicație reală v-ar împinge date în coada de la PHP, folosind, de exemplu, extensia php-redis sau predis.
concluzie
acesta este doar un exemplu simplu pentru a demonstra modul în care nodul poate fi integrat cu aplicația PHP. Există câteva limitări în implementare. De exemplu, va aminti doar o conexiune de la fiecare utilizator. Prin urmare, dacă un utilizator are mai multe file sau ferestre deschise la fluxul de știri, se va actualiza o singură pagină. Acest lucru poate fi rezolvat prin stocarea unei matrice de prize per utilizator și urmărirea fiecărei conexiuni și deconectări pentru a adăuga sau elimina prizele din matrice. Este la latitudinea cititorului să pună în aplicare o soluție mai bună. De asemenea, a prezentat instrumente precum Composer și Bower pe care vă recomand să le utilizați în aplicațiile dvs.Lee Boynton este un dezvoltator cu sediul în Hampshire, Marea Britanie, cu un interes deosebit în aplicații în timp real, cum ar fi mesagerie instant și fluxuri de activitate. Are cunoștințe despre dezvoltarea și administrarea serverului, precum și despre dezvoltarea frontendului. Lucrează la compania locală Symbios Group și este, de asemenea, membru al PHP Hampshire pentru care ajută la organizarea de evenimente.