Upload
phil-leggetter
View
1.764
Download
1
Embed Size (px)
Citation preview
Real-time Web Apps & Symfony.
What are your options?
PHIL @LEGGETTERHead of Developer Relations
1 / 72
@leggetter
2 / 72
What we'll cover
1. Why Real-Time?2. What are your options
How do you choose?
Pros & Cons
3. 3 Example Solutions for Symfony
3 / 72
Why Realtime?
4 / 72
Notifications & Signalling
5 / 72
Activity Streams
6 / 72
Data Visualizations
7 / 72
8 / 72
Chat
9 / 72
Real-Time Location Tracking
10 / 72
Multi-User Collaboration
11 / 72
Multiplayer Games /
"Do some real-time art!"
12 / 72
13 / 72
Users expect a real-time UX
14 / 72
Users expect a real-time UX
Without a real-time UX your app appears
broken
15 / 72
Real-time Web Apps & Symfony.What are your options?
16 / 72
6 Factors to Consider
17 / 72
1. Use an existing solution
Don't reinvent the wheel
Unless you've a unique use case
18 / 72
Why use an existing solution?
Fallback/upgrade hacks still requiredSupport/CommunityMaintenanceFuture featuresScaling
19 / 72
20 / 72
2. Use languages you're comfortable
with
21 / 72
Solutions by language
PHP: ReactPHP, Ratchet, dNode-php, phpDaemonJava: Netty, JettyJavaScript (Node.JS): Faye, Socket.IO (Engine.IO), Primus.io.NET (C#): SignalR, XSocketsPython: Lots of options built on TornadoRuby: em-websocket, FayeLanguage agnostic: most hosted services
22 / 72
j.mp/realtime-tech-guide
23 / 72
3. Native Mobile Support?
24 / 72
Native Mobile Support?
Only some have mobile librariesHow much data are you sending?SSL required on 3/4G networks
25 / 72
FayeFirebaseHydnaPubNub
PusherRatchet (via Autobahn)SignalRSocket.IO
Solutions with Native Mobile Libraries
26 / 72
4. Application/SolutionFunctionality
27 / 72
Functionality, huh?!
28 / 72
Functionality, huh?!
Communication Patterns
29 / 72
onMessage
// client
var sock = new SockJS( 'http://localhost:9999/sockjs' );
30 / 72
onMessage
// client
var sock = new SockJS( 'http://localhost:9999/sockjs' );
sock.onmessage = function( e ) {
console.log( 'message', e.data );
};
31 / 72
onMessage
// client
var sock = new SockJS( 'http://localhost:9999/sockjs' );
sock.onmessage = function( e ) {
console.log( 'message', e.data );
};
// server
sock.write( 'hello SockJS' );
32 / 72
PubSub
// client
var client = new FayeClient();
33 / 72
PubSub
// client
var client = new FayeClient();
client.subscribe( 'chat', function( message ) {
// Handle Update
} );
34 / 72
PubSub
// client
var client = new FayeClient();
client.subscribe( 'chat', function( message ) {
// Handle Update
} );
// server
var message = {
text: 'Hello, world!',
user_name: '@leggetter'
}
Faye.publish( 'chat', message );
35 / 72
Evented PubSub
// client
var pusher = new Pusher( APP_KEY );
36 / 72
Evented PubSub
// client
var pusher = new Pusher( APP_KEY );
var channel = pusher.subscribe( 'chat' );
37 / 72
Evented PubSub
// client
var pusher = new Pusher( APP_KEY );
var channel = pusher.subscribe( 'chat' );
channel.bind( 'message', function( data ) {
// Handle Update
} );
38 / 72
Evented PubSub
// client
var pusher = new Pusher( APP_KEY );
var channel = pusher.subscribe( 'chat' );
channel.bind( 'message', function( data ) {
// Handle Update
} );
channel.bind( 'message-updated', function( data ) {} );
channel.bind( 'room-name-changed', function( data ) {} );
39 / 72
Evented PubSub
// client
var pusher = new Pusher( APP_KEY );
var channel = pusher.subscribe( 'chat' );
channel.bind( 'message', function( data ) {
// Handle Update
} );
channel.bind( 'message-updated', function( data ) {} );
channel.bind( 'room-name-changed', function( data ) {} );
// server
var data = [
'text' => 'Hello, world!',
'user_name' => '@leggetter'
}
pusher->trigger( 'chat', 'message', data );
40 / 72
Data Sync
var myDataRef = new Firebase('https://yo.firebaseio.com/');
41 / 72
Data Sync
var myDataRef = new Firebase('https://yo.firebaseio.com/');
myDataRef.push( {name: '@leggetter', text: 'Yo!'} );
42 / 72
Data Sync
var myDataRef = new Firebase('https://yo.firebaseio.com/');
myDataRef.push( {name: '@leggetter', text: 'Yo!'} );
myDataRef.on( 'child_added', function(snapshot) {
// Data added
});
myDataRef.on( 'child_changed', function(snapshot) {
// Data has changed
});
myDataRef.on( 'child_removed', function(snapshot) {
// Data removed
});
43 / 72
RMI
// client
$.connection.hub.start(); // async
var chat = $.connection.chatHub;
44 / 72
RMI
// client
$.connection.hub.start(); // async
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message
};
45 / 72
RMI
// client
$.connection.hub.start(); // async
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message
};
chat.server.send( 'me', 'hello world' );
46 / 72
RMI
// client
$.connection.hub.start(); // async
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message
};
chat.server.send( 'me', 'hello world' );
// server
public class ChatHub : Hub
{
47 / 72
RMI
// client
$.connection.hub.start(); // async
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message
};
chat.server.send( 'me', 'hello world' );
// server
public class ChatHub : Hub
{
public void Send(string name, string message)
{
48 / 72
RMI
// client
$.connection.hub.start(); // async
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message
};
chat.server.send( 'me', 'hello world' );
// server
public class ChatHub : Hub
{
public void Send(string name, string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
}
49 / 72
50 / 72
51 / 72
52 / 72
5. Architecture Considerations
53 / 72
I wanna build a real-time Symfony app
or
I wanna add real-time to an existing
Symfony app
54 / 72
Self Hosted (Tightly Coupled)
55 / 72
PHP Self-Hosted options
React (PHP)Event-driven, non-blocking I/O with PHP.
Ratchet (Built on React PHP)WebSockets, WAMP, PubSub samples. No HTTP Fallback
dnode-php (RPC/RMI)phpDaemon
Lots of examples. Most docs in Russian.
56 / 72
Chris Boden, Creator/Maintainer of React (PHP) & Ratchet
“ Yes it’s possible but not common or probably
recommended yet. There are some projects that are
starting to do this by running the HTTP stack on
React [...] but it’s very uncommon at this point in
time
57 / 72
58 / 72
Self-Hosted Demo 1: Symfony + Ratchet (Loosely Coupled)
59 / 72
Pros
PHPSimple integrationStandards-based
WAMP/AutobahnJS, Android, iOS & more
Cons
No HTTP fallbackLow-level abstractionsDifferent programming styleYou need to scale
Self-Hosted Demo 1 - Pro & Cons
60 / 72
61 / 72
Self-Hosted Demo 2: Symfony + Faye (Loosely Coupled)
62 / 72
Pros
PubSubConnection fallbackIn-build Redis/Queue supportSimple integration
Cons
Not PHP(?)You need to scale
Self-Hosted Demo 2 - Pro & Cons
63 / 72
64 / 72
Hosted Demo: Pusher
65 / 72
Pros
Simple & powerfulInstantly scalableManaged & dedicatedDirect integration into Symfony
Cons
3rd party reliance
Hosted - Pros & Cons
66 / 72
6. Self-Hosted v Hosted
"Build vs. Buy"
67 / 72
How do you choose?
6 Realtime Framework Considerations
1. Use an Existing Solution2. Use a language you're comfortable with3. Do you need native mobile support?4. onMessage, PubSub (Evented), RMI or DataSync5. Architectural considerations6. Hosted v Self-Hosted (Build vs. Buy)
69 / 72
You need Real-Time!
There are lots of options.
Make the choice that's right for you.
I hope this helps!
70 / 72
Resources
Real-time Tech GuideReact (PHP)Ratchet (PHP)Faye (Node/Ruby)PusherLopiPusherBundlegithub.com/leggetter/realtime-symfony-examples
71 / 72
Real-time Web Apps & Symfony.
What are your options?
Questions?
joind.in/14980 | leggetter.github.io/realtime-symfony
PHIL @LEGGETTERHead of Developer Relations
72 / 72