Load test Drupal and CiviCRM with LoadImpact

Published
2015-06-10 03:28
Written by

This has been my approach (together with CiviCoop) to load test a big site with CiviCRM where most visitors where expected to login.
Let me know if you would agree with this approach or if you have a better alternative.

Every big drupal site needs load testing before going live.

These are the key questions you should have answered in the final stages before deployment:

  • How does your infrastructure handle the expected amount of visitors?
  • how does it perform with maximum amount of visitors?
  • and at what amount of visitors does it start to crumble?

For anonymous load testing there are a number of tools available.
For logged in users there are not so many available.

But what about the sites where logging in is secured using unique tokens per user visit like drupal?

How do you load test those?

The problem is that you often can record or script what you need to post during login.

But sites like drupal secure their login pages with an unique token so you do not know what you will need to post beforehand.

With LoadImpact.com that problem is solvable.

LoadImpact automates load testing and gives graphs like:

Example of LoadImpact graphs

To setup a load test on Load Impact for logged in users you can do:

Step 1: Record one or more user scenario's with the Load Impact chrome plugin: https://chrome.google.com/webstore/detail/load-impact-user-scenario/comn...

Step 2: Export user scenario to Load Impact.

Step 3: Look into the generated LUA code and find the GET request to the login page.

Step 4: Change it so the form token is gathered and placed in a variable:

For example:

http.page_start("Page 1")
local pages = http.request_batch({
    {"GET", "https://www.domain.com/user", response_body_bytes=10240}
})

local body = pages[1]['body']
local token = string.match(body, 'input type="hidden" name="form_build_id" value="(.-)"')

Step 5: find the POST request to the drupal login page and change the "form_build_id" with the token value.

if token ~= nil then
http.request_batch({
    {"POST", "https://www.domain.com/user", headers={["Content-Type"]="application/x-www-form-urlencoded"}, data="form_build_id=" .. token .. "&form_id=user_login&name=<username>op=Log%20in&pass=<password>", auto_decompress=true}
})
else
  log.error("failed to find token" .. body .. "");
end

And you're done. Now load tests can be performed with thousands of concurrent logged in users on your drupal site.

If your user scenario contains other form submissions you can repeat this for the other forms as well.

Using CiviCRM as an example: someting similar is needed if CiviCRM searches are performed.

CiviCRM adds a session dependent qfKey to every search. Without the right qfKey a search will not be executed properly, harming the load test.

To solve this you have to execute the following steps in the Load Impact user scenario.

Step 1: Find the GET page for the search and place the qfKey in a variable

local pages = http.request_batch({
    {"GET", "https://www.domain.com/civicrm/contact/search?reset=1", response_body_bytes=102400}
})

local body = pages[1]['body']
local token = string.match(body, 'input type="hidden" name="qfKey" value="(.-)"')

Step 2: find the POST request to the search page and replace the qfKey with the token

if token ~= nil then
http.page_start("Page 5")
http.request_batch({
    {"POST", "https://www.domain.com/civicrm/contact/search", headers={["Content-Type"]="application/x-www-form-urlencoded"}, data="_qf_Basic_refresh=Search&_qf_default=Basic%3Arefresh&contact_type=&entryURL=https%3A%2F%2Fwww.domain.com%2Fcivicrm%2Fcontact%2Fsearch%3Freset%3D1&group=&qfKey=" .. token .. "&sort_name=&tag=", auto_decompress=true}
})

http.page_end("Page 5")
else
  log.error("failed to find token" .. body .. "");
end

And you can also do proper CiviCRM searches in your Load Impact user scenario and load test your Drupal+CiviCRM site before deployment.

Originally posted on http://orgis.com/en/blog/web/professional-load-testing-drupal-and-civicrm-loadimpact

 

Filed under

Comments

I've done similar tests before using LoadStorm, it has the advantage that you don't need to script your tests, you just tell it to go to this page, fill these values into these fields, etc. via a GUI.  It works quite well.

It's also useful in your load testing to randomly clear all caches during the test and see if that causes things to explode.

So LoadStorm can pick up hidden variables in a form and use those in posts and gets for following pages all via GUI?

If so, nice!

With LoadImpact you do not need to script the tests either, they are recorded and created automatically. But you can change the recorded scripts when needed.