javascript - rails - websocket heroku node js



當我在Unicorn服務器上運行時,Websockets在我的Rails應用程序中不起作用,但在瘦服務器上運行 (1)

我正在學習Ruby on Rails,在Heroku上構建一個帶有WebSockets的實時Web應用程序,但我無法弄清楚為什麼在Unicorn服務器上運行websocket連接失敗。 我有我的Rails應用程序配置為使用Procfile在本地和Heroku上獨角獸運行...

web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb

...我從$foreman start當地$foreman start 。 在javascript中的客戶端上創建websocket連接時發生故障...

var dispatcher = new WebSocketRails('0.0.0.0:3000/websocket'); //I update the URL before pushing to Heroku

...在Chrome Javascript控制台中出現以下錯誤'websocket connection to ws://0.0.0.0:3000/websocket' failed. Connection closed before receiving a handshake response. 'websocket connection to ws://0.0.0.0:3000/websocket' failed. Connection closed before receiving a handshake response.

...當我在Heroku上的Unicorn上運行它時,我在Chrome Javascript控制台中遇到了類似的錯誤'websocket connection to ws://myapp.herokuapp.com/websocket' failed. Error during websocket handshake. Unexpected response code: 500. 'websocket connection to ws://myapp.herokuapp.com/websocket' failed. Error during websocket handshake. Unexpected response code: 500.

Heroku日誌中的堆棧跟踪顯示, RuntimeError (eventmachine not initialized: evma_install_oneshot_timer):

奇怪的是,當我使用命令$rails s在瘦服務器上本地運行它時,它工作正常。

我花了最近五個小時在網上研究這個問題,並沒有找到解決方案。 任何想法來解決這個問題,甚至想法從我的工具獲得更多的信息,將不勝感激!


更新:我覺得很奇怪, websocket-rails只支持基於EventMachine的web服務器,而websocket-rails基於的faye-websocket支持很多支持多線程的web服務器

經過進一步調查和測試,我意識到我以前的假設是錯誤的。 websocket-rails似乎不需要一個基於EventMachine的web服務器,而是需要一個支持rack.hijack支持多線程的(不支持Unicorn的 )web服務器。 ( 彪馬符合這個標準,而在性能上可以與獨角獸 相媲美 。)

有了這個假設,我嘗試使用最直接的方法解決EventMachine not initialized錯誤,即初始化EventMachine,方法是在初始化程序config/initializers/eventmachine.rb插入以下代碼:

Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive?

和.... 成功!

我已經能夠通過單個端口使用基於 EventMachine的服務器 而不使用 獨立服務器模式來使WebSocket Rails在本地服務器上工作。 (關於ruby 2.1.3p242的Rails 4.1.6)

只要您對Web服務器選擇沒有限制,這應該適用於Heroku。

警告:這不是官方支持的websocket-rails配置。 使用多線程Web服務器(如Puma)時必須小心,因為您的代碼及其依賴關係必須是線程安全的。 一個(臨時的) 解決方法是將每個worker的最大線程數限制為1,並增加worker的數量,實現類似於Unicorn的系統。

出於好奇,我在修復上面的問題後再次嘗試了獨角獸

  • 第一個websocket連接被web服務器接收( Started GET "/websocket" for ... ),但websocket客戶端的state被卡在connecting ,似乎無限期掛起。

  • 第二個連接導致HTTP錯誤代碼500以及app error: deadlock; recursive locking (ThreadError) app error: deadlock; recursive locking (ThreadError)顯示在服務器控制台輸出中。

通過刪除Rack::Lock (潛在危險)的操作,可以解決死鎖錯誤,但連接仍然掛起,即使服務器控制台顯示連接已被接受。

毫不奇怪,這失敗了。 從錯誤信息,我認為由於與其網絡體系結構(線程/並發)有關的原因, Unicorn是不兼容的。 但是,再次,這可能只是在這個特定的Rack中間件的一些錯誤...

有誰知道為什麼獨角獸不兼容的具體技術原因?

原文答案:

你有沒有檢查Web服務器和WebSocket服務器及其調試日誌的端口? 這些錯誤消息聽起來像是連接到WebSocket服務器以外的東西。

您使用的兩個Web服務器的一個關鍵區別似乎是一個( Thin )基於EventMachine,一個( Unicorn )不是。 Websocket Rails項目wiki指出, 獨立服務器模式必須用於基於非EventMachine的Web服務器,如Unicorn(因為它需要Redis服務器,所以需要在Heroku上進行更複雜的設置)。 錯誤消息RuntimeError (EventMachine not initialized: evma_install_oneshot_timer):建議不使用獨立模式

Heroku AFAIK只將外部端口 (作為環境變量提供)作為端口80公開。WebSocket服務器通常需要自己的套接字地址(端口號)(可以通過反向代理WebSocket服務器來解決)。 Websocket-Rails通過掛接到現有的基於EventMachine的Web服務器(Unicorn不提供) 劫持Rack來解決這個限制。





websocket