Scaling Rails App

Scaling Rails App

No prior understanding of scaling

No assumption regarding libraries

No assumption regarding system architecture

Scalability is the capability of a system, network, or process to handle a growing amount of work, or its potential to be enlarged to accommodate that growth.

Horizontal: adding more machines

Vertical: adding more resource in a machine

Simple application

Upgrade to better library

Change SQLite to better database

Change your app server

Don't Do
Webrick Puma
Mongrel Unicorn
Passenger
Thin

Consider: daemonize your app server, adjust workers configuration, integrate into deploy script. Also event based, process based or thread based.

Use Webserver

Why we need extra layer?

- SSL

- App server doesn't handle static files well

- App server is designed for low latency client

- App server is IO blocking

- Web server manage expires header, gzip compression for static files, redirection, and many more

- HTTP/1.1 keep-alive is not available in app server

- Using only app server will make it harder if we want to scale to multiple machine

- HTTP2

Webservers

Webservers

  • HttpPlatformHandler (IIS)
  • mod_proxy (Apache / lighthttpd)
  • proxy_pass (Nginx)
  • Passenger + nginx / apache module
  • Please do not use fcgi anymore

Make application work across multiple machine

Static Files Service for assets

config.asset_host = "https://someserver.example.com"

Static files server
(Nginx, Apache, etc)

AWS S3

Azure Blob Storage

Google Cloud Storage

Swift

(Openstack Storage)

Consider:

  • Implement "strong caching header".
    Cache-Control is preferable over Expires.

  • Implement "weak caching header" i.e. Last-Modified or ETag

  • Implement gzip and add Content-Encoding="gzip" header

  • Restrict access by checking http referer

  • Adjust your deploy script (asset_sync)

  • CORS problem.

What about user uploaded content?

  • Paperclip, Carrierwave, and Refile has plugins/extensions for major storage service provider

  • Use networked file system such as nfs or smb

  • Use sftp or ftp (shudder)

  • Extend those gems. We are engineers.

  • We can use the same asset host or use different server

Why don't we move database to special server so it can be used by many rails application?

config/database.yml

Self hosted database

AWS RDS

AWS

Dynamodb

Google
Cloud SQL

Google
Cloud Datastore

Azure Cosmos DB

Azure SQL

Consider:

  • Replication - Copying an entire table or database onto multiple servers.

  • Partitioning - Splitting up a large monolithic database into multiple smaller databases based on data cohesion.

  • Clustering - Using multiple application servers to access the same database. Used for computation intensive, parallelized, analytical applications that work on non volatile data.

  • Sharding - Splitting up a large table of data horizontally i.e. row-wise.

  • Update your deployment script

  • Replication is great for high availability

  • Secure your database so it's not available from the big bad world. Use db tunnel.

Now we can tell web server to connect to multiple rails instance

How?

Load Balancer

  • Nginx has built in support
  • Apache also has built in support using mod_proxy_balancer
  • IIS?
  • Standalone load balancer such as HAProxy
  • Hardware load balancer?

What's Next?

Cache

Doesn't make sense if each rails instance implement it's own  data cache

config.cache_store = :memory_store, { size: 64.megabytes }
config.cache_store = :file_store, "/cache/directory"
config.cache_store = :mem_cache_store, "cache.example.com"
config.cache_store = :redis_store, 'redis://1.2.3.4:6379/0/cache'

Roll your own

memcached server
redis server

distributed

replicated

networked file system

AWS ElastiCache

Azure

Cache Store

Redis Cloud
Mem Cloud

Better. Now implement workers

www.

example.com

assets.

example.com

Workers

Next, Add CDN

  • Different domains. Browser limit connections to single domain
  • Distributed globally
  • High capacity
  • High speed
  • Caching
  • Header control
  • Analytics
  • Whole sites or just assets
  1. Setup CDN
  2. Set CDN origin to our site / assets site
  3. CDN will give you end point
  4. Optional, set CNAME or alias your domain to CDN
  5. Set your application to use CDN endpoint

 

set CNAME cdn.example.com to cdn.cdnprovider.net

config.asset_host = "https://cdn.example.com"

Build yourself

www.

example.com

assets.

example.com

cdn.

example.com

I want to add...
Scaling Principles

  1. Separate
  2. Scale individual service horizontally or vertically
  3. Load balance or connect to other

TODO for your consideration:

  • Configuration and or Orchestration tools. Chef. Puppet. Salt. Ansible. Terraform. Cloudformation.
  • Logging. Collecting Log. Transporting Log. Storing Log. Parsing. Analysis.
    Use ELK (Elasticsearch, Logstash, Kibana) or Graylog.
  • Monitoring. Zabbix, Monit, God, Nagios, Cacti, Newrelic, Cloudwatch. 
  • Budget planning.
    Use tools from cloud providers, prices as advertised, estimate and extrapolate from usage data.
  • Security. Protect public access to data storage and services.

Scaling Rails App

Questions?

Scaling Rails App

By Karuna Murti

Scaling Rails App

Scaling Rails Application

  • 1,714