Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Real-Time Web Apps & .NET
What are Your Options?
NDC { Oslo } 10-June-2016
@leggetter
PHIL @LEGGETTER
Head of Developer Relations
leggetter@nexmo.com
3 / 105
@leggetter
4 / 105
@leggetter
What we'll cover
1. Why Real-Time?
2. Common Real-Time Use Cases
3. What are your options?
How do you choose? inc. Communi...
When do we need Realtime?
6 / 105
@leggetter
WCaaS
7 / 105
@leggetter
WCaaS
Data: Is there a timely nature to the data?
7 / 105
@leggetter
8 / 105
@leggetter
User Experience: Is there a timely nature to the
experience?
8 / 105
@leggetter
Realtime is required when there's a Need or
Demand for:
Up to date information
Interaction to maintain engagement (UX)
9 /...
Common Real-Time Use Cases
10 / 105
@leggetter
Notifications & Activity Streams
11 / 105
@leggetter
Data Visualizations
12 / 105
@leggetter
13 / 105
Chat & Bots
@leggetter
13 / 105
Chat & Bots
@leggetter
14 / 105
@leggetter
Real-Time Location Tracking
15 / 105
@leggetter
Multi-User Collaboration
16 / 105
@leggetter
WebRTC Powered AV Chat
17 / 105
@leggetter
18 / 105
@leggetter
Users expect a real-time UX
18 / 105
@leggetter
Users expect a real-time UX
Without a real-time UX your app appears
broken
18 / 105
@leggetter
You All Have Real-Time Data in Your Apps
Every Single Event
Data Changes
System Interactions
User Interactions
19 / 105
@l...
Real-time Web Apps & .NET
What are your options?
20 / 105
@leggetter
7 Factors to Consider
21 / 105
@leggetter
1. Should you keep on polling?
22 / 105
@leggetter
Polling Calculations
Scenario
1. Site average of 10,000 Users
23 / 105
@leggetter
Polling Calculations
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, with a 10 second polling interval
23 / 105
@...
Polling Calculations
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, with a 10 second polling interval
3. Request...
Polling Calculations
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, with a 10 second polling interval
3. Request...
Polling Calculations
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, with a 10 second polling interval
3. Request...
Polling Calculations
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, with a 10 second polling interval
3. Request...
Polling Calculations
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, with a 10 second polling interval
3. Request...
Cache - clients keep polling
Push Proxy solutions
fanout.io
streamdata.io
Quick Win solutions
24 / 105
@leggetter
2. Use an existing solution
Don't reinvent the wheel
Unless you've a unique use case
25 / 105
@leggetter
Why use an existing solution?
Connection fallback/upgrade hacks still required
WebSocket: 91% of connections
HTTP fallback...
Why use an existing solution?
Connection fallback/upgrade hacks still required
WebSocket: 91% of connections
HTTP fallback...
Why use an existing solution?
Connection fallback/upgrade hacks still required
WebSocket: 91% of connections
HTTP fallback...
Why use an existing solution?
Connection fallback/upgrade hacks still required
WebSocket: 91% of connections
HTTP fallback...
Why use an existing solution?
Connection fallback/upgrade hacks still required
WebSocket: 91% of connections
HTTP fallback...
27 / 105
@leggetter
j.mp/realtime-tech-guide
27 / 105
@leggetter
3. Use languages you're comfortable
with
28 / 105
@leggetter
3. Use languages you're comfortable
with
28 / 105
@leggetter
Solutions by language
PHP: Ratchet, dNode-php
Java: Netty, Jetty
JavaScript (Node.JS): Faye, Socket.IO (Engine.IO), Primus...
4. Client Device Support?
30 / 105
@leggetter
Client Device Support
Only some have a selection of client libraries
31 / 105
@leggetter
Client Device Support
Only some have a selection of client libraries
Supported connection transports
31 / 105
@leggetter
Client Device Support
Only some have a selection of client libraries
Supported connection transports
How much data are you...
Client Device Support
Only some have a selection of client libraries
Supported connection transports
How much data are you...
5. Application/Solution
Communication Patterns
32 / 105
@leggetter
5. Application/Solution
Communication Patterns
How does the client/server & client/client communicate
32 / 105
@leggetter
Simple Messaging
33 / 105
@leggetter
0:00 34 / 105
@leggetter
Internet ^5 Machine
0:00 34 / 105
@leggetter
Internet ^5 Machine
Simple Messaging
// client
var ws = new WebSocket('wss://localhost/');
35 / 105
@leggetter
Simple Messaging
// client
var ws = new WebSocket('wss://localhost/');
ws.onmessage = function(evt) {
var data = JSON.pars...
Simple Messaging
// client
var ws = new WebSocket('wss://localhost/');
ws.onmessage = function(evt) {
var data = JSON.pars...
Simple Messaging
// client
var ws = new WebSocket('wss://localhost/');
ws.onmessage = function(evt) {
var data = JSON.pars...
Simple Messaging
// client
var ws = new WebSocket('wss://localhost/');
ws.onmessage = function(evt) {
var data = JSON.pars...
Simple Messaging
using Nexmo.Api;
// SMS
var results = SMS.Send(new SMS.SMSRequest
{
from = "15555551212",
to = "177755512...
PubSub
37 / 105
@leggetter
38 / 105
@leggetter
PubSub
// client
var client = new Faye.Client('http://localhost:8000/faye');
39 / 105
@leggetter
PubSub
// client
var client = new Faye.Client('http://localhost:8000/faye');
client.subscribe('/leggetter-updates', functi...
PubSub
// client
var client = new Faye.Client('http://localhost:8000/faye');
client.subscribe('/leggetter-updates', functi...
PubSub
// client
var client = new Faye.Client('http://localhost:8000/faye');
client.subscribe('/leggetter-updates', functi...
PubSub
// client
var client = new Faye.Client('http://localhost:8000/faye');
client.subscribe('/leggetter-updates', functi...
PubSub
// client
var client = new Faye.Client('http://localhost:8000/faye');
client.subscribe('/leggetter-updates', functi...
Evented PubSub
40 / 105
@leggetter
Evented PubSub
// client
var updates = io('/leggetter-updates');
41 / 105
@leggetter
Evented PubSub
// client
var updates = io('/leggetter-updates');
updates.on('created', function (data) {
// Add activity t...
Evented PubSub
// client
var updates = io('/leggetter-updates');
updates.on('created', function (data) {
// Add activity t...
Evented PubSub
// client
var updates = io('/leggetter-updates');
updates.on('created', function (data) {
// Add activity t...
Evented PubSub
// client
var updates = io('/leggetter-updates');
updates.on('created', function (data) {
// Add activity t...
Evented PubSub
// client
var updates = io('/leggetter-updates');
updates.on('created', function (data) {
// Add activity t...
PubSub vs. Evented PubSub
42 / 105
@leggetter
43 / 105
@leggetter
44 / 105
@leggetter
PubSub
client.subscribe('devexp-channel', function(data) {
if(data.eventType === 'chat-message') {
addMessage(data.message...
PubSub
client.subscribe('devexp-channel', function(data) {
if(data.eventType === 'chat-message') {
addMessage(data.message...
PubSub
client.subscribe('devexp-channel', function(data) {
if(data.eventType === 'chat-message') {
addMessage(data.message...
PubSub
client.subscribe('devexp-channel', function(data) {
if(data.eventType === 'chat-message') {
addMessage(data.message...
DataSync
46 / 105
@leggetter
47 / 105
@leggetter
Data Sync
// client
var ref = new Firebase("https://app.firebaseio.com/doc1/lines");
48 / 105
@leggetter
Data Sync
// client
var ref = new Firebase("https://app.firebaseio.com/doc1/lines");
ref.on('child_added', function(childS...
Data Sync
// client
var ref = new Firebase("https://app.firebaseio.com/doc1/lines");
ref.on('child_added', function(childS...
Data Sync
// client
var ref = new Firebase("https://app.firebaseio.com/doc1/lines");
ref.on('child_added', function(childS...
Data Sync
// client
var ref = new Firebase("https://app.firebaseio.com/doc1/lines");
ref.on('child_added', function(childS...
Data Sync
// client
var ref = new Firebase("https://app.firebaseio.com/doc1/lines");
ref.on('child_added', function(childS...
RMI (aka RPC)
49 / 105
@leggetter
50 / 105
@leggetter
RMI
// client
var chat = $.connection.chatHub;
51 / 105
@leggetter
RMI
// client
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message...
RMI
// client
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message...
RMI
// client
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message...
RMI
// client
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message...
RMI
// client
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message...
RMI
// client
var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {
// handle message...
52 / 105
@leggetter
53 / 105
@leggetter
54 / 105
@leggetter
55 / 105
@leggetter
56 / 105
@leggetter
6. Deployment & Architecture
Considerations
57 / 105
@leggetter
Code
https://github.com/leggetter/realtime-dotnet-examples
Short link: http://j.mp/rt-dotnet-ex
58 / 105
@leggetter
Self Hosted (Tightly Coupled) 59 / 105
@leggetter
.NET Self-Hosted Real-Time options
SignalR
XSockets
60 / 105
@leggetter
61 / 105
@leggetter
Self-Hosted Demo 1: ASP.NET + SignalR (Tightly Coupled)
61 / 105
@leggetter
What we'll look at:
PM> Install-Package Microsoft.AspNet.SignalR
Scriptsjquery.signalR*.js
App_StartSignalRStartup.cs
Cont...
Pros
.NET
Simple integration
MS Supported
jQuery Dependency
Cons
Tightly coupled
RMI only
Self-Scaling
Scaling (realtime +...
64 / 105
@leggetter
Self-Hosted Demo 2: ASP.NET + XSockets (Tightly Coupled)
64 / 105
@leggetter
What we'll look at:
PM> Install-Package XSockets
App_StartXSocketsStartup.cs
ControllersHomeController.cs
XSocketsChatCont...
Pros
.NET
Simple integration
Communication patterns
PubSub/Evented
RMI
Licensed
Cons
Tightly coupled
Self-Scaling
Scaling ...
Self-Hosted: .NET + Message Queue (Loosely Coupled)
67 / 105
@leggetter
68 / 105
@leggetter
Pros
.NET
Maps well to PubSub
Loosely coupled
Could use another runtime
Cons
How does it fit with RMI/SignalR?
Multiple co...
If SignalR or XSockets aren't a good fit
you may have to look at a non-.NET solution
70 / 105
@leggetter
.NET Hosted Real-Time options
Ably
Firebase
Fanout
PubNub
Pusher
Realtime.co
Syncano
71 / 105
@leggetter
72 / 105
@leggetter
Hosted Demo: PubNub
72 / 105
@leggetter
What we'll look at:
PM> Install-Package Pubnub
ControllersChatController.cs
ViewsHomePubNub.cshtml
ScriptchatPubNub.js
Pub...
Pros
Simple & powerful
Instantly scalable
Managed & dedicated
Direct integration. No overhead.
Cons
3rd party reliance
Diff...
Why use a hosted service?
Scenario
1. Site average of 10,000 Users
75 / 105
@leggetter
Why use a hosted service?
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, no polling
75 / 105
@leggetter
Why use a hosted service?
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, no polling
3. Requests from pages load ...
Why use a hosted service?
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, no polling
3. Requests from pages load ...
Why use a hosted service?
Scenario
1. Site average of 10,000 Users
2. Over 1 Hour, no polling
3. Requests from pages load ...
7. Self-Hosted v Hosted
"Build vs. Buy"
76 / 105
@leggetter
Build vs. Buy - Costs
baremetrics.com/calculator
77 / 105
@leggetter
How do you choose?
7 Realtime Framework Considerations
1. Should you keep on polling?
2. Use an Existing Solution
3. Use a...
You need Real-Time!
There are lots of options.
Make the choice that's right for you.
I hope this helps!
79 / 105
@leggetter
Resources
Real-time Tech Guide
github.com/leggetter/realtime-dotnet-examples
Tools, Tips and Techniques for Developing Rea...
Real-time Web Apps & .NET
What are your options?
Questions?
PHIL @LEGGETTER
Head of Developer Relations
81 / 105
@leggetter
Future (If Time)
82 / 105
@leggetter
Network Infrastructure & Protocols
Reliability
Speed
Beyond HTTP
HTTP2
83 / 105
@leggetter
Bayeux
DDP
dNode
EPCP
GRIP
gRPC
MQTT
Pusher Protocol
STOMP
SignalR Protocol
WAMP (Web App Messaging Protocol)
XMPP (variou...
85 / 105
@leggetter
Firebase
GitHub
Iron.io
MailChimp
MailJet
PagerDuty
Nexmo
SendGrid
Real-Time APIs
86 / 105
@leggetter
87 / 105
@leggetter
More "Things"!
88 / 105
@leggetter
The Physical Web
89 / 105
@leggetter
IoT, Apps & Developers
90 / 105
@leggetter
A thing can be anything
91 / 105
@leggetter
A thing can be anything
Sensors
Appliances
Vehicles
Smart Phones
Devices (Arduino, Electric Imp, Raspberry Pi etc.)
91 / 1...
A thing can be anything
Sensors
Appliances
Vehicles
Smart Phones
Devices (Arduino, Electric Imp, Raspberry Pi etc.)
Server...
The Majority of code we'll write will still be
for "Apps"
Configuring
Monitoring
Interacting
App Logic
92 / 105
@leggetter
Real-Time Use Case Evolution
Notifications & Signalling
Activity Streams
Data Viz & Polls
Chat
Collaboration
Multiplayer G...
Notifications/Activity Streams -> Actions
94 / 105
@leggetter
The end of apps as we know it - Intercom
Subscriptions
95 / 105
@leggetter
Personalised Event Streams
96 / 105
@leggetter
Unified UIs
97 / 105
@leggetter
Chat & Bots for Everything and the rise of the .ai domain 98 / 105
@leggetter
600M MAUs
10M integrations
app-within-an-app model
taxi, order food, tickets, games etc.
WeChat
99 / 105
@leggetter
Chat Integrations
100 / 105
@leggetter
Siri
Google Now
Microso Cortana
Facebook M
Chat "Virtual Assistants"
101 / 105
@leggetter
102 / 105
@leggetter
Chat has evolved. Chat is now a platform!
103 / 105
@leggetter
Multi-Device Experiences
104 / 105
@leggetter
Ben Foxall - A conceptual future for the multi-device web (FutureJS 2014)
105 / 105
@leggetter
Prochain SlideShare
Chargement dans…5
×

Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016

412 vues

Publié le

Real-time is becoming the life blood of applications. Facebook, Twitter, Uber, Google Docs and many more apps have increased user expectation to demand real-time features. Features such as Notifications, activity streams, real-time data visualisations, chat or collaborative experiences instantly keep users up to date and enable them to work much more effectively. So, how do you build these sorts of features with .NET?
This talk will cover the benefits of moving away from polling to push, the options you have with .NET web application to do this and when adding real-time features to your apps, and the pros and cons of each to help choose which is the best solution for you.

Publié dans : Logiciels
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016

  1. 1. Real-Time Web Apps & .NET What are Your Options? NDC { Oslo } 10-June-2016 @leggetter
  2. 2. PHIL @LEGGETTER Head of Developer Relations leggetter@nexmo.com 3 / 105 @leggetter
  3. 3. 4 / 105 @leggetter
  4. 4. What we'll cover 1. Why Real-Time? 2. Common Real-Time Use Cases 3. What are your options? How do you choose? inc. Communication Patterns .NET examples Pros & Cons 4. Q&A 5 / 105 @leggetter
  5. 5. When do we need Realtime? 6 / 105 @leggetter
  6. 6. WCaaS 7 / 105 @leggetter
  7. 7. WCaaS Data: Is there a timely nature to the data? 7 / 105 @leggetter
  8. 8. 8 / 105 @leggetter
  9. 9. User Experience: Is there a timely nature to the experience? 8 / 105 @leggetter
  10. 10. Realtime is required when there's a Need or Demand for: Up to date information Interaction to maintain engagement (UX) 9 / 105 @leggetter
  11. 11. Common Real-Time Use Cases 10 / 105 @leggetter
  12. 12. Notifications & Activity Streams 11 / 105 @leggetter
  13. 13. Data Visualizations 12 / 105 @leggetter
  14. 14. 13 / 105 Chat & Bots @leggetter
  15. 15. 13 / 105 Chat & Bots @leggetter
  16. 16. 14 / 105 @leggetter
  17. 17. Real-Time Location Tracking 15 / 105 @leggetter
  18. 18. Multi-User Collaboration 16 / 105 @leggetter
  19. 19. WebRTC Powered AV Chat 17 / 105 @leggetter
  20. 20. 18 / 105 @leggetter
  21. 21. Users expect a real-time UX 18 / 105 @leggetter
  22. 22. Users expect a real-time UX Without a real-time UX your app appears broken 18 / 105 @leggetter
  23. 23. You All Have Real-Time Data in Your Apps Every Single Event Data Changes System Interactions User Interactions 19 / 105 @leggetter
  24. 24. Real-time Web Apps & .NET What are your options? 20 / 105 @leggetter
  25. 25. 7 Factors to Consider 21 / 105 @leggetter
  26. 26. 1. Should you keep on polling? 22 / 105 @leggetter
  27. 27. Polling Calculations Scenario 1. Site average of 10,000 Users 23 / 105 @leggetter
  28. 28. Polling Calculations Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, with a 10 second polling interval 23 / 105 @leggetter
  29. 29. Polling Calculations Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, with a 10 second polling interval 3. Requests from pages load + HTML, CSS, JS, Images for 10k users = 50,000 23 / 105 @leggetter
  30. 30. Polling Calculations Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, with a 10 second polling interval 3. Requests from pages load + HTML, CSS, JS, Images for 10k users = 50,000 4. Poll requests per user/minute = (60 / 10) = 6 23 / 105 @leggetter
  31. 31. Polling Calculations Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, with a 10 second polling interval 3. Requests from pages load + HTML, CSS, JS, Images for 10k users = 50,000 4. Poll requests per user/minute = (60 / 10) = 6 5. Poll requests per user/hour = (6 * 60) = 360 23 / 105 @leggetter
  32. 32. Polling Calculations Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, with a 10 second polling interval 3. Requests from pages load + HTML, CSS, JS, Images for 10k users = 50,000 4. Poll requests per user/minute = (60 / 10) = 6 5. Poll requests per user/hour = (6 * 60) = 360 6. Poll requests site wide per hour = (360 * 10,000) = 3,600,000 23 / 105 @leggetter
  33. 33. Polling Calculations Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, with a 10 second polling interval 3. Requests from pages load + HTML, CSS, JS, Images for 10k users = 50,000 4. Poll requests per user/minute = (60 / 10) = 6 5. Poll requests per user/hour = (6 * 60) = 360 6. Poll requests site wide per hour = (360 * 10,000) = 3,600,000 With polling the site would need to handle 3.65 Million requests per hour Or 50k HTTP requests + maintain 10k persistent connections? 23 / 105 @leggetter
  34. 34. Cache - clients keep polling Push Proxy solutions fanout.io streamdata.io Quick Win solutions 24 / 105 @leggetter
  35. 35. 2. Use an existing solution Don't reinvent the wheel Unless you've a unique use case 25 / 105 @leggetter
  36. 36. Why use an existing solution? Connection fallback/upgrade hacks still required WebSocket: 91% of connections HTTP fallback: 9% of connections 26 / 105 @leggetter
  37. 37. Why use an existing solution? Connection fallback/upgrade hacks still required WebSocket: 91% of connections HTTP fallback: 9% of connections Support/Community 26 / 105 @leggetter
  38. 38. Why use an existing solution? Connection fallback/upgrade hacks still required WebSocket: 91% of connections HTTP fallback: 9% of connections Support/Community Maintenance 26 / 105 @leggetter
  39. 39. Why use an existing solution? Connection fallback/upgrade hacks still required WebSocket: 91% of connections HTTP fallback: 9% of connections Support/Community Maintenance Future features 26 / 105 @leggetter
  40. 40. Why use an existing solution? Connection fallback/upgrade hacks still required WebSocket: 91% of connections HTTP fallback: 9% of connections Support/Community Maintenance Future features Scaling 26 / 105 @leggetter
  41. 41. 27 / 105 @leggetter
  42. 42. j.mp/realtime-tech-guide 27 / 105 @leggetter
  43. 43. 3. Use languages you're comfortable with 28 / 105 @leggetter
  44. 44. 3. Use languages you're comfortable with 28 / 105 @leggetter
  45. 45. Solutions by language PHP: Ratchet, dNode-php Java: Netty, Jetty JavaScript (Node.JS): Faye, Socket.IO (Engine.IO), Primus.io .NET (C#): SignalR, XSockets Python: Lots of options built on Tornado Ruby: em-websocket, Faye Language agnostic: most hosted services 29 / 105 @leggetter
  46. 46. 4. Client Device Support? 30 / 105 @leggetter
  47. 47. Client Device Support Only some have a selection of client libraries 31 / 105 @leggetter
  48. 48. Client Device Support Only some have a selection of client libraries Supported connection transports 31 / 105 @leggetter
  49. 49. Client Device Support Only some have a selection of client libraries Supported connection transports How much data are you sending? 31 / 105 @leggetter
  50. 50. Client Device Support Only some have a selection of client libraries Supported connection transports How much data are you sending? SSL required on 3/4G networks 31 / 105 @leggetter
  51. 51. 5. Application/Solution Communication Patterns 32 / 105 @leggetter
  52. 52. 5. Application/Solution Communication Patterns How does the client/server & client/client communicate 32 / 105 @leggetter
  53. 53. Simple Messaging 33 / 105 @leggetter
  54. 54. 0:00 34 / 105 @leggetter Internet ^5 Machine
  55. 55. 0:00 34 / 105 @leggetter Internet ^5 Machine
  56. 56. Simple Messaging // client var ws = new WebSocket('wss://localhost/'); 35 / 105 @leggetter
  57. 57. Simple Messaging // client var ws = new WebSocket('wss://localhost/'); ws.onmessage = function(evt) { var data = JSON.parse(evt.data); 35 / 105 @leggetter
  58. 58. Simple Messaging // client var ws = new WebSocket('wss://localhost/'); ws.onmessage = function(evt) { var data = JSON.parse(evt.data); // ^5 performHighFive(); }; 35 / 105 @leggetter
  59. 59. Simple Messaging // client var ws = new WebSocket('wss://localhost/'); ws.onmessage = function(evt) { var data = JSON.parse(evt.data); // ^5 performHighFive(); }; // server server.on('connection', function(socket){ 35 / 105 @leggetter
  60. 60. Simple Messaging // client var ws = new WebSocket('wss://localhost/'); ws.onmessage = function(evt) { var data = JSON.parse(evt.data); // ^5 performHighFive(); }; // server server.on('connection', function(socket){ socket.send(JSON.stringify({action: 'high-5'})); }); 35 / 105 @leggetter
  61. 61. Simple Messaging using Nexmo.Api; // SMS var results = SMS.Send(new SMS.SMSRequest { from = "15555551212", to = "17775551212", text = "this is a test" }); // Voice var result = Voice.TextToSpeech(new Voice.TextToSpeechCallCommand { to = "17775551212", from = "15555551212", text = "Hello from Nexmo" }); 36 / 105 @leggetter
  62. 62. PubSub 37 / 105 @leggetter
  63. 63. 38 / 105 @leggetter
  64. 64. PubSub // client var client = new Faye.Client('http://localhost:8000/faye'); 39 / 105 @leggetter
  65. 65. PubSub // client var client = new Faye.Client('http://localhost:8000/faye'); client.subscribe('/leggetter-updates', function(data) { 39 / 105 @leggetter
  66. 66. PubSub // client var client = new Faye.Client('http://localhost:8000/faye'); client.subscribe('/leggetter-updates', function(data) { console.log(data.text); }); 39 / 105 @leggetter
  67. 67. PubSub // client var client = new Faye.Client('http://localhost:8000/faye'); client.subscribe('/leggetter-updates', function(data) { console.log(data.text); }); client.subscribe('/leggetter-dm-notifications', function(data) { console.log(data.count); }); 39 / 105 @leggetter
  68. 68. PubSub // client var client = new Faye.Client('http://localhost:8000/faye'); client.subscribe('/leggetter-updates', function(data) { console.log(data.text); }); client.subscribe('/leggetter-dm-notifications', function(data) { console.log(data.count); }); // server server.publish('/leggetter-updates', {text: 'Hello DevWeek!'}); 39 / 105 @leggetter
  69. 69. PubSub // client var client = new Faye.Client('http://localhost:8000/faye'); client.subscribe('/leggetter-updates', function(data) { console.log(data.text); }); client.subscribe('/leggetter-dm-notifications', function(data) { console.log(data.count); }); // server server.publish('/leggetter-updates', {text: 'Hello DevWeek!'}); server.publish('/leggetter-dm-notifications', {count: 2}); 39 / 105 @leggetter
  70. 70. Evented PubSub 40 / 105 @leggetter
  71. 71. Evented PubSub // client var updates = io('/leggetter-updates'); 41 / 105 @leggetter
  72. 72. Evented PubSub // client var updates = io('/leggetter-updates'); updates.on('created', function (data) { // Add activity to UI }); 41 / 105 @leggetter
  73. 73. Evented PubSub // client var updates = io('/leggetter-updates'); updates.on('created', function (data) { // Add activity to UI }); updates.on('updated', function(data) { // Update activity }); updates.on('deleted', function(data) { // Remove activity }); 41 / 105 @leggetter
  74. 74. Evented PubSub // client var updates = io('/leggetter-updates'); updates.on('created', function (data) { // Add activity to UI }); updates.on('updated', function(data) { // Update activity }); updates.on('deleted', function(data) { // Remove activity }); // server var io = require('socket.io')(); var updates = io.of('/leggetter-updates'); 41 / 105 @leggetter
  75. 75. Evented PubSub // client var updates = io('/leggetter-updates'); updates.on('created', function (data) { // Add activity to UI }); updates.on('updated', function(data) { // Update activity }); updates.on('deleted', function(data) { // Remove activity }); // server var io = require('socket.io')(); var updates = io.of('/leggetter-updates'); updates.emit('created', {text: 'PubSub Rocks!', id: 1}); 41 / 105 @leggetter
  76. 76. Evented PubSub // client var updates = io('/leggetter-updates'); updates.on('created', function (data) { // Add activity to UI }); updates.on('updated', function(data) { // Update activity }); updates.on('deleted', function(data) { // Remove activity }); // server var io = require('socket.io')(); var updates = io.of('/leggetter-updates'); updates.emit('created', {text: 'PubSub Rocks!', id: 1}); updates.emit('updated', {text: 'Evented PubSub Rocks!', id: 1}); updates.emit('deleted', {id: 1}); 41 / 105 @leggetter
  77. 77. PubSub vs. Evented PubSub 42 / 105 @leggetter
  78. 78. 43 / 105 @leggetter
  79. 79. 44 / 105 @leggetter
  80. 80. PubSub client.subscribe('devexp-channel', function(data) { if(data.eventType === 'chat-message') { addMessage(data.message); } 45 / 105 @leggetter
  81. 81. PubSub client.subscribe('devexp-channel', function(data) { if(data.eventType === 'chat-message') { addMessage(data.message); } else if(data.eventType === 'channel-purposed-changed') { updateRoomTitle(data.purpose); } else if(/* and so on */) { } }) 45 / 105 @leggetter
  82. 82. PubSub client.subscribe('devexp-channel', function(data) { if(data.eventType === 'chat-message') { addMessage(data.message); } else if(data.eventType === 'channel-purposed-changed') { updateRoomTitle(data.purpose); } else if(/* and so on */) { } }) Evented PubSub var devexp = io('/devexp-channel'); devexp.on('chat-message', addMessage); devexp.on('channel-purposed-changed', updateChannelPurpose); 45 / 105 @leggetter
  83. 83. PubSub client.subscribe('devexp-channel', function(data) { if(data.eventType === 'chat-message') { addMessage(data.message); } else if(data.eventType === 'channel-purposed-changed') { updateRoomTitle(data.purpose); } else if(/* and so on */) { } }) Evented PubSub var devexp = io('/devexp-channel'); devexp.on('chat-message', addMessage); devexp.on('channel-purposed-changed', updateChannelPurpose); devexp.on('current-topic-changed', updateChannelTopic); devexp.on('user-online', userOnline); devexp.on('user-offline', userOffline); 45 / 105 @leggetter
  84. 84. DataSync 46 / 105 @leggetter
  85. 85. 47 / 105 @leggetter
  86. 86. Data Sync // client var ref = new Firebase("https://app.firebaseio.com/doc1/lines"); 48 / 105 @leggetter
  87. 87. Data Sync // client var ref = new Firebase("https://app.firebaseio.com/doc1/lines"); ref.on('child_added', function(childSnapshot, prevChildKey) { // code to handle new child. }); 48 / 105 @leggetter
  88. 88. Data Sync // client var ref = new Firebase("https://app.firebaseio.com/doc1/lines"); ref.on('child_added', function(childSnapshot, prevChildKey) { // code to handle new child. }); ref.on('child_changed', function(childSnapshot, prevChildKey) { // code to handle child data changes. }); 48 / 105 @leggetter
  89. 89. Data Sync // client var ref = new Firebase("https://app.firebaseio.com/doc1/lines"); ref.on('child_added', function(childSnapshot, prevChildKey) { // code to handle new child. }); ref.on('child_changed', function(childSnapshot, prevChildKey) { // code to handle child data changes. }); ref.on('child_removed', function(oldChildSnapshot) { // code to handle child removal. }); 48 / 105 @leggetter
  90. 90. Data Sync // client var ref = new Firebase("https://app.firebaseio.com/doc1/lines"); ref.on('child_added', function(childSnapshot, prevChildKey) { // code to handle new child. }); ref.on('child_changed', function(childSnapshot, prevChildKey) { // code to handle child data changes. }); ref.on('child_removed', function(oldChildSnapshot) { // code to handle child removal. }); ref.push({ 'editor_id': 'leggetter', 'text': 'Nexmo Rocks!' }); 48 / 105 @leggetter
  91. 91. Data Sync // client var ref = new Firebase("https://app.firebaseio.com/doc1/lines"); ref.on('child_added', function(childSnapshot, prevChildKey) { // code to handle new child. }); ref.on('child_changed', function(childSnapshot, prevChildKey) { // code to handle child data changes. }); ref.on('child_removed', function(oldChildSnapshot) { // code to handle child removal. }); ref.push({ 'editor_id': 'leggetter', 'text': 'Nexmo Rocks!' }); Framework handles updates to other clients 48 / 105 @leggetter
  92. 92. RMI (aka RPC) 49 / 105 @leggetter
  93. 93. 50 / 105 @leggetter
  94. 94. RMI // client var chat = $.connection.chatHub; 51 / 105 @leggetter
  95. 95. RMI // client var chat = $.connection.chatHub; chat.client.broadcastMessage = function (name, message) { // handle message }; 51 / 105 @leggetter
  96. 96. RMI // client var chat = $.connection.chatHub; chat.client.broadcastMessage = function (name, message) { // handle message }; chat.server.send( 'me', 'hello world' ); 51 / 105 @leggetter
  97. 97. RMI // client var chat = $.connection.chatHub; chat.client.broadcastMessage = function (name, message) { // handle message }; chat.server.send( 'me', 'hello world' ); $.connection.hub.start(); // async 51 / 105 @leggetter
  98. 98. RMI // client var chat = $.connection.chatHub; chat.client.broadcastMessage = function (name, message) { // handle message }; chat.server.send( 'me', 'hello world' ); $.connection.hub.start(); // async // server public class ChatHub : Hub { 51 / 105 @leggetter
  99. 99. RMI // client var chat = $.connection.chatHub; chat.client.broadcastMessage = function (name, message) { // handle message }; chat.server.send( 'me', 'hello world' ); $.connection.hub.start(); // async // server public class ChatHub : Hub { public void Send(string name, string message) { 51 / 105 @leggetter
  100. 100. RMI // client var chat = $.connection.chatHub; chat.client.broadcastMessage = function (name, message) { // handle message }; chat.server.send( 'me', 'hello world' ); $.connection.hub.start(); // async // server public class ChatHub : Hub { public void Send(string name, string message) { // Call the broadcastMessage method to update clients. Clients.All.broadcastMessage(name, message); } } 51 / 105 @leggetter
  101. 101. 52 / 105 @leggetter
  102. 102. 53 / 105 @leggetter
  103. 103. 54 / 105 @leggetter
  104. 104. 55 / 105 @leggetter
  105. 105. 56 / 105 @leggetter
  106. 106. 6. Deployment & Architecture Considerations 57 / 105 @leggetter
  107. 107. Code https://github.com/leggetter/realtime-dotnet-examples Short link: http://j.mp/rt-dotnet-ex 58 / 105 @leggetter
  108. 108. Self Hosted (Tightly Coupled) 59 / 105 @leggetter
  109. 109. .NET Self-Hosted Real-Time options SignalR XSockets 60 / 105 @leggetter
  110. 110. 61 / 105 @leggetter
  111. 111. Self-Hosted Demo 1: ASP.NET + SignalR (Tightly Coupled) 61 / 105 @leggetter
  112. 112. What we'll look at: PM> Install-Package Microsoft.AspNet.SignalR Scriptsjquery.signalR*.js App_StartSignalRStartup.cs ControllersHomeController.cs HubsChatHub.cs ViewsHomeSignalR.cshtml ScriptchatSignalRChat.js 62 / 105 @leggetter
  113. 113. Pros .NET Simple integration MS Supported jQuery Dependency Cons Tightly coupled RMI only Self-Scaling Scaling (realtime + HTTP) Self-Hosted Demo 1: Pro & Cons 63 / 105 @leggetter
  114. 114. 64 / 105 @leggetter
  115. 115. Self-Hosted Demo 2: ASP.NET + XSockets (Tightly Coupled) 64 / 105 @leggetter
  116. 116. What we'll look at: PM> Install-Package XSockets App_StartXSocketsStartup.cs ControllersHomeController.cs XSocketsChatController.cs ViewsHomeXSockets.cshtml ScriptsXSockets.latest.js ScriptchatXSocketsChat.cs 65 / 105 @leggetter
  117. 117. Pros .NET Simple integration Communication patterns PubSub/Evented RMI Licensed Cons Tightly coupled Self-Scaling Scaling (realtime + HTTP) Licensed Self-Hosted Demo 2: Pro & Cons 66 / 105 @leggetter
  118. 118. Self-Hosted: .NET + Message Queue (Loosely Coupled) 67 / 105 @leggetter
  119. 119. 68 / 105 @leggetter
  120. 120. Pros .NET Maps well to PubSub Loosely coupled Could use another runtime Cons How does it fit with RMI/SignalR? Multiple components Self-scaling Queue routing questions In: HTTP. Out: WebSocket Self-Hosted: .NET + Message Queue - Pro & Cons 69 / 105 @leggetter
  121. 121. If SignalR or XSockets aren't a good fit you may have to look at a non-.NET solution 70 / 105 @leggetter
  122. 122. .NET Hosted Real-Time options Ably Firebase Fanout PubNub Pusher Realtime.co Syncano 71 / 105 @leggetter
  123. 123. 72 / 105 @leggetter
  124. 124. Hosted Demo: PubNub 72 / 105 @leggetter
  125. 125. What we'll look at: PM> Install-Package Pubnub ControllersChatController.cs ViewsHomePubNub.cshtml ScriptchatPubNub.js PubNub Real-Time Analytics 73 / 105 @leggetter
  126. 126. Pros Simple & powerful Instantly scalable Managed & dedicated Direct integration. No overhead. Cons 3rd party reliance Difficult to influence functionality Hosted - Pros & Cons 74 / 105 @leggetter
  127. 127. Why use a hosted service? Scenario 1. Site average of 10,000 Users 75 / 105 @leggetter
  128. 128. Why use a hosted service? Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, no polling 75 / 105 @leggetter
  129. 129. Why use a hosted service? Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, no polling 3. Requests from pages load + HTML, CSS, JS, Images for 10k users = 50,000 75 / 105 @leggetter
  130. 130. Why use a hosted service? Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, no polling 3. Requests from pages load + HTML, CSS, JS, Images for 10k users = 50,000 4. That's it! Total: 50,000 75 / 105 @leggetter
  131. 131. Why use a hosted service? Scenario 1. Site average of 10,000 Users 2. Over 1 Hour, no polling 3. Requests from pages load + HTML, CSS, JS, Images for 10k users = 50,000 4. That's it! Total: 50,000 Your servers handle 50k requests per hour instead of 3.6M You offload the polling or persistent connections to the service 75 / 105 @leggetter
  132. 132. 7. Self-Hosted v Hosted "Build vs. Buy" 76 / 105 @leggetter
  133. 133. Build vs. Buy - Costs baremetrics.com/calculator 77 / 105 @leggetter
  134. 134. How do you choose? 7 Realtime Framework Considerations 1. Should you keep on polling? 2. Use an Existing Solution 3. Use a language you're comfortable with 4. Do you need multiple client device support? 5. Simple Messaging, PubSub/Evented, RMI or DataSync 6. Architectural considerations 7. Hosted v Self-Hosted (Build vs. Buy) 78 / 105 @leggetter
  135. 135. You need Real-Time! There are lots of options. Make the choice that's right for you. I hope this helps! 79 / 105 @leggetter
  136. 136. Resources Real-time Tech Guide github.com/leggetter/realtime-dotnet-examples Tools, Tips and Techniques for Developing Real- time Apps Nexmo 80 / 105 @leggetter
  137. 137. Real-time Web Apps & .NET What are your options? Questions? PHIL @LEGGETTER Head of Developer Relations 81 / 105 @leggetter
  138. 138. Future (If Time) 82 / 105 @leggetter
  139. 139. Network Infrastructure & Protocols Reliability Speed Beyond HTTP HTTP2 83 / 105 @leggetter
  140. 140. Bayeux DDP dNode EPCP GRIP gRPC MQTT Pusher Protocol STOMP SignalR Protocol WAMP (Web App Messaging Protocol) XMPP (various) Communication Pattern Protocol Standardisation 84 / 105 @leggetter
  141. 141. 85 / 105 @leggetter
  142. 142. Firebase GitHub Iron.io MailChimp MailJet PagerDuty Nexmo SendGrid Real-Time APIs 86 / 105 @leggetter
  143. 143. 87 / 105 @leggetter
  144. 144. More "Things"! 88 / 105 @leggetter
  145. 145. The Physical Web 89 / 105 @leggetter
  146. 146. IoT, Apps & Developers 90 / 105 @leggetter
  147. 147. A thing can be anything 91 / 105 @leggetter
  148. 148. A thing can be anything Sensors Appliances Vehicles Smart Phones Devices (Arduino, Electric Imp, Raspberry Pi etc.) 91 / 105 @leggetter
  149. 149. A thing can be anything Sensors Appliances Vehicles Smart Phones Devices (Arduino, Electric Imp, Raspberry Pi etc.) Servers Browsers Apps: Native, Web, running anywhere 91 / 105 @leggetter
  150. 150. The Majority of code we'll write will still be for "Apps" Configuring Monitoring Interacting App Logic 92 / 105 @leggetter
  151. 151. Real-Time Use Case Evolution Notifications & Signalling Activity Streams Data Viz & Polls Chat Collaboration Multiplayer Games 93 / 105 @leggetter
  152. 152. Notifications/Activity Streams -> Actions 94 / 105 @leggetter The end of apps as we know it - Intercom
  153. 153. Subscriptions 95 / 105 @leggetter
  154. 154. Personalised Event Streams 96 / 105 @leggetter
  155. 155. Unified UIs 97 / 105 @leggetter
  156. 156. Chat & Bots for Everything and the rise of the .ai domain 98 / 105 @leggetter
  157. 157. 600M MAUs 10M integrations app-within-an-app model taxi, order food, tickets, games etc. WeChat 99 / 105 @leggetter
  158. 158. Chat Integrations 100 / 105 @leggetter
  159. 159. Siri Google Now Microso Cortana Facebook M Chat "Virtual Assistants" 101 / 105 @leggetter
  160. 160. 102 / 105 @leggetter
  161. 161. Chat has evolved. Chat is now a platform! 103 / 105 @leggetter
  162. 162. Multi-Device Experiences 104 / 105 @leggetter
  163. 163. Ben Foxall - A conceptual future for the multi-device web (FutureJS 2014) 105 / 105 @leggetter

×