Building a Realtime WebSocket API with Phoenix

Building a Realtime WebSocket API with Phoenix

Sometimes consumers of your APIs require near-realtime communication because regular RESTful HTTP apis can be a few milliseconds too slow. These performant and scalable APIs can be made over websocket TCP connections where events are pushed from client and server in near-realtime fashion.

This talk is a story of how I built such an API. We'll look at why this decision to create a websocket API was made and we will take a look at the data that supported this decision. We will take a deep dive into Phoenix websockets, channels, and transports to expose the underlying architecture. Finally, we look at how we tested the API, how we authenticated users over the channels, and how Phoenix helped this all happen with relative ease.

94d3675b2e2431b326b0de7aff01b742?s=128

Jamie Wright

March 21, 2019
Tweet

Transcript

  1. Websocket API Beer City Code 2019 Building a real time

    ⋆ ⋆ in Phoenix
  2. @jwright

  3. jamie @brilliantfantastic.com

  4. @jwright http://speakerdeck.com/jwright

  5. Background Some

  6. Background Some

  7. Background Some http://chronic.io

  8. Background Some

  9. Background Some

  10. Background Some Server is gold copy Server pushes events to

    clients Clients displays event
  11. Background Some Server triggers push smart notifications

  12. Background Some Events at any second 

  13. Background Some Demo

  14. None
  15. Websockets

  16. Websocket What’s a

  17. Websocket What’s a Protocol

  18. Websocket Full-duplex connection Both sides can chat at same time

  19. Http Simplex connection One side can chat at a time

  20. Websocket What’s a https://tools.ietf.org/html/rfc6455 RFC

  21. Websocket What’s a https://www.w3.org/TR/websockets/ W3C Spec

  22. Websocket What’s a

  23. Websocket What’s a Starts with a Handshakes via HTTP

  24. None
  25. None
  26. TCP (C’est une pipe) HTTP W ebSocket

  27. Websockets Why we chose

  28. Realtime Websockets Why we chose

  29. Websockets Why we chose Eventful

  30. Phoenix Why

  31. Phoenix Why WebSockets

  32. Phoenix Why Elixir

  33. Phoenix Why Stateful

  34. Fast Phoenix Why

  35. Example APIs

  36. Example APIs https://api.slack.com/rtm Send messages in channel Receive team events

    Receive user presence
  37. Example APIs https://pusher.com/docs/pusher_protocol Receive system events Receive user presence Trigger

    client events
  38. Example APIs https://getstream.io/docs/#realtime Receive feed changes

  39. Works How it

  40. Connecting

  41. Connecting

  42. Connecting

  43. Connecting Give clients a starting point Identify events from a

    single endpoint (client) Opportunity to authenticate
  44. None
  45. Connecting

  46. Connecting

  47. Connecting

  48. Channels Joining

  49. Channels Joining Custom Protocol

  50. Channels Joining Multiplexed

  51. Channels Joining PubSub

  52. Channels Joining Built In

  53. Channels Joining

  54. Channels Joining

  55. Channels Joining

  56. Channels The Problem with

  57. Problems { topic: “events:1234”, event: “phx_join” } { topic: “events:1234”,

    event: “phx_reply”, payload: { ok: true, token: “1234” }}} WS WS WS WS Joining Channels
  58. Problems Joining Channels Remove complicated setup from clients Build reconnection/

    heartbeat logic https://bit.ly/2WjtKxZ
  59. Messages

  60. Messages Meat

  61. Messages Event name Event data

  62. Messages Incoming

  63. Messages Incoming

  64. Messages Incoming

  65. Messages Incoming

  66. Messages Incoming

  67. Messages Outgoing

  68. Messages Outgoing

  69. Messages Outgoing

  70. Outgoing

  71. None
  72. Review

  73. Review POST /graphql { url: “ws://…”, token: “1234” } HTTP

    HTTP HTTP HTTP Connecting { mutation: { connect: { … } }
  74. Review [“timers:start”, { duration: 1500, timestamp: 1273485 } ] [“timers:started”,

    { id: 1234, duration: 1500, remaining_time: 1500, status: “running” } ] WS WS WS WS Sending Messages
  75. Thank You!

  76. Questions?

  77. @jwright