WebSocket For Web Rubyists

60
WebSocket for Web Rubyists @ryudoawaru at OEDO’05

Transcript of WebSocket For Web Rubyists

WebSocket for Web Rubyists@ryudoawaru at OEDO’05

はじめに発表する機会をいただき ありがとうございます

提 供提 供

五倍紅寶石五倍紅寶石

自己紹介鄧 慕凡(テン ムファン)

a.k.a: 竜堂 終

両方どもある小説の登場人物

Github / Twitter: @ryudoawaru

http://ryudo.tw

台湾人であり

ルビーストRubeastであり

Rubyの肩書

RubyConf Taiwan執行委員長

Rails Girls Taipei主催人

仕事は

五倍の紅宝石http://5xruby.tw/en

無限虫制師Unlimited Bug WorksGenerator

弊社の業務

Ruby / Rails の 教育業者

コンサルタンシー / オフショア海外の取引先は日本、シンガポールなどを持ちます

Rubyの広めるRailsGirls / RubyConf…etc

RWC初めの海外スポンサーになりました

ここから、英語で話す

Agenda

Introduce WebSocket / EM-Websocket.

Architectural Perception for Web Rubyists.

WebSocketRFC 6455

Websocket

W3C / HTML5 Standard

Standard Javascript API

Full-duplex

Pub-Sub between client and server

Search in rubygems.org

Gem Category

EventMachine-Websocket

Faye-Websokcet

EM-Websocket

EM-Websocket

From 2009

Simple implementation

Easily handle c10k by 1 process

http://shokai.org/blog/archives/7149

Typical Server Side Code

EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws| ws.onopen { ws.send "Hello Client!"} ws.onmessage { |msg| ws.send "Pong: #{msg}" } ws.onclose { puts "WebSocket closed" } end

Typical Client Side Code

var ws = new WebSocket('ws://host/uri'); ws.onopen = function() { show('websocket opened'); }; ws.onclose = function() { show('websocket closed'); } ws.onmessage = function(m) { show('websocket message: ' + m.data); }; ws.send('Hello Websocket!!');

How does it workClient Server

Handshake Response

Websocket

Handshake Request

GET /chat HTTP 1.1 Host: server.host.com Upgrade: Websocket Connection: Upgrade Origin: http://host.com Sec-Websocket-Key: “WwV7thr/Uwrg3mA57risrQ==" Sec-WebSocket-Version:"13"

Connection:”Upgrade" Sec-WebSocket-Accept: F0VaFFGV/JHx1hJWBlhuJAqdse8= Upgrade:"websocket"

Events

onopen:When new connection is established

onmessage:When new message comes from another side

onclose:When connection is closed by the other side

Methods of Handshake Object

send:Send message to client or server side.

close:Close connection.

Message Flow

Server

Client

Client

Client

1. send msg

2. onmessage

3. Send to all clients

4. onmessage

Basic EM-WebSocket Code Style

conns_in_channel = Set.new EM::WebSocket.start(...) do |ws| ws.onopen do |request| conns_in_channel.add ws end ws.onmessage do |msg| conns_in_channel.each do |conn| EM.next_tick{conn.send(msg)} end end ws.onclose do conns_in_channel.delete ws end end

Store connection

Remove connection on quit

Set to store connection

Send msg to connections 1 by 1

WebSocket Protocol is Simple.

But it’s never easy to make a great product.

Architectural Issue

Application Stack Style

Authentication

Application Stack StyleStandalone or in App?

Two Styles

Standalone

In-App

Standalone

Web Service Stack

WebSocket Service Stack

Normal HTTP Request

WS Request

In App Style

Web Service Logic

Normal HTTP Logic

Normal HTTP Request

WS Request

Live with HTTP Service in the Rack Stack

request.websocket?

Rack Stack

WebSocketOther Rack Stuffs

YES NO

Identify by Request Headers

# middlewares/chat_backend.rb def call(env) if Faye::WebSocket.websocket?(env) # WebSockets logic goes here ws.rack_response else @app.call(env) end end

https://devcenter.heroku.com/articles/ruby-websockets

Identify by Request Headers

# config/routes.rb Example::Application.routes.draw do match "/websocket", :to => ActionCable.server, via: [:get, :post] end

https://github.com/rails/actioncable

Standalone or In App?

Normal Web Services

Keeps Connection for very short period.

Process could be terminated w/o affecting any client.

Client Server

open

close

open

close

WebSocket Service

Long-running Connection

Stop process means killing all connections.

Server

Client

Client

Client

Concurrency Model

WebSocket Gems use one of following concurrency models:

Reactor: EventMachine based Gems.

Thread: Tubesock.

Mixed: ActionCable

This may conflicts with model of your normal Web Services.

Comparison of Connection Features

Normal Web Works WebSocket

Connection Period short long

Concurrency Model Depend on App Server Reactor or Thread

Process Long-Running? No Yes

AuthenticateConfirm identity in handshake

Authentication Issue

Client Server

Handshake Request

Handshake Response

Websocket

Confirm at this point!

Possible Methods to Confirm Identity

Cookie

Headers

URL / Query Parameters

Identify by Cookie

Easy approach for web developers.

WebSocket may run at different host.

Some browsers don’t support cookie on ws:// request.

Most mobile APP’s http client may not support cookie/session by default.

Identify by Request Headers

Unable to add custom header in the JavaScript WebSockets API.

Identify by URL

Client

⓵GET http://host/chat

WebSocketWeb Service

⓷Use ticket to handshake

⓸Identity confirmed

⓶Generate URL: ws://host2/abc1234 as “ticket”

Attention

Security issue:

The “ticket" should be removed from database after connection established.

Should only be valid in a short time.

Showcase

Chatroom for ForumiOS APPWEB

http://www.focus-sport.club.tw/

Serve all platforms by one stack.

Runs Permanently.

Handle more than 1k concurrent connections very easily.

ご清聴ありがとうございました

Any Question?