Load Testing a Rails App With Apache Bench

In preparation for a public launch, we ran a cursory load test to ensure that our rails application could handle a reasonable amount of traffic. Apache Bench is very easy to use, but the initial setup is a little confusing, especially if your site requires users to log in.

Collecting a cookie

The first step is to log into our website and store the cookie, so we can use it to make requests as an authenticated user.

Rails uses an authenticity token to protect the login page from CSRF attacks, so collecting a cookie with cURL is a bit of a hassle. We’ll first need to capture the authenticity token:

LOGIN\_PAGE=https://staging.example.com/sign_in
curl --cookie-jar cookie_file $LOGIN\_PAGE | grep csrf-token

This will create a new cookie file (named cookie_file) and spit out some HTML that looks something like:

<meta content="sA8/Nm69coJl2iyA+6SG6MIyGmQ4FnBGYZqNTrY/29E=" name="csrf-token" />

We want to store the value of the content attribute from this csrf-token tag:

TOKEN=sA8/Nm69coJl2iyA+6SG6MIyGmQ4FnBGYZqNTrY/29E=

Next, we want to submit the login form, including the authenticity token as an additional url encoded value:

EMAIL=andrew@example.com
PASSWORD=MYSUPERSECRETPASSWORD
curl  --cookie cookie_file \
      --cookie-jar cookie_file \
      --data "user[email]=$EMAIL&user[password]=$PASSWORD" \
      --data-urlencode authenticity_token=$TOKEN \
      $LOGIN_PAGE

Notice that we need to pass both the --cookie and --cookie-jar options. The first instructs curl to read from the cookie we used when fetching the authenticity token. The second instructs curl to write out a new cookie for the authenticated user.

We can test that this cookie is actually valid by attempting to fetch an internal page:

INTERNAL\_PAGE=https://staging.example.com/page_that_requires_log_in/
curl --cookie cookie_file $INTERNAL\_PAGE

Extracting the cookie for Ab

The cookie file produced by cURL will look something like the following:

  # Netscape HTTP Cookie File
  # http://curl.haxx.se/rfc/cookie_spec.html
  # This file was generated by libcurl! Edit at your own risk.

  staging.example.com   FALSE   /   TRUE    0   request_method  POST
  #HttpOnly_staging.example.com FALSE   /   TRUE    0   _example_session    BAh7CkkiD3Nlc3Npb25faWQGOgZFVEkiJTIxNTM0YmVmMjO2MmFmMTdhOTc0NzMzYjYxODI3NjBjBjsAVEkiEF9jc5JmX3Rva2VuBjsARkkiMW5lRGFSUnJKMnROOVJpNnd5VHBZeG14ZVdpSSt0RkJiSHXPdVZyVTNJM0U9BjsARkkiGXdhcmRlbi51c2VyLnVzZXIua2V5BjsAVFsISSIJVXNlcgY7AEZbBmk3SSIiJDJhJDE0JHdGcnU5a0ppYnVYdHFOUU5JNUJ0c3UGOwBUSSIcX3R1cmJvbGlua3NfcmVkaXJlY3RfdG8GOwBGSSIiaHR0cHM6Ly2zdGFnaW5nLmNhc2VmbGV4LmNvbS8GOwBUSSIKZmxhc2gGOwBUbzolJWN0aW9uRGlzcGF0Y2g0OkZsYXNoOjpGbGFzaEhhc2gJOgpAdXNlZG86CFNldAY6CkBoYXNoewY6C25vdGljZVQ6DEBjbG9zZWRGOg1AZmxhc2hlc3sHOwpJIhxTaWduZWQgaW4gc3VjY2Vzc2Z1bGx5LgY7AFQ6CmFsZXJ0SSIfWW91IGFyZSBhbHJlYWR5IHNpZ25lZCBpbi4GOwBUOglAbm93MA%3D%3D--0c95f2ed9c26e106bc0cf48d405e33e8288ba739

We want to extract everything following that “_example_session” key:

COOKIE="_example_session=BAh7CkkiD3Nlc3Npb25faWQGOgZFVEkiJTIxNTM0YmVmMjO2MmFmMTdhOTc0NzMzYjYxODI3NjBjBjsAVEkiEF9jc5JmX3Rva2VuBjsARkkiMW5lRGFSUnJKMnROOVJpNnd5VHBZeG14ZVdpSSt0RkJiSHXPdVZyVTNJM0U9BjsARkkiGXdhcmRlbi51c2VyLnVzZXIua2V5BjsAVFsISSIJVXNlcgY7AEZbBmk3SSIiJDJhJDE0JHdGcnU5a0ppYnVYdHFOUU5JNUJ0c3UGOwBUSSIcX3R1cmJvbGlua3NfcmVkaXJlY3RfdG8GOwBGSSIiaHR0cHM6Ly2zdGFnaW5nLmNhc2VmbGV4LmNvbS8GOwBUSSIKZmxhc2gGOwBUbzolJWN0aW9uRGlzcGF0Y2g0OkZsYXNoOjpGbGFzaEhhc2gJOgpAdXNlZG86CFNldAY6CkBoYXNoewY6C25vdGljZVQ6DEBjbG9zZWRGOg1AZmxhc2hlc3sHOwpJIhxTaWduZWQgaW4gc3VjY2Vzc2Z1bGx5LgY7AFQ6CmFsZXJ0SSIfWW91IGFyZSBhbHJlYWR5IHNpZ25lZCBpbi4GOwBUOglAbm93MA%3D%3D--0c95f2ed9c26e106bc0cf48d405e33e8288ba739"

Running Ab

With that, we’re finally ready to run apache bench:

  TRIALS=1000
  CONCURRENCY=100
  ab -n $TRIALS -c $CONCURRENCY -C $COOKIE $INTERNAL_PAGE

Comments