Your SlideShare is downloading. ×
0
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Sometimes web sockets_dont_work
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Sometimes web sockets_dont_work

724

Published on

Presentation by Pawel Ledwon at the 1st XMPP / Realtime Meetup

Presentation by Pawel Ledwon at the 1st XMPP / Realtime Meetup

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
724
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
6
Comments
0
Likes
1
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

Transcript

  • 1. SOMETIMESWEBSOCKETSDON’T WORK @pawel_ledwon
  • 2. WE DOWEBSOCKETS …and a bit more
  • 3. REASONS TO LOVEWebSockets persistent and bi-directional very straightforward API don’t incur too much latency
  • 4. var websocket = new WebSocket("ws://example.com");websocket.onopen = function() { websocket.send("Howdy!");};websocket.onmessage = function(message) { console.log("BEEP", message.data);};
  • 5. DONE!
  • 6. NOPE!
  • 7. WHAT’S THE ISSUE?1.ancient browsers2.corporate firewalls3.restrictive proxies ...
  • 8. L E T ’SSOLVETHEM!
  • 9. PRIMARY OBJECTIVES1.improve connectivity2.provide clients with best possible transport3.improve initial latency
  • 10. SECONDARY OBJECTIVES1.keep costs reasonable2.gather some metrics3.allow experimenting
  • 11. DESIGN
  • 12. TRANSPORTa type ofconnection
  • 13. DIFFERENT TRANSPORTS WebSockets Flash HTTP-based (SSL/Non-SSL)
  • 14. TRANSPORT CLASSTransport.connect(url) ...
  • 15. STRATEGYa recipe for findingbest workingtransport
  • 16. STRATEGIES SHOULD BE 1.quick and effective 2.easy to understand 3.also easy to test 4.simple to modify
  • 17. BACK TO OUR PROBLEMS 1.ancient browsers 2.corporate firewalls 3.restrictive proxies
  • 18. ANCIENT BROWSERSeasiest problem to solve client-side checksno communication needed
  • 19. if (WebSocketTransport.isSupported()) { return WebSocketTransport;} else if (FlashTransport.isSupported()) { return FlashTransport;} else { return HTTPTransport;}
  • 20. TRANSPORT CLASSTransport.connect(url)Transport.isSupported()
  • 21. BACK TO OUR PROBLEMS 1.ancient browsers 2.corporate firewalls 3.restrictive proxies
  • 22. FLASH & FIREWALLS neeeds port 843 to be open or…waits 3s before trying original port … you never know what’s coming
  • 23. FLASH IS NOT THAT BAD1.it’s basically a WebSocket2.has low message latency3.requires less infrastructure
  • 24. DIFFERENT SOLUTIONS 1.give up and avoid Flash 2.wait and switch to HTTP 3.try Flash & HTTP in parallel 1.use first connected 2.switch to Flash
  • 25. CONNECTING IN PARALLEL Flasha) HTTP Flashb) HTTP Flashc) HTTP
  • 26. BACK TO OUR PROBLEMS 1.ancient browsers 2.corporate firewalls 3.restrictive proxies
  • 27. WEBSOCKETS & PROXIES some work just fine some are too old some just hate us all
  • 28. WEBSOCKETS & PROXIESissues with upgradingfrequent disconnectionssame issue with Flash
  • 29. DEALING WITH IT1.handle WebSockets like Flash2.use encrypted connections3.detect broken connections4.disable transports temporarily
  • 30. CACHING1.run full strategy on 1st attempt2.cache info about best transport3.use cache on subsequent attempts
  • 31. STRATEGIES - RECAPdetect browser features cache transport info connect in parallel detect disconnections retry attempts disable transports support delays support timeouts
  • 32. IMPLEMENTATION
  • 33. SINGLE RESPONSIBILITY PRINCIPLE one decision per strategy simple interface lots different types
  • 34. var runner = strategy.connect(function(error, connection) { if (error) { console.log(":("); } else { // we can even get multiple connections console.log("We’ve got a connection!"); }});// ok, it has been long enough, I’m giving uprunner.abort();
  • 35. COMPOSING STRATEGIES strategies form trees they can use other strategiesdecisions are still simple and local
  • 36. STRATEGIES1.transport provides transport to strategy adapter2.if runs a test and choses another strategy3.best connected runs in parallel to find best strategy4.sequential runs strategies sequentially5.delayed runs a strategy with a delay6.cached stores and fetches cached transport info7.first connected terminates a strategy on first connection
  • 37. transport ws
  • 38. sequentialtransport ws
  • 39. sequential sequentialtransport transport ws sockjs
  • 40. delayedsequential sequentialtransport transport ws sockjs
  • 41. best connected delayedsequential sequentialtransport transport ws sockjs
  • 42. if ws.isSupported() true best connected delayedsequential sequentialtransport transport ws sockjs
  • 43. if ws.isSupported() true false best connected sequential delayed transportsequential sequential sockjstransport transport ws sockjs
  • 44. cached if ws.isSupported() true false best connected sequential delayed transportsequential sequential sockjstransport transport ws sockjs
  • 45. REPRESENTATION
  • 46. REPRESENTATION SHOULD BE1.understandable by humans2.easy to read in JavaScript3.possible to send to clients4.simple to modify and test
  • 47. SENDING JS IS NOT AN OPTION 1.it’s dangerous 2.too expressive 3.difficult to test
  • 48. JSON1.has no side-effects2.widely supported3.known by everyone
  • 49. JSONneeds an interpreter
  • 50. DESIRABLE FEATURES1.ability to define variables2.passing by reference3.predictable execution4.limited expressiveness
  • 51. [ [":def", "ws_options", { hostUnencrypted: Pusher.host + ":" + Pusher.ws_port, hostEncrypted: Pusher.host + ":" + Pusher.wss_port, lives: 2 }], [":def", "sockjs_options", { hostUnencrypted: Pusher.sockjs_host + ":" + Pusher.sockjs_http_port, hostEncrypted: Pusher.sockjs_host + ":" + Pusher.sockjs_https_port }], [":def", "timeouts", { loop: true, timeout: 15000, timeoutLimit: 60000 }], [":def_transport", "ws", "ws", 3, ":ws_options"], [":def_transport", "sockjs", "sockjs", 1, ":sockjs_options"], [":def", "ws_loop", [":sequential", ":timeouts", ":ws"]], [":def", "sockjs_loop", [":sequential", ":timeouts", ":sockjs"]], [":def", "strategy", [":cached", 1800000, [":if", [":is_supported", ":ws"], [ ":best_connected_ever", ":ws_loop", [":delayed", 2000, [":sockjs_loop"]] ], [ ":sockjs_loop" ] ]] ] ]]
  • 52. [ [":def", "ws_options", { hostUnencrypted: Pusher.host + ":" + Pusher.ws_port, hostEncrypted: Pusher.host + ":" + Pusher.wss_port, lives: 2 }], [":def", "sockjs_options", { hostUnencrypted: Pusher.sockjs_host + ":" + Pusher.sockjs_http_port, hostEncrypted: Pusher.sockjs_host + ":" + Pusher.sockjs_https_port }], [":def", "timeouts", { loop: true, timeout: 15000, timeoutLimit: 60000 }], [":def_transport", "ws", "ws", 3, ":ws_options"], [":def_transport", "sockjs", "sockjs", 1, ":sockjs_options"], [":def", "ws_loop", [":sequential", ":timeouts", ":ws"]], [":def", "sockjs_loop", [":sequential", ":timeouts", ":sockjs"]], [":def", "strategy", [":cached", 1800000, [":if", [":is_supported", ":ws"], [ ":best_connected_ever", ":ws_loop", [":delayed", 2000, [":sockjs_loop"]] ], [ ":sockjs_loop" ] ]] ] ]]
  • 53. [ [":def", "ws_options", { hostUnencrypted: Pusher.host + ":" + Pusher.ws_port, hostEncrypted: Pusher.host + ":" + Pusher.wss_port, lives: 2 }], [":def", "sockjs_options", { hostUnencrypted: Pusher.sockjs_host + ":" + Pusher.sockjs_http_port, hostEncrypted: Pusher.sockjs_host + ":" + Pusher.sockjs_https_port }], [":def", "timeouts", { loop: true, timeout: 15000, timeoutLimit: 60000 }], [":def_transport", "ws", "ws", 3, ":ws_options"], [":def_transport", "sockjs", "sockjs", 1, ":sockjs_options"], [":def", "ws_loop", [":sequential", ":timeouts", ":ws"]], [":def", "sockjs_loop", [":sequential", ":timeouts", ":sockjs"]], [":def", "strategy", [":cached", 1800000, [":if", [":is_supported", ":ws"], [ ":best_connected_ever", ":ws_loop", [":delayed", 2000, [":sockjs_loop"]] ], [ ":sockjs_loop" ] ]] ] ]]
  • 54. [ [":def", "ws_options", { hostUnencrypted: Pusher.host + ":" + Pusher.ws_port, hostEncrypted: Pusher.host + ":" + Pusher.wss_port, lives: 2 }], [":def", "sockjs_options", { hostUnencrypted: Pusher.sockjs_host + ":" + Pusher.sockjs_http_port, hostEncrypted: Pusher.sockjs_host + ":" + Pusher.sockjs_https_port }], [":def", "timeouts", { loop: true, timeout: 15000, timeoutLimit: 60000 }], [":def_transport", "ws", "ws", 3, ":ws_options"], [":def_transport", "sockjs", "sockjs", 1, ":sockjs_options"], [":def", "ws_loop", [":sequential", ":timeouts", ":ws"]], [":def", "sockjs_loop", [":sequential", ":timeouts", ":sockjs"]], [":def", "strategy", [":cached", 1800000, [":if", [":is_supported", ":ws"], [ ":best_connected_ever", ":ws_loop", [":delayed", 2000, [":sockjs_loop"]] ], [ ":sockjs_loop" ] ]] ] ]]
  • 55. METRICS
  • 56. WE COLLECT1.transport state changes2.browser name, features3.some strategy actions
  • 57. BETA DEPLOYMENTS1.deploy a new feature2.wait for enough data3.evaluate all metrics4.keep or revert changes
  • 58. THANKS! @pawel_ledwon

×