read

Action Cable debuted at RailsConf 2015 and is now part of Rails 5. Built on top of WebSockets it provides real time communication with your backend server.

Part 1 of the videos is here:

And Part 2 here:

I’ve created a very simple Rails5 chat application that you can download from here.

You can run this locally using the following command:

rails s

Open a couple of browser windows and you should be able to talk to yourself…

As this is a new application we need to initialise Elastic Beanstalk and select the environment that we configures in the previous steps.

eb init

Before deploying we need to make some tweaks to our environment. Currently our load Balancer is setup to use HTTP and HTTPS - it won’t currently understand the Web Socket protocol.

We need to change this so that it uses raw TCP and SSL:

Add domains names to your certificate

The next thing we need to do is modify the configuration of the nginx instance that is sitting in front of our Rails application on the Elastic Beanstalk instances.

If we were manually configuring a server we’d simply SSH onto our machine and edit the nginx config files. This doesn’t work for PAAS type deployments where the machines you are running on are ephemeral.

To configure our nginx server we need to add a new folder to the root of our project .ebextensions and add a config file nginx.config.

files:
  /etc/nginx/conf.d/proxy.conf:
    content: |
      client_max_body_size 500M;
      server_names_hash_bucket_size 128;

      upstream backend {
        server unix:///var/run/puma/my_app.sock;
      }

      server {
        listen 80;

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

        server_name *.cmgresearch.net;

        large_client_header_buffers 8 32k;

        location / {
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_set_header X-NginX-Proxy true;

          proxy_buffers 8 32k;
          proxy_buffer_size 64k;

          proxy_pass http://backend;
          proxy_redirect off;

          location /assets {
            root /var/app/current/public;
          }

          # enables WS support
          location /cable {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade "websocket";
            proxy_set_header Connection "Upgrade";
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          }
        }
      }


container_commands:
  01restart_nginx:
    command: "service nginx restart"

This config file will create a new file on our Elastic Beanstalk instances called /etc/nginx/conf.d/proxy.conf and will then restart the nginx server so that it picks up the new config file.

The important part this new file is:

# enables WS support
location /cable {
  proxy_pass http://backend;
  proxy_http_version 1.1;
  proxy_set_header Upgrade "websocket";
  proxy_set_header Connection "Upgrade";
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Using PostgreSQL

Initially we setup ActionCable to use PostgreSQL as it’s back end by setting up the

Switch back to redis by editing config/cable.yml as follows:

production:
  adapter: postgresql

This will use our existing DATABASE_URL to connect to Postgres and then use Postgres’ built in NOTIFY and LISTEN commands

Make sure all our changes are committed and deploy the application:

git add .
git commit -m "Chat app with postgres"
eb deploy --profile demo

And you should have a chat application running on your instance.

If you hit any issues with the websocket not connecting then you can use:

eb logs

to view the logs from your server - this should flag up any errors with the ActionCable system.

Using Redis

Now we know that our chat application is working in Elastic Beanstalk we can switch over to using Redis. Lets change our cable.yml file so in production it uses Redic:

production:
  adapter: redis
  url: <%= ENV['REDIS_URL'] %>  
  channel_prefix: <%= ENV['CABLE_CHANNEL_PREFIX'] %>

We now need to do some work in our VPC to create a new security group for our Redis instances and set it up so that our web server security group can access the Redis port:

Redis Security Group

Now navigate to the ElastiCache dashboard and we can create a new Redis instance. Make sure you expand out the Advanced settings and create a new Private Subnet group with the private subnets from your VPC. This is where our convention for our subnet CIDR blocks really helps as Amazon doesn’t show us any of our names.

Create private subnet

Finally make sure that you place the Redis instances in our Redis security group so that it is accessible from our Web Server instances.

Redis Security Group

The last thing we need to do is add the two environment variables (REDIS_URL and CABLE_CHANNEL_PREFIX) to our Elastic Beanstalk settings.

Set CABLE_CHANNEL_PREFIX Set REDIS_URL

Once that cofiguration has completed we can deploy and test our application again:

git add .
git commit -m "Switch to Redis"
eb deploy --profile demo

All being well our chat application should still work, but now it will be using Redis as the ActionCable back end instead of PostgreSQL.

Once again, if you have issues then run check the logs as it normally tells you exactly what has gone wrong:

eb logs

Why not subscribe to my mailing list - I'll send out regular emails with new content (don't worry I won't spam you!)

* indicates required
Blog Logo

Chris Greening


Published

Image

Chris Greening

Blogging about random stuff

Back to Overview