Your SlideShare is downloading. ×
Realtime Communication Techniques with PHP
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Realtime Communication Techniques with PHP

74,053
views

Published on

Published in: Technology

1 Comment
17 Likes
Statistics
Notes
  • It seems to be like http://www.spoutserver.com is no longer valid..
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
74,053
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
277
Comments
1
Likes
17
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • - Once upon a time, the internet was flat. Users asked for content and web servers gave it to them. - XMLHttpRequest came along and change all of that. - Google said “well, we know they are going to ask for their new messages soon anyway, so why not give them the new messages before they ask?”
  • - Unless you are Facebook, the database is your bottle neck. - Solutions that consume database resources are not very scalable - Timeliness is often sacrificed for scalability
  • Basically the same as refresh but with less data transfered
  • Transcript

    • 1. Realtime Communication Techniques with PHP Scott Mattocks & Chris Lewis, OnForce, Inc.
    • 2. Agenda
      • Introductions
      • Overview
        • User expectations
        • Problems with delivery
      • Techniques
        • Refresh
        • Short Polling
        • Long Polling
        • WebSockets
      • Q&A
    • 3. Introductions
      • Scott Mattocks
        • Senior PHP developer at OnForce, Inc.
        • Contributor to PEAR
        • Author of Pro PHP-GTK
      • Chris Lewis
        • Senior PHP developer at OnForce, Inc.
        • 6 years of enterprise PHP experience
        • 12 years of front-end web development experience
      • Both are contributors to the WaterSpout Real-time Communication Server
    • 4. Overview
      • Example: http://www.spoutserver.com
        • Click “John Locke” in the Demos section
    • 5. Overview
      • Users expect data to be delivered more quickly and seemlessly
        • Gmail changed the way user expect to interact with websites
      • Loading an entire page to show a small change is slow and wasteful
    • 6. Problems with delivery
      • The web runs (for the most part) on HTTP
        • HTTP is one way
        • User asks for data
        • Server sends data back
        • The server can't do anything without the user asking first
    • 7. Problems with delivery
      • Timeliness
        • There is a gap between arrival of the data on the server and notification of the user.
        • We want to reduce the gap without killing the servers.
      Client Server New Data New Data Black out
    • 8. Problems with delivery
      • Efficiency
        • How much of the transfered data is important to the user?
        • Data transfer:
          • X bytes sent for request (GET headers)
          • Y bytes sent for response (body and headers)
          • Z bytes of new data
          • Z / (X + Y) = efficiency
        • We want try to send only the data that has changed and that is important to the user
    • 9. Problems with delivery
      • Scalability
        • What kind of load are we causing on the server?
        • Are we holding resources (i.e. database connections) that could be used to server other users?
        • We want to do more with less
    • 10. Solutions
      • Refresh the page
      • Short Polling
      • Long Polling
        • 1 server
        • 2 servers
      • WebSockets
    • 11. Solutions @gnomeboy want to come over for some cookies? @gnomegirl hellz yeah!
      • Example: Simple twitter feed style page
    • 12. Solutions
      • Page consists of a wrapper around message content
        • Avg message size = 100 bytes
        • Avg page size (without images) = 4 KB
        • Avg request headers = 410 bytes
        • Avg response headers = 210 bytes
      • (JavaScript code examples use Prototype)
    • 13. Refresh
      • The same as if the user hit F5
        • Reloads the entire page
        • New page load adds the new message
      • No constant connection to the server
        • Black out periods between requests
    • 14. Refresh database web server web server
    • 15. Refresh
      • Difficulty
        • 1 out of 10
        • Use HTML or JavaScript
      • <meta http-equiv=&quot;refresh&quot; content=&quot;5&quot; />
      • setTimeout('window.location.reload(true)', 5000);
    • 16. Refresh
      • Timeliness
        • Timeliness of data depends on the refresh rate
        • There is an additional delay for the round trip to the server
          • Includes time to send request, process request, and send response
    • 17. Refresh
      • Efficiency (assume 10 total requests, 1 new message)
        • Data transfer:
          • 410 bytes sent for each request
          • 4210 bytes sent for each response, 4310 for new message response
          • 100 bytes of new data
          • 100 / ((410 + 4210) * 10 + 100) = .0021 per message
        • Server resources used
          • 1 HTTP process per request (10 total)
          • 1 Database connection per request (10 total)
    • 18. Short Polling
      • Ask the server for updates since the last time you asked
        • Like a road trip with a 3 year old
        • Are we there yet? Are we there yet?
      • No constant connection to the server
        • Black out periods between requests
        • Cursor required to prevent data loss
    • 19. Short Polling database web server web server
    • 20. Short Polling
      • Difficulty
        • 5 out of 10
        • AJAX
          • Background request to the server checks for new messages at a timed interval
          • New messages are added to DOM by JavaScript
    • 21. Short Polling function poll_server () { new Ajax. Request ( this .urlPolling, { method: 'post' , parameters: data, onSuccess: this .successHandler, onFailure: this .handleFailure, onException: this .handleException }); } setInterval ( 'poll_server()' , 5000 );
    • 22. Short Polling function successHandler (trans, messages_div) { if (trans.responseText) { var json = trans.responseText. evalJSON (); if (json.message) { var msg = json.message + '<br />' ; $(messages_div). insert (msg); } } }
    • 23. Short Polling function successHandler (trans, messages_div) { if (trans.responseText) { var json = trans.responseText. evalJSON (); if (json.message) { var msg = json.message + '<br />' ; $(messages_div). insert (msg); } } }
    • 24. Short Polling
      • Timeliness
        • Timeliness of data depends on the refresh rate
        • There is an additional delay for the round trip to the server
          • Includes time to send request, process request, and send response
    • 25. Short Polling
      • Efficiency (assume 10 total requests, 1 new message)
        • Data transfer:
          • 410 bytes sent for each request
          • 210 bytes sent for each empty response, 310 for new message response
          • 100 bytes of new data
          • 100 / ((410 + 210) * 10 + 100) = .0158 per message
        • Server resources used
          • 1 HTTP process per request (10 total)
          • 1 Database connection per request (10 total)
    • 26. Long Polling - 1 server
      • Ask the server for updates since the last time you asked
        • Server does not respond until a new message has arrived
      • No constant connection to the server
        • Black out periods between sending response and next request
        • Cursor required to prevent data loss
    • 27. Long Polling – 1 server database web server web server
    • 28. Long Polling – 1 server
      • Difficulty – Client side
        • 5 out of 10
        • AJAX
          • Background request to the server checks for new messages and waits for responses
          • New messages are added to DOM by JavaScript
    • 29. Long Polling – 1 server
      • Difficulty – Server side
        • 5 out of 10
        • Continuously loop checking for new messages
        • Break out of loop when new message arrives
    • 30. Long Polling – 1 server function poll_server () { new Ajax. Request ( this .urlPolling, { method: 'post' , parameters: data, onSuccess: this .successHandler, onFailure: this .handleFailure, onException: this .handleException }); } document. observe ( 'dom:loaded' , poll_server);
    • 31. Long Polling – 1 server function successHandler (trans, messages_div) { if (trans.responseText) { var json = trans.responseText. evalJSON (); if (json.message) { var msg = json.message + '<br />' ; $(messages_div). insert (msg); } } poll_server (); }
    • 32. Long Polling – 1 server <?php $query = 'SELECT message FROM messages WHERE dateadded > ?' ; $stmt = $pdo -> prepare ( $query ); while (true) { $message = $stmt -> execute ( $cursor_date ); if (! empty ( $message )) { echo json_encode ( $message ); break ; } } ?>
    • 33. Long Polling – 1 server
      • Timeliness
        • Near real-time
        • As soon as a message shows up on the server, it is sent to the waiting client
        • Black out period between sending response and making new request can add some delay
    • 34. Long Polling – 1 server
      • Efficiency (1 request, 1 new message)
        • Data transfer:
          • 410 bytes sent for request
          • 310 bytes for new message response
          • 100 bytes of new data
          • 100 / (410 + 310) = .138 per message
        • Server resources used
          • 1 HTTP process
          • 1 Database connection
    • 35. Long Polling – 2 servers
      • 2 servers work together to use fewer resources
        • Main web server handles initial page request
        • Main server informs polling server when new message arrives
        • Polling server informs client
      • No constant connection to server
        • Black out periods between sending response and next request
        • Cursor required to prevent data loss
    • 36. Long Polling – 2 servers web server polling server HTTP XHR over HTTP
    • 37. Long Polling – 2 servers
      • Difficulty – Client side
        • 5 out of 10
        • AJAX
          • Background request to the server checks for new messages and waits for responses
          • New messages are added to DOM by JavaScript
    • 38. Long Polling – 2 servers
      • Difficulty – Server side
        • 8 out of 10
        • Web server makes cURL call to polling server when a new message is added
        • Polling server determines who message is for and sends the response to the waiting connection
    • 39. Long Polling – 2 servers function poll_server () { new Ajax. Request ( this .urlPolling, { method: 'post' , parameters: data, onSuccess: this .successHandler, onFailure: this .handleFailure, onException: this .handleException }); } document. observe ( 'dom:loaded' , poll_server);
    • 40. Long Polling – 2 servers function successHandler (trans, messages_div) { if (trans.responseText) { var json = trans.responseText. evalJSON (); if (json.message) { var msg = json.message + '<br />' ; $(messages_div). insert (msg); } } poll_server (); }
    • 41. Long Polling – 2 servers Main Web Server Polling Server <?php $query = 'INSERT INTO messages VALUES (?, ?)' ; $stmt = $pdo -> prepare ( $query ); $stmt -> prepare ( $message , $date ); $polling_server -> send ( $message ); ?> <?php foreach ( $this ->waiting as $connection ){ $connection -> respond ( $message ); } ?>
    • 42. Long Polling – 2 servers
      • Timeliness
        • Near real-time
        • As soon as a message shows up on the server, it is sent to the waiting client
        • Black out period between sending response and making new request can add some delay
    • 43. Long Polling – 2 servers
      • Efficiency (1 request, 1 new message)
        • Data transfer:
          • 410 bytes sent for request
          • 310 bytes for new message response
          • 100 bytes of new data
          • 100 / (410 + 310) = .138 per message
        • Server resources used
          • 1 HTTP process on polling server per message
          • 0 Database connections
    • 44. WebSockets
      • According to http://en.wikipedia.org/wiki/WebSocket:
      • „ WebSockets is a technology providing for bi-directional, full-duplex communications channels, over a single Transmission Control Protocol (TCP) socket, designed to be implemented in web browsers and web servers”
    • 45. WebSockets
      • WebSockets allow server to push data to client
      • Connection established via client-initiated handshake
      • After handshake, both the client and the server can send and recieve data
        • Server can send data without the client asking for it first
    • 46. WebSockets
      • Builds off of 2 server long polling
        • Main web server communicates with event server
      • Constant connection between client and server
        • No black out periods
        • No need for cursor
    • 47. WebSockets web server WebSocket server JSON via WebSockets
    • 48. WebSockets
      • Difficulty – Client side
        • 5 out of 10
        • WebSocket API
          • Connection established
          • onMessage events fired when new data comes in from the server
          • New messages are added to DOM by JavaScript
    • 49. WebSockets
      • Difficulty – Server side
        • 8 out of 10
        • Web server makes cURL call to WebSocket server when a new message is added
        • WebSocket server determines who message is for and sends the response to the waiting connection
    • 50. WebSockets function poll_server () { var socket = new WebSocket ( 'ws://example.com/' ); socket.onmessage = function (response) { successHandler (response, 'message_errors' ); } } document. observe ( 'dom:loaded' , poll_server);
    • 51. WebSockets function successHandler (trans, messages_div) { if (trans.data) { var json = trans.data. evalJSON (); if (json.message) { var msg = json.message + '<br />' ; $(messages_div). insert (msg); } } }
    • 52. WebSockets Main Web Server WebSocket Server <?php $query = 'INSERT INTO messages VALUES (?, ?)' ; $stmt = $pdo -> prepare ( $query ); $stmt -> prepare ( $message , $date ); $polling_server -> send ( $message ); ?> <?php foreach ( $this ->waiting as $connection ){ $connection -> respond ( $message ); } ?>
    • 53. WebSockets
      • Timeliness
        • Real-time
        • As soon as a message shows up on the server, it is sent to the waiting client
        • No black out period
    • 54. WebSockets
      • Post Handshake Efficiency
        • Data transfer:
          • 0 bytes sent for request
          • 100 bytes for new message response
          • 100 bytes of new data
          • 100 / 100 = 1.000 per message
        • Server resources used
          • 1 process on WebSocket server
          • 0 Database connections
    • 55. WebSockets
      • Efficiency Demo
        • http://spoutserver.com/demos/compare
      • Comparison
        • Refresh: .0021
        • Short Polling: .0158
        • Long Polling: .138
        • WebSockets: 1.00
    • 56. WaterSpout
      • Lightweight HTTP server
        • Static files
        • Dynamic content (PHP)
      • Best used as part of event-driven server pair
        • Can function as both ends
      • Handles WebSockets and long polling
      • Written in PHP
    • 57. WaterSpout
      • Two types of connections
        • Listeners
        • Updates
      • When an update comes in the appropriate listeners are notified
        • Custom controllers define which listeners should be notified
    • 58. WaterSpout - Listeners <?php public function listen () { // Handle cursor for long polling fall back. // ... $this ->dispatcher-> add_listener ( $this ); } ?>
    • 59. WaterSpout - Dispatcher <?php /* Called every .25 seconds on all waiting listeners */ public function process_event (Controller $mover = null) { $key = array_search (( int ) $this ->_cursor, array_keys (self:: $_commands )); if ( $key === false && ! is_null ( $this ->_cursor)) { return ; } $commands = array_slice (self:: $_commands , $key ); if ( empty ( $commands )) { return ; } $response = new HTTPResponse ( 200 ); $body = array ( '__URI__' => $this ->uri, 'commands' => $commands, 'cursor' => end ( array_keys (self:: $_commands )) + 1 ); $response -> set_body ( $body , true); $this -> write ( $response ); $this ->_cursor = ( int ) end ( array_keys (self:: $_commands )) + 1 ; } ?>
    • 60. WaterSpout vs Apache/Nginx
      • Neither Apache nor Nginx has a way for one process to notify the listeners
        • You need to put the incoming update into some shared location (mysql, memcache, etc)
        • Listeners have to poll the shared location
          • Heavy
          • Slows down timeliness
      • WaterSpout solves this by letting updates notify listeners
    • 61. WebSockets
      • Resources
        • http://dev.w3.org/html5/websockets/
        • http://en.wikipedia.org/wiki/Web_Sockets
        • http://www.spoutserver.com/
    • 62. Questions?
      • Contact
        • [email_address]
      • Twitter
        • @spoutserver
      • Feedback
        • http://joind.in/talk/view/1748
      • Slides
        • http://www.slideshare.net/spoutserver