Monday, March 31, 2014

Getting websocket-rails up and running on Heroku

I wanted to document my endeavors to get websocket-rails up and running on Heroku. In my case, I'll be adding Redis to the mix, as I'm trigger server-side events from a worker process that is running delayed_job tasks. Thus, in a multi-process environment, Redis has to be used to communicate from the worker process to the Rails process (which actually maintains the web socket infrastructure). My experiences with setting this all up were actually quite pleasant and things just worked without many issues. The documentation for websocket-rails could benefit from elaborating some non-development environment scenarios, but that's a very minor gripe.

Step 1: Get the solution running in development

Pretty straight-forward. You have to get everything working in your development environment. Nothing earth shattering here, but if you plan on triggering server-side events to your JavaScript clients from something like delayed_job, you will need to use Redis. I'm using OS X Mavericks here, so I install tools through Homebrew. Here's how I got Redis up and running in my environment:
  1. Install via Homebrew: brew install redis
  2. Start up Redis from the command line: redis-server /usr/local/etc/redis.conf
If you need to monitor Redis, use the redis-cli: redis-cli monitor Now that we have Redis up and running, get websocket-rails integrated into your application. I won't belabor how to do that--the documentation does a good job of detailing how. I use a channel to communicate from the client-side and the server-side. Another thing to note is that for anything I do on the client that I want an event for coming from the server, I use a correlation ID from the client-side that I can keep track of on the client-side, so when an event from the server-side is received, I can determine whether I'm interested in it because it contains the original correlation ID. Read more here about the correlation ID design pattern.

Step 2: Get the solution running on Heroku

Now that everything works in development, I needed to get the solution out to Heroku.
  1. If you previously installed SSL, you will have to disable it before enabling websockets support. Remove the certificates: heroku certs:remove, then remove SSL support through the Dashboard.
  2. Enable websockets support: heroku labs:enable websockets
  3. Add a Redis provider Heroku addon to the app if you haven't done that already. Note the Redis connection information.
  4. Update the websocket_rails.rb initializer with the Redis connection information. I had to add some conditional logic to determine which environment I was deployed in. Also import here is that host and port won't typically be enough to connect to a Redis add-on. You'll definitely need a password and probably a username. Those can be passed through the redis options in this initializer. Currently my websocket_rails initializer has some code in it like this:
    
        if ENV["RAILS_ENV"] == 'production'
            config.redis_options = {
                username: 'rediscloud',
                password: 'UHDDBHD&*#$DFkkdfha',
                host: 'pub-redis-88885.us-east-1-3.3.ec2.redisdomecity.com',
                port: '15204'
            }
        else
            config.redis_options = {
                host: 'localhost',
                port: '6379'
            }
        end
    
    
    This will invariably change so I can differentiate between staging and production, but you get the point.
Doing all this I was able to get the websocket-rails stuff to work and have not had any issues with it, even with dynes spinning up and down.

3 comments:

  1. Hey Chris - I'm trying to get websocket-rails up and running on Heroku and I'm having some trouble. Do you have standalone server mode enabled? Are you using unicorn or thin as your web process?

    ReplyDelete
  2. I'm using thin as the web process. I also run a worker process for Delayed Job. All of this is managed from the Procfile. Not sure what you mean in regards to standalone server mode enabled. Can you explain that?

    ReplyDelete
    Replies
    1. Sure - sorry I'm using unicorn as the server and it doesn't work out of the box with websocket-rails because it doesn't use EventMachine. In the latest version of websocket-rails there's a config option to run it as a standalone server, if you're not using thin. Heroku recommends using unicorn on their cedar stack which is probably why I'm having a problem. Thanks for replying

      Delete