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

Realtime Communication Techniques with PHP

on

  • 34,572 views

 

Statistics

Views

Total Views
34,572
Views on SlideShare
34,413
Embed Views
159

Actions

Likes
17
Downloads
256
Comments
1

7 Embeds 159

http://lets-learn-it.blogspot.in 68
http://www.slideshare.net 45
http://lets-learn-it.blogspot.com 38
https://twitter.com 4
http://www.lets-learn-it.blogspot.in 2
http://lets-learn-it.blogspot.de 1
http://www.lets-learn-it.blogspot.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • It seems to be like http://www.spoutserver.com is no longer valid..
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • - 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

Realtime Communication Techniques with PHP Realtime Communication Techniques with PHP Presentation Transcript

  • Realtime Communication Techniques with PHP Scott Mattocks & Chris Lewis, OnForce, Inc.
  • Agenda
    • Introductions
    • Overview
      • User expectations
      • Problems with delivery
    • Techniques
      • Refresh
      • Short Polling
      • Long Polling
      • WebSockets
    • Q&A
  • 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
  • Overview
    • Example: http://www.spoutserver.com
      • Click “John Locke” in the Demos section
  • 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
  • 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
  • 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
  • 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
  • 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
  • Solutions
    • Refresh the page
    • Short Polling
    • Long Polling
      • 1 server
      • 2 servers
    • WebSockets
  • Solutions @gnomeboy want to come over for some cookies? @gnomegirl hellz yeah!
    • Example: Simple twitter feed style page
  • 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)
  • 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
  • Refresh database web server web server
  • 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);
  • 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
  • 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)
  • 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
  • Short Polling database web server web server
  • 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
  • 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 );
  • 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); } } }
  • 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); } } }
  • 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
  • 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)
  • 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
  • Long Polling – 1 server database web server web server
  • 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
  • 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
  • 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);
  • 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 (); }
  • 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 ; } } ?>
  • 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
  • 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
  • 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
  • Long Polling – 2 servers web server polling server HTTP XHR over HTTP
  • 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
  • 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
  • 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);
  • 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 (); }
  • 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 ); } ?>
  • 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
  • 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
  • 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”
  • 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
  • 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
  • WebSockets web server WebSocket server JSON via WebSockets
  • 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
  • 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
  • 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);
  • 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); } } }
  • 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 ); } ?>
  • 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
  • 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
  • WebSockets
    • Efficiency Demo
      • http://spoutserver.com/demos/compare
    • Comparison
      • Refresh: .0021
      • Short Polling: .0158
      • Long Polling: .138
      • WebSockets: 1.00
  • 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
  • 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
  • WaterSpout - Listeners <?php public function listen () { // Handle cursor for long polling fall back. // ... $this ->dispatcher-> add_listener ( $this ); } ?>
  • 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 ; } ?>
  • 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
  • WebSockets
    • Resources
      • http://dev.w3.org/html5/websockets/
      • http://en.wikipedia.org/wiki/Web_Sockets
      • http://www.spoutserver.com/
  • Questions?
    • Contact
      • [email_address]
    • Twitter
      • @spoutserver
    • Feedback
      • http://joind.in/talk/view/1748
    • Slides
      • http://www.slideshare.net/spoutserver