Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Adding Real-Time Functionality to PHP Apps with Redis, Node, and Socket.io

dclaysmith
April 19, 2013

Adding Real-Time Functionality to PHP Apps with Redis, Node, and Socket.io

dclaysmith

April 19, 2013
Tweet

More Decks by dclaysmith

Other Decks in Technology

Transcript

  1. Me D Clay Smith @dclay • Previously Head of IT

    for Franchise Direct • Created ThetaBoard (real-time collaboration) • Self-Employed Developer
  2. History of Real-time Java Applets. Create raw TCP connections. AJAX

    Polling. Use a javascript timer and make XMLHttpRequests (XHR) every few seconds to look for changes. • New TCP Connections (Overhead) • Full Request (Cookies, Headers, etc) • Time Lag • Tracking which messages have already been processed
  3. History of Real-time Comet. Create long lasting HTTP connections between

    the client and server. • Steaming ◦ Hidden IFrame on page ("forever frame") which fills up with script tags that are processed incrementally. ◦ XMLHttpRequest accepting multipart response from server--callback processes each part that is sent. • AJAX with Long Polling ◦ XMLHttpRequest made and waits until it receives data. Rinse and Repeat. Hacky.
  4. Current Solution HTML5 WebSockets "WebSocket is a web technology providing

    full-duplex communications channels over a single TCP connection." - Wikipedia • Initiated using HTTP then "upgraded" • Its own protocol -- based on TCP ◦ Sends messages instead of bytes ◦ Bi-directional
  5. Options PHP Only-ish • Ratchet (http://socketo.me/) • Wrench (https://github.com/varspool/Wrench) Hosted

    3rd Party Service • Pusher (http://pusher.com/) PHP + Node.js + Redis
  6. Benefits • Use your existing codebase and business logic. •

    Node (non-blocking, event-driven) handles the websocket connections better than the PHP based solutions (blocking). • Socket.io (http://socket.io/). A Node.js library that abstracts away the WebSocket implementation and provides fallback for browsers with partial (or no) support. • Free • Easy
  7. Self Promotion The Next Big Thing! Hockey Stick Growth! No

    one is doing what we are! Billion Dollar Industry!
  8. What We'll Need LAMP Server. Apache, MySql, and PHP. Node.js.

    Event-driven I/O server-side JavaScript environment based on the V8 engine. Redis. Advanced key-value store that offers publish/subcribe functionality.
  9. Setting Things Up 1. Request http://todo.dev from Apache 2. Web

    Page returned with socket.io js script tag. 3. Node.js web server serves the content of this file. 4. Javascript file sent back to the client. 5. Create websocket connection!
  10. Redis We need an efficient way to know when the

    state of our application changes (ie. Todos are created, updated, or deleted). Redis is primarily a key-value data store. Most importantly it allows us to listen for certain events (subscribe) and publish events (well, uh, publish).
  11. Pub/Sub Flow A. Node.js web server SUBSCRIBES to events on

    the Redis Server 1. User makes a request to the ToDo app (create, update, delete) 2a. ToDo app responds with an updated list. 2b. ToDo app PUBLISHES changes to Redis Server. 3. Node.js receives the message it was waiting for.
  12. Bridging the Gap: PHP to Redis Predis Predis is a

    flexible and feature-complete PHP client library for the Redis key-value store. https://github.com/nrk/predis All we need is the ability to "publish".
  13. Spread the Word 1) Node receives event on /todo channel

    2) Socket io sends message to sockets that have connected.
  14. Socket.io in a Nutshell send - just send a message

    > io.sockets.send('Hey!'); emit - send custom event with data & callback > io.sockets.emit('type', data, function (data) { console.log('they got it'); }); broadcast - send to all the other sockets. > io.socket.broadcast.send('Hey!', data); volatile - it's ok if a message is dropped. > io.socket.volatile.send('It is ok if you miss this', data); "Rooms" (Projects, Boards, Lists) > io.socket.join("todo-list-12") (or 'leave') > io.sockets.in("todo-list-12").emit('itemAdded', data );
  15. Yes, this is dog. Back at the browser, listen for

    and handle messages sent back down the socket. var Socket = io.connect('http://localhost: 8080'); Socket.on('message', function (message) { console.log('Hello. Yes, This is dog.'); $('body').html('Message received'); });
  16. Adding Complexity • Node ◦ Authentication ▪ Does user have

    access? ▪ Does user have access to Board # 12? ◦ Managing different channels (rooms) ▪ Each socket only concerned with their Board. ◦ Collision ▪ If user adds item, don't add it again. ▪ Broadcast vs. Emit ◦ SSL • Client ◦ Backbone ◦ Ember ◦ Angular