Comparing Rate limiting solutions for a Rails App

In the ‘scary free internet’ we can have DoS attacks or simply a client who has an error using your APi sending thousands of requests in a minute. This could have bad effects in your application performance.

To avoid these effects we can implement this example in our web app: Every IP cannot make more than 10 requests per minute, from that limit we should reject the requests

gem ratelimit

Seems more oriented to count everything in the app:

  • Manually you create a Redis database when Rails starts:
@ip_ratelimit = Ratelimit.new("request_ip_limit_db")
  • You can check in order to send a Forbidden message:
@ip_ratelimit.exec_within_threshold request.remote_ip, threshold: 10, interval: 60 do
  render json: 'IP request limit overhead.', status: 403
end
  • Wherever you want in the controllers you can increment the counter:
@ip_ratelimit.add(request.remote_ip)

Features:

  • Based on local Redis database
  • You can count whatever target (not only IPs)
  • Implementation:
    • Make an initializer to setup Redis database
    • Make a filter in Application controller to increment IP counter

gem rack-throttle

Seems the easier, cleaner and faster ruby based solution for our example.

  • Configured at config/application.rb:
require 'rack/throttle'
require 'memcached'
class Application < Rails::Application
  config.middleware.use Rack::Throttle::Minute,   max: 10, cache: Memcached.new, key_prefix: :throttle
end

Features:

  • Memcached based (which makes it faster). You can user Redis also.
  • Only counts remote_host accesses (identified by default by Rack::Request#ip).
  • Strategies can be customized.
  • Cleaner in code because this represents a “Rack Layer”, not a “Controller Filter” which spread more the code all over our App.

Nginx ngx_http_limit_req_module

This is a fully implementation of the Leaky Bucket algorithm :

limit_req_zone $binary_remote_addr zone=one:10m rate=10r/m;
server {
    location / {
        limit_req zone=one burst=5;
    }

How it runs:

  • Reserving a 10Mbytes of shared memory
  • Limiting 10 request per minute
  • When it is overloaded (burst) 5 requests are delayed to the next minute.
  • When rate+burst is over, request is terminated with an error 503 (Service Temporarily Unavailable)

Other solutions

gem rack-attack:

  • Rack level solution
  • Implements Blacklists and Whitelists

Improve your Ruby code quality with metrics

In the ruby world we have several tools to analyse our ruby (and Rails) code. In this article we will see the most used (and useful for me), and how to integrate into our CI process with Jenkins.

These gems are:

In your Gemfile you should include all gems:

 # Metrics
 gem 'simplecov', require: false
 gem 'simplecov-rcov', require: false
 gem 'rubocop', require: false
 gem 'rails_best_practices', require: false
 gem 'metric_fu', require: false

Simplecov needs some configuration at the beginning of your ‘spec_helper.rb’ to generate the coverage files:

require 'simplecov'
require 'simplecov-rcov'
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
SimpleCov.start 'rails'

That’s all done in your Rails project. Now you need to install two plugins in your Jenkins server:

Finally I have configured my metrics build as:

build-configuration

 

 

Boostrap AngularJS project with Yeoman

First take a look to this post making a basic NodeJS installation on Ubuntu. You will need npm and bower installed.

Installing Yeoman

Install all tools needed:

npm install -g grunt grunt-cli yo generator-karma generator-angular

Create Angular project

cd myapp
yo angular myapp
gem install compass
bower install grunt-svgmin grunt-contrib-jshint -S
grunt serve

WebStorm

Download it from Jetbrains-Webstorm site.

tar xvf WebStorm-9.0.3.tar.gz