Web sites not working in my Rails application when I start a Unicorn server but running on a thin server

I am learning Ruby on Rails to create a real-time web application using WebSockets on Heroku, but I cannot understand why the connection to the web server fails when running on a Unicorn server. I have a Rails application configured to work on Unicorn both locally and on Heroku using Procfile ...

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

... which I start locally with $foreman start . The error occurs when creating a connection to the web server on the client in javascript ...

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

... with the following error in the Chrome Javascript console, '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.

... and when I run it in Unicorn on Heroku, I get a similar error in the Chrome Javascript console, '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.

The stack trace in Heroku logs says: RuntimeError (eventmachine not initialized: evma_install_oneshot_timer):

Which is strange that it works fine when I run it locally on a thin server using the $rails s command.

I spent the last five hours researching this problem on the Internet and did not find a solution. We will be very grateful for any ideas to fix this, or even the idea of ​​getting more information from my tools!

+6
source share
1 answer

UPDATE: It was strange to me that websocket-rails only supports EventMachine-based web servers, and the faye-websocket on which websocket-rails are based supports many multithreading web servers .

After further research and testing, I realized that my previous assumption was wrong. Instead of requiring an EventMachine-based web server, websocket-rails seems to require a multi-threaded (so there is no Unicorn) web server that supports rack.hijack . ( Puma meets these criteria, being comparable in performance to the Unicorn.)

Under this assumption, I tried to solve the EventMachine not initialized error using the most direct method, namely, initializing the EventMachine by inserting the following code into the config/initializers/eventmachine.rb :

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

and .... success!

I managed to get Websocket Rails to work on my local server through a single port using a non- EventMachine-server without an offline server . (Rails 4.1.6 on Ruby 2.1.3p242)

This should be applicable to Heroku if you have no restrictions on choosing a web server.

A WARNING. This is not an officially supported configuration for websocket-rails. Care must be taken when using multi-threaded web servers such as Puma, as your code and its dependencies must be thread safe. A (temporary?) Workaround is to limit the maximum flows per worker to one and increase the number of workers, reaching a system like Unicorn.


Out of curiosity, I tried Unicorn again after fixing the above problem:

  • The first connection to the web server was received by the web server ( Started GET "/websocket" for ... ), but the state the websocket client was stuck on connecting , it seems to hang indefinitely.

  • The second connection resulted in an HTTP 500 app error: deadlock; recursive locking (ThreadError) with app error: deadlock; recursive locking (ThreadError) app error: deadlock; recursive locking (ThreadError) displayed in the server console output.

As a result of the (potentially dangerous) Rack::Lock removal action, a blocking error can be resolved, but the connections still freeze, although the server console indicates that the connections were accepted.

No wonder this fails. From the error message, I think Unicorn is incompatible due to reasons related to its network architecture (threading / concurrency). But then again, it might be some kind of mistake in this rack middleware ...

Does anyone know the specific technical reasons why Unicorn is incompatible?


ORIGINAL RESPONSE:

Have you checked the ports for both the web server and the WebSocket server and debug logs? These error messages sound as if they are connecting to something other than the WebSocket server.

A key difference in the two web servers you use seems to be that one (thin) is EventMachine and one (Unicorn) not. The Websocket Rails wiki indicates that one internal port (provided as an environment variable) is externally as port 80. A WebSocket server usually requires its own socket address (port number) (which can be processed by reverse proxying the WebSocket server). Websocket-Rails seems to manage this limitation by connecting to an existing EventMachine- based web server (which Unicorn does not provide) rack capture .

+23
source

Source: https://habr.com/ru/post/974794/


All Articles