rails + websocket


#1

最近想來玩玩看websocket
但是不太曉得這東西的前因後果
只知道他是一個能讓http的雙向溝通的協定

問題1:
為什麼websocket不能跟傳統http共用同一個server,而要自建一個新的呢?

ruby有em-websocket這個gem可以用 拿來架server
但是我找到的範例是用sinatra架的

問題2:
websocket server是如何跟rails/sinatra整合的呢?browser request被處理的流程又是什麼?websocket一定要搭配web server使用嗎?

以上 求解惑~


#2

hmm…我來完整點的回這篇

傳統 http vs websocket 可以用兩種模式來形容,http 很像是結帳人潮,你排隊然後結完帳就走,如果你要重複買東西,請重新排隊結帳一次,但 websocket 很像教室,需要準備一票課桌椅,老師上課時可以隨時提問,而打瞌睡的傢伙也會霸佔著課桌椅,直到自己醒來或是老師叫他

http 模式中,只需要準備一個櫃臺和一個排隊走道,店員只需要針對一個客人進行服務,然後就趕他走,很快很簡單,但是客人會很不爽,因為要繞很多次,而 websocket 模式中,需要準備很多教室來容納同學,甚至有分校的狀況,同學和同學間可以有互動,類似私下講話或是傳小抄,但這都要過老師那邊才能給另外一個傢伙,而老師如果有事情告訴大家,其實也是 1 : 1 的講,而不是表面中的 1 : N 廣播,這邊有個重點在於 websocket 因為連線不會中斷,所以 server 對 server 間的溝通很重要,類似某個同學寄信的校長室,校長要所有老師進行廣播告訴所有學生,或是某個同學想和全校同學說話,但每個班級都是一個 server 的狀況下,這些需求都要辦到才行

所以…這兩個模式有很大的差異就是了,至於有沒有做雙用的,當然有,很久以前我就把 em-websocket 增加了 http 支援,類似 long polling 且可以拿來送網頁,但是 em-websocket 作者不收…因為它叫做 “websocket” ((所以這是基本教義派的政治問題X"D

而 Rails 5.0 因為有 ActionCable (透過 Redis 的 pub/sub 來對 server to server 溝通) 所以才支援廣播,否則做出 websocket 是不堪用的,而一般的 nginx / apache 因為任務導向,基本上應該都只丟 proxy 功能出來(轉導 websocket 封包到別的 server / port),剩下的都要開發者自己實現,所以沒必要也沒義務支援 websocket 才是(因為留住 connection 耗能很高的啊…)

然而後來有很多 gem,支援這件事情了( http + websocket ),類似我之前有說的 https://github.com/boazsegev/plezi 就是雙用的 gem 還可以依附在 Rails / Sinatra 之內

最後, websocket 一定要配 http server ? 這是一定的,因為 websocket 只是一個連線機制,而這個連線機制目前無法拿來送初始化的 html,所以勢必還是要配一個 http server 才行

另外附註一點,websocket 是 TCP 的 socket 協定擴充版,而多人同畫面的線上遊戲基本上是 UDP 的 socket,實作上有一點點的差別,不過基本上是相同的意思就是了

okay 大概是這樣子,還有問題可以再提出,以上


#3

感謝解惑!
回答中有幾點不太明白:

這邊是指:websocket server一次只能處理一個connection,所以如果要對N個client做推播(用法不確定)就要做N次嗎?

假設我做了一個通訊app,有100個user(1~100),2台server(A/B),A server處理user 1~50的web socket,B server處理user 61~100的socket,若user 1要傳訊息給user 100的話,則流程應該如下?:
(a) server A 處理 user 1 socket
(b) server A 將user 1的訊息與 server B 同步
© server B 處理 user 100 socket

以上~


#4
  1. 是,所謂的廣播其實歸到最後就是一個一個慢慢發,和 RDB 所謂的多對多關連其實是多個一對多,而單一條拉出來看其實是一對一一樣,最多有些類似 fork 的機制會快點而已,併行發送相同訊息不用另外處理,但是通常還是需要個別處理傳送內容,類似加上使用者 id 之類

  2. 類似,通常會取 master / slave(雙層,master負責處理,slave負責後送和廣播) 或是 P2P 機制,這兩個機制我之前都做過,類似 slave 收到訊息都直接丟給 master , master 處理完丟給 slave,slave 廣播出去,或是 P2P 的一台就處理完,然後就每台都發,或是學 Redis 的 pub/sub 去訂閱 channel,聽該 channel 的都收得到,而也可以針對 channel 進行發送(其實就是 Redis 擔任不處理的 master 角色 )


#6

感謝回覆,想再進一步詢問:
1.這邊列出剛剛有被提出的pattern:

  • master/slave
  • P2P
  • pub/sub
    這三個東西都是communication pattern嗎?概念上是屬於同層級的東西嗎?只能擇一使用還是可以混用?

2.websocket是雙向溝通的protocol,所以只要是牽涉大量往返傳送資料的應用類型,就非得使用websocket嗎?剛剛回覆中好像有提到他的缺點之一是高耗能

3.共筆(hackpad/google drive)也是用websocket實作嗎?


#7
  1. 單純的網路拓樸而已,Server 玩多一點就會知道,類似 MySQL / Oracle 之類的 RDBMS 是 master / slave, Mongo / HBase 是 P2P,而 pub / sub 只是機制而已,應該隸屬於 master / slave,去找網路拓樸會有一大票就是,基本上要看設計和規模,除非規模太大否則會擇一而不會混用

  2. 高耗能是對 server 而言,但這世界一直都是有一好沒兩好,所以 websocket 不用每個封包都送 header / cookie …之類的東西,所以省流量,且 client 端反而比較輕鬆些,缺點示弱化的話會變成類似 long polling 甚至是 comet

  3. 用啥做都可以,給你三個關鍵字, comet / long polling / websocket,其實可以做到非常類似的作品就是了,其餘的都和實作有關,事實上我之前做的就是 long polling + websocket,目前公司第一個作品是 comet,因為IE9不支援 websocket 的啊…而 long polling / comet 則是連 IE6 都吃


#8

相當清楚~感謝回答