A tale of friendly competition and Server-Sent Events

Me

Espen Hovlandsdal

Developer at VG

I believe in Javascript

espen.codes

Background

 is a broadcaster

Traditionally, journalists ➜ users

"Push" makes more sense than "poll"

More and more "realtime" services

 is a broadcaster

Use case is usually very similar:

Broadcast some arbitrary data

The tale begins...

Websockets is starting to sound like a good idea

Spend 10% of time
on a prototype

"Websockets are awesome, but does it scale?"

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

http.listen(3000, function() {
    console.log('listening on *:3000');
});

setInterval(function() {
    io.emit('ping', { timestamp: Date.now() });
}, 5000);

Server

// On VG.no:

var chance = 50;
if ((Math.random() * 100) < chance) {
    var script = d.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.src = '<url-to-client-script>.js';
}

Client

Result? Not encouraging

  • Latency spikes
  • High CPU usage
  • Hard to debug
  • Server "crashed"
  • Monster server,
    ~60k connection cap?

Some time later...

Let's investigate

WSS: Not HTTP

handshake resembles HTTP

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

Full-duplex

On top of TCP
Port 80/443

6 different protocols

RFC since
Dec 2011

Proxies and firewalls still cause issues

Server-Sent Events?

One-way - 
Server ➜ Client

Extremely simple,
HTTP-based

GET /chat HTTP/1.1
Host: server.example.com
Accept: text/event-stream


HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Type: text/event-stream
Cache-Control: no-cache

id: 123
data: some arbitrary data

id: 124
data: {"we could also":"push json"}

Additional features

  • "Events since ID" (dropped clients)
  • Named events
  • Configurable reconnect timeout

Time passes

Confidence grows

"I can do this"

Node.js
SSE
Simple!

Result?

Go
would
scale
better

Erlang was
built for
this task

Did you
try this in
Python? 

Do you even
Nimrod,
bro?

C++,
aight?

Fine.

Do your worst!

(I'll go heal my wounded pride)

Results!

Node.js

  • Spiky response times
  • Bit of GC every now and then
  • High CPU usage

Go

  • Consumed less CPU than node
  • Hit the roof at about ~30% more clients than node

Ruby (EventMachine)

  • Similar to node, but with less CPU usage
  • Very quick connects
  • Fairly high memory usage

Erlang

  • Very unfamiliar
  • Response times very varying
  • "Cheated" the system slightly

Clojure (http-kit)

  • Nice, predictable performance
  • Fairly stable response times
  • Delivery time a bit varied
  • High memory consumption

Python (Twisted)

  • Comparable to Node.js and Ruby
  • CPU usage a bit higher than the others

BUT THEN

C

  • Epoll, pthread, ~350 LOC
  • Could not give it enough work
  • Peaked at ~200k
  • Mostly rock solid response times
  • Very low memory usage

Written by...
a sysop

My hero:
Ole Fredrik Skudsvik

Since then:

  • C++

  • Nim

  • php-react

Scalability vs maintainability

  • C

  • C++

  • Clojure

Microservice!

Lessons learned

“If you only have a hammer, you tend to see every problem as a nail.”

- Abraham Maslow

You can learn a lot during two weeks of intense hacking

Benchmarking stuff is not easy

Friendly competition can be helpful, educational and
a lot of fun

We want to share

SSE Hub is open-source

RabbitMQ

C/C++

 

+ ecosystem

Thx.

Credits

Lego man by Okan Benn

Cowboy hat by Paul Stevens

Horse by Gilad Fried

Salesman by John Salzarulo

Lazy by Aaron Tregent

Whining + sick day by Clara Joy

Muscle by Jurjen Versteeg

Hourglass by Sma-rtez

Hammer by John Caserta

Graphics licensed under CC BY 3.0 US:

Mortar Board by Ian Graham

Snake tornado kindly borrowed from Natalie Dee

A tale of friendly competition and Server-Sent Events

By Espen Hovlandsdal

A tale of friendly competition and Server-Sent Events

  • 1,529