Pub / Sub in Ruby

22
Publish / Subscribe in Ruby Adrien Siami - Dimelo @Intrepidd

description

Slides of my paris.rb talk about pub/sub in ruby

Transcript of Pub / Sub in Ruby

Page 1: Pub / Sub in Ruby

Publish / Subscribe in RubyAdrien Siami - Dimelo

@Intrepidd

Page 2: Pub / Sub in Ruby

What’s Pub / Sub ?

• Bidirectional communication between server and clients

• Clients subscribe to channels

• Server or client pushes events to some channels

• Clients are notified in realtime!

Page 3: Pub / Sub in Ruby

Use case

• Private messaging

• Broadcasting

• Server-sent events

Page 4: Pub / Sub in Ruby

Possible Solutions (in ruby)

• Pusher

• PubNub

• Faye

Page 5: Pub / Sub in Ruby

Pusher

Pros• SaaS

• Batteries Included (Auth, Presence)

Cons • SaaS

Page 6: Pub / Sub in Ruby

PubNubPros

• SaaS

• Batteries Included (Auth, Presence)

Cons• SaaS

• One event = one channel

Page 7: Pub / Sub in Ruby

FayePros

• Built with ! (And Javascript)

• Open Source and self hosted

• Extensible

• Server level hooks

• Globbing (/users/*)

• Great Maintainer (@jcoglan)

Cons

• Les batteries included

Page 8: Pub / Sub in Ruby
Page 9: Pub / Sub in Ruby

Benchmarks

Websocket Json-p Cors Failure rate

Faye 84.68% 5.46% 9.81% 0.62%

Pusher 88.4% 6,67% 4,94% 3.7%

Page 10: Pub / Sub in Ruby

Faye Overview - Javascript

var client = new Faye.Client('http://foo.bar/faye'); !client.subscribe('/user/123', function(message) { console.log(message.content); }); !client.publish('/user/999', {content: 'Hey dude wassup?'});

Page 11: Pub / Sub in Ruby

Faye Overview - Rubyrequire 'faye' require 'eventmachine' !EM.run { ! client = Faye::Client.new('http://foo.bar/faye') ! client.subscribe('/user/123') do |message| puts message.content end ! client.publish('/user/999', {content: 'Hey dude wassup?'}) }

Page 12: Pub / Sub in Ruby

Faye Hosting

• It’s a Rack system ! I Know this.

• EventMachine, one thread, tons of connections

• In-Memory by default

• Faye engines, e.g faye-redis, for multiple process architecture

Page 13: Pub / Sub in Ruby

Benchmarks

Server Without redis!(1 worker)!

With redis!(1 worker)

with redis !(4 workers)

Passenger + nginx 43 sec 1m 25 sec 53 sec

Node! 1m 18 sec 1m 42 sec

Thin 38 sec 1m 28 sec

Puma 30 sec 1m 28 sec 43 sec

• Connect 10k clients • Subscribe • send some messages • disconnect

Page 14: Pub / Sub in Ruby

Gotchas

• Tune your file descriptors

• Use EM.epoll

• PhusionPassenger.advertised_concurrency_level = 0

• passenger_max_requests 0;

Page 15: Pub / Sub in Ruby

DIY !

• Authentication

• Presence

Page 16: Pub / Sub in Ruby

Faye Authentication

• JWT based signature, generated by the Rails Server when allowed

• Inserted into the faye request through a plugin executing an Ajax Call

• Check at the faye server level

dimelo/faye-authentication

Page 17: Pub / Sub in Ruby

Faye AuthenticationIn a controller app (route /faye/auth):

def auth if can?(:read, params[:message].try(:channel)) render :json => {signature: Faye::Authentication.sign(params[:message], 'faye secret')} else render :text => "Forbidden", :status => '403' end

In your JS :

client.addExtension(new FayeAuthentication(client));

Page 18: Pub / Sub in Ruby

Faye AuthenticationOn the faye server (config.ru):

server = Faye::RackAdapter.new mount: '/faye' server.add_extension Faye::Authentication::ServerExtension.new('faye secret') run server

Page 19: Pub / Sub in Ruby

Faye Presence

• Keep track of several clients per user

• Notify connection / disconnection

• Keep infos about the session (away / available)

Page 20: Pub / Sub in Ruby

Faye Presence

{ "event": "user-disconnected", "user": { "id": 42, "infos" : { "status": "away" } } }

Page 21: Pub / Sub in Ruby

Thank you.

Page 22: Pub / Sub in Ruby

Dimelo contest!• Submit a pull request on a 20+ stars ruby Github repository • Have it merged • Have a chance to win a Xbox One or a PS4 • http://contest.dimelo.com • http://jobs.dimelo.com