1 of 38

Slide Notes

Hey everybody. It seems like folks are just about finished trickling in, so we're going to go ahead and get started.

WebSockets from the Wire Up

Published on Nov 23, 2015

No Description

PRESENTATION OUTLINE

WebSockets from the Wire Up

Christine Spang
Hey everybody. It seems like folks are just about finished trickling in, so we're going to go ahead and get started.

Hi!

My name is Christine Spang, and I was MIT class of 2010. While I was an undergrad here in course 6, I was a member of the SIPB, so thanks to them, and especially to Chelsea Voss, for bringing me back here to give a talk for the SIPB IAP talks series.

----

Hi! I'm Christine. I've been hacking on open source software since I got into Debian in high school. Later I went to MIT and got a degree in computer science and was a systems engineer at a tiny company called Ksplice, which developed hotpatching technology for the Linux kernel.

Untitled Slide

I work at a company that I cofounded in 2013 in San Francisco, and we're building a platform that makes it easy for developers to build applications that use data from email, contacts, and calendars. Feel free to ask me more about the company after the talk.

This talk

  • What are websockets?
  • Examples (w/Python!)
  • Performance & use in production

What are WebSockets?

Now that we've gotten the introductions out of the way, let's dive into WebSockets.

I'm first going to give you some of the history of protocols powering web applications, the shortcomings they had, and how web developers attempted to address those shortcomings.

Along the way, I'll show you how WebSockets took a concept that's been around as long as servers have been around and adapted it for the web to enable new kinds of web applications to be built.
Photo by Jake Mates

Untitled Slide

To answer this question, we need to talk about a bit of history first.

Internet history, that is. Or more specifically, the history of the world wide web, or web for short.

So, websockets are a protocol that can be used to power certain types of web applications. But most of the web is currently powered by a protocol called HTTP, or hypertext transfer protocol. How many people here have heard of HTTP? How many people here know how it works?
Photo by Thomas Hawk

Untitled Slide

Here's a quick little diagram showing HTTP in action.

So, you have web servers which actually host static pages and code that make up a web application, and then you have web browsers, which are clients which talk to the web server using HTTP and retrieve content to show browser users.

A typical HTTP request consists of a verb, in this case "GET", followed by an argument, in this case "/", which just means the top-level page or application.

To respond to a browser's request, the server sends some data over the wire, which includes a status code, in this case "200 OK", which in HTTP means success, and the HTML, CSS, and Javascript that the browser should render and display to the user.

This protocol and process worked really well for a long time. The web was originally created by Tim Berners Lee for sharing academic documents, which were mostly static. But as time went on, people wanted to create actual software programs where most of the work was done on the web server, and the browser acts as a thin client, retrieving new data and rendering it to the user.

(There are number of reasons to want this, such as not having to distribute new updates to the application to user's computers.)

With this simple HTTP model, you *can* create interactive applications... the main wrench is that every time some interaction happens---say, a user clicks on a link or a button, or the app wants to refresh the page to update the information being displayed, it has to initiate an entirely new HTTP connection to the server, send its request, and receive a response. And it turns out that because of the way HTTP works, every one of those requests, even if the browser just needs the answer to a tiny question, has to send quite a lot of data over the wire---HTTP requests are, on average, about 800 bytes.

Untitled Slide

Here's an example of a simple HTTP request that retrieves the top-level page at www.inboxapp.com.

And you can see that even for such a simple request, it's pretty verbose. Much more complex requests can contain things like cookies, which inflate the size of the request even more.

Untitled Slide

So we create webapps using plain old HTTP, but once you start trying to do things that are much more interactive, you start running into the problem that this model is very slow.

We could refresh the page every time we wanted to let users interact with a site, but it takes a long time to send requests back and forth to the server. Even in the best case scenario, we're limited by the speed of light. Light itself takes around 40ms to travel between Boston and San Francisco. And that's just for the bits to travel in a best-case scenario. More typically you're looking at around 80ms latency coast-to-coast, plus the time to transfer any data, which includes HTTP headers, and to bootstrap the TCP connection itself.
Photo by 55Laney69

Untitled Slide

So developers tried to work around these problems in a number of different ways. And one of the first ways was this method that ended up being called AJAX, short for asynchronous javascript.

Basically, you have a piece of JavaScript in your webapp, and you wired that piece of javascript up to a button that you want to talk to the server, and the javascript can asynchronously send a request to the server, get the response, and then potentially update a subset of the current page with new data.

So this allows us to update pages without completely refreshing them, but it still has to create another HTTP connection (including opening a new TCP connection) to the server every time it wants to send data back and forth.

Clients could use AJAX to poll a web server for updates to a page as well, basically making a new connection at some interval to ask for updates.
Photo by Mike Johnston

Untitled Slide

This was an improvement on having to send a new HTTP GET or POST request every time, but it didn't fundamentally change the model of how web applications operated.

One problem was that, if computation was happening on the server, and the client wanted to keep updated about the server's current state, it basically had to poll, or keeping check in, with the server at some interval, and create a new connection every time.

So we haven't talked about this up until this point, but another limitation upon webapps compared to, say, a desktop application, up to this point, is that the communication between the client and the server is fundamentally unidirectional.
Photo by Matt Peoples

Untitled Slide

And web developers figured out a way to mostly get around this as well, and came up with a model that's called "comet", or sometimes, "long-polling", which involves keeping a long-lived HTTP connection open until a timeout expires or the server has some data to return to the client. The client then opens another HTTP connection to the server and continues to wait for data.

This actually worked pretty well,
but the one case in which it still degraded was that though not if the application needed to pass messages back and forth at a high interval.

"Historically, creating web applications that need bidirectional
communication between a client and a server (e.g., instant messaging
and gaming applications) has required an abuse of HTTP to poll the server for updates while sending upstream notifications as distinct
HTTP calls [RFC6202]."

This is actually a quote from the WebSockets RFC:

https://tools.ietf.org/html/rfc6455

It's referring to a technique known as "long polling".
Photo by 55Laney69

Untitled Slide

In order to be able to implement proper real-time applications, apps that were sending small messages back and forth between client and server often, we really needed a protocol that allowed bidirectional communication between client and server with low-latency.

That's where websockets come in.
Photo by Joao Schmidt

Untitled Slide

Let's talk about what the websocket protocol actually is now, so we can better understand how they evolve how webapps can work, and allow for different kinds of apps to exist on the web.

In order to do so, we need to briefly look at another piece of computing history, or what the word "socket" actually means in a computing context anyway.

In the 1970s when UNIX was developed at Bell Labs, part of the operating system API that Brian Kernighan, Dennis Ritchie, Ken Thompson, etc. created contained an API they called a socket. I don't know why they called it that, but they did.

UNIX domain sockets were used for local inter-process communication (IPC), on a single server. You'd make a call to the socket() syscall with the AF_UNIX domain and then you'd get a [file] descriptor you could use to communicate between processes. This socket was a bidirectional link between two different programs, which could use it to send messages back and forth.

If you use the socket() syscall on Linux, you can also use it to create a socket that goes across the network---so your program on a local computer can open up a socket to a game server, for example, and the game server can send the program updates and vice-versa.

Socket API

socket()
send()
recv()

The Linux socket() API is really super simple. Three syscalls: socket(), which creates the socket descriptor, and then send() and receive() to pass messages back and forth.

Untitled Slide

I bring all of this up because it turns out you can think of websockets as basically UNIX sockets for web applications.

The WebSockets protocol and API were introduced as a part of the HTML 5 specification, but were eventually split out in order to keep HTML 5 simpler.

WebSockets

  • Compatible with existing web infrastructure
  • Able to traverse proxies and firewalls
  • Low overhead: bidirectional, no HTTP header/msg
  • Minimizes new TCP connection creation
  • Makes "realtime" webapps possible at scale
https://www.websocket.org/aboutwebsocket.html

Before websockets, there were some ways to open up socket connections in web applications, but there was no standard API for it. You had to use a non-standard browser extension like Flash to do it. The websockets spec made the idea of using sockets for web applications standard, and also dealt with problems unique to web applications trying to use sockets, like dealing firewalls and proxies.

Makes "real-time" possible on the web
(games, stock-tickers, chat, etc.)

Basically anything live-updating at a high frequency.

Untitled Slide

Let's take a look at a quick websocket example.

Bring up the Python client/server example in a split window and explain the code.

Show the tcpdump invocation used to generate a packet dump.

wireshark websocket_simple.dump and use "http or websocket" to filter the packet output, since websockets are layered on top of tcp, but we don't really care that much about the tcp packet output.

Untitled Slide

Here's a basic diagram showing how the connection bootstrap process works.

Once a connection is bootstrapped, either side can send a message to the other without creating a new connection.

Switching Protocols

WebSockets use HTTP code 101 in order to be able to initiate websockets connections over HTTP, which also allows apps to transparently fall back to other mechanisms if the client or server don't support websockets. More on that later.
Photo by modernowl

Untitled Slide

Now that we've seen a super simple example of WebSockets in action, let's take a look at something a bit more real world.

One sort of webapp that websockets make possible are games.

A few years ago, to demonstrate the new websockets support in Firefox, Mozilla created an open source game called BrowserQuest. Let's take a look at how this game works to get a better feel for what's happening behind the scenes with websockets.

(pull up the game and show what's going on in the chrome developer console)

Untitled Slide

We're going to walk through an example of using nginx to proxy websockets, using BrowserQuest, an open source game produced by Mozilla as an example of the power of websockets.

netstat

Show that when running a websockets program, you're only opening sockets on port 80.

Performance

Show padding on each HTTP request for long polling or AJAX vs padding for sending messages back and forth via WebSockets.

Average HTTP header size: 800 bytes.

Overhead per WS frame: 2-14 bytes.

1,000 clients polling every 1s for 20b response:
6.6 Mbps network throughput

1,000 WS clients sending 20b messages:
0.2 Mbps network throughput

Most benefit from using WS is for apps which send small messages frequently.

No TCP connection bootstrap per message
+
low overhead
=
low latency

Backwards Compatibility

Of course, even if you want to use websockets for a new app, you have to keep in mind backwards compatibility for clients.

Your users don't care about WebSockets.

Use a polyfill library to fall back to comet / long-polling techniques. They implement cross-browser support so you don't have to.

I'd recommend going with SocketIO, generally. It's supported my Automattic (the company behind Wordpress), and very active.

You can use it as just a wrapper around websockets, but it also provides many more features, including broadcasting to multiple sockets, storing data associated with each client, and asynchronous I/O.

(Remember, WebSockets are just a socket API that's compatible with the API---they don't give you a lot of features out of the box. Just like there are libraries implemented on top of UNIX sockets (zeromq, for example), there are libraries on top of WebSockets.)

In Python, you can use the library "Flask-SocketIO" to create websockets apps with polyfill support using Flask.

Untitled Slide

http://caniuse.com/#feat=websockets

About 80% of browsers in use today support websockets. Your customers don't care if you're using websockets. They want your app to //work//.

Use a polyfill library.
(Probably SocketIO.)

Use a polyfill library to fall back to comet / long-polling techniques. They implement cross-browser support so you don't have to.

I'd recommend going with SocketIO, generally. It's supported my Automattic (the company behind Wordpress), and very active.

You can use it as just a wrapper around websockets, but it also provides many more features, including broadcasting to multiple sockets, storing data associated with each client, and asynchronous I/O.

(Remember, WebSockets are just a socket API that's compatible with the API---they don't give you a lot of features out of the box. Just like there are libraries implemented on top of UNIX sockets (zeromq, for example), there are libraries on top of WebSockets.)

Untitled Slide

If you're running a websockets app in production, you'll probably want to proxy them through a real web server like nginx or Apache to give you more flexibility in deployment, and for things like really solid TLS connection termination. nginx has supported websockets proxying since version 1.3.13, so as long as you have that version you should be all set.

You can also use Apache with the `mod_proxy_wstunnel` extension. (I haven't used this myself.)

You can also use HAproxy or Varnish but (maybe?) not for SSL connections. I don't have experience with this either. Really depends on the setup you're looking for.

Summing Up

WebSockets are a new protocol which provide low-latency network sockets that are compatible with existing internet infrastructure. They're super useful for writing real-time webapps, like chat and games.

You can use a polyfill library for backwards compatibility to techniques with better browser support, like xhr-longpolling, and it's recommended to proxy your websocket server behind a web server in production.

The Python ecosystem is pretty complex. I recommend using Flask-SocketIO.
Photo by eriwst

WebSockets...

  • Are a socket API built for web compat
  • Enable scaleable real-time webapps
  • Are supported only on recent browsers
  • Can achieve backcompat with a polyfill library (for Python, Flask-SocketIO)
WebSockets are a new protocol which provide low-latency network sockets that are compatible with existing internet infrastructure. They're super useful for writing real-time webapps, like chat and games.

You can use a polyfill library for backwards compatibility to techniques with better browser support, like xhr-longpolling, and it's recommended to proxy your websocket server behind a web server in production.

The Python ecosystem is pretty complex. I recommend using Flask-SocketIO.
Photo by eriwst

learn more!

That's all I have for the material in this talk. There's a lot more to learn about websockets if you're interested. I have all of my talk materials online on GitHub, feel free to take of the examples and play around with them and extend them. The websockets RFC (RFC6455) is actually pretty good, especially the introduction-check it out!

Questions?

Does anyone have any questions?

Come work with me. :)


spang@nylas.com

And just a quick obligatory note here at the end: if you're a hacker interested in stuff like this, you should come with me! We don't have a lot of spaces for interns this summer, but I definitely want to talk to anyone who's highly enthusiastic and wants to dive into a fast-paced startup in San Francisco.

If you're not a student, we're hiring full-time engineers as fast as we can. Come join me!