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:
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:
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.
Finally make sure that you place the Redis instances in our Redis security group so that it is accessible from our Web Server instances.
The last thing we need to do is add the two environment variables (REDIS_URL
and CABLE_CHANNEL_PREFIX
) to our Elastic Beanstalk settings.
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