Passenger + nginx + faye-websockect not stored clients in array

83 views
Skip to first unread message

Julian Botia

unread,
Jul 1, 2016, 12:19:41 PM7/1/16
to Phusion Passenger Discussions
 

I have a ruby on rails app. I added support for websockets with faye/websocket, for this target I read some tutorials how:

  1. http://joelandritsch.com/posts/adding-websocket-support-to-rails-using-faye-websocket-4

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

When I deploy code in production with passenger + nginx in aws @clients not store the new connections. in local environment work fine

my code is:

# app\middleware\track_backend.rb

require 'faye/websocket'

  class TrackBackend
    KEEPALIVE_TIME = 15 # in seconds
    CHANNEL        = "chat-demo"

    def initialize(app)
      Rails.logger.info "initialize"
      p 'inicio'
      @app     = app
      @clients = []
    end

    def call(env)
      if Faye::WebSocket.websocket?(env)
        ws = Faye::WebSocket.new(env, nil, {ping: KEEPALIVE_TIME })
        ws.on :open do |event|
          Rails.logger.info "onopen"
          p [:open, ws.object_id]
          Rails.logger.info "clients b: #{@clients.length}"
          @clients << ws
          Rails.logger.info "clients a: #{@clients.length}"
        end

        ws.on :message do |event|
          p [:message, event.data]
          #user = User.new
          #user.name = event.data
          #user.save
          Rails.logger.info "new message :)"
          Rails.logger.info "clients: #{@clients.length}"
          Rails.logger.info "#{event.data}"
          @clients.each {|client| client.send(event.data) }
        end

        ws.on :close do |event|
          p [:close, ws.object_id, event.code, event.reason]
          @clients.delete(ws)
          ws = nil
        end

        ws.on :error do |event|
                print event
        end

        # Return async Rack response
        ws.rack_response

      else
        @app.call(env)
      end
    end
  end

# config\application.rb

require File.expand_path('../boot', __FILE__)

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module TrackingPilot
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
    # config.time_zone = 'Central Time (US & Canada)'

    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    # config.i18n.default_locale = :de

    # Do not swallow errors in after_commit/after_rollback callbacks.
    config.active_record.raise_in_transactional_callbacks = true
    config.middleware.use "TrackBackend"
  end
end

/etc/nginx/nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
        ##
        # Phusion Passenger config
        ##
        # Uncomment it if you installed passenger or passenger-enterprise
        ##

        include /etc/nginx/passenger.conf;

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

/etc/nginx/sites-enabled/tracking.conf

server {
    listen 80;
    server_name public_ip;

    # Tell Nginx and Passenger where your app's 'public' directory is
    root /var/www/tracking/code/public;

    # Turn on Passenger
    passenger_enabled on;
    passenger_ruby /usr/local/rvm/gems/ruby-2.3.0/wrappers/ruby;

    location /websocket {
       passenger_app_group_name tracking_pilot_websocket;
       passenger_force_max_concurrent_requests_per_process 0;
   }
}

Phusion Passenger 5.0.29

nginx version: nginx/1.10.1

Thanks and I wait a clue to solve this problem

Daniel Knoppel

unread,
Jul 6, 2016, 6:17:58 AM7/6/16
to Phusion Passenger Discussions
So what does your rails logging say? And did you check the Passenger log too?

- Daniel

Julian Botia

unread,
Jul 25, 2016, 11:19:51 PM7/25/16
to Phusion Passenger Discussions
sorry for answering so late

For the test I made two requests and then stopped the server

Here is the log attached level 7 output for the 2 request. I replaced the URL to example.org.

first request

App 7936 stdout: [:open, 22409900]
App 7936 stdout: "clients before: 0"
App 7936 stdout: "clients after: 1"

second request

App 7948 stdout: [:open, 22409640]
App 7948 stdout: "clients before: 0"
App 7948 stdout: "clients after: 1"
error.log

Daniel Knoppel

unread,
Aug 17, 2016, 4:41:32 AM8/17/16
to Phusion Passenger Discussions
So you expected clients before: 0 to go 0 --> 1 --> 2?

Did you see that the count output is from 2 different application processes, and that the second one (7948) is started only after the first one already counted?

I can imagine two problems here:
1) The app doesn't work with more than 1 process because it doesn't synchronize with other processes (e.g. through a database)
2) The app does synchronize, but it only works for processes that are already active

The solution would be to implement working synchronization. Alternatively the workaround for 1) would be to limit the passenger pool size to 1, and for 2) the workaround could be to set min_instances equal to pool size and warmup the server with a prestart url.

- Daniel
Reply all
Reply to author
Forward
0 new messages