Let me preface this blog by stating that I am not a Drupal admin. However, I see Drupal enough to make me want to dive into it's architecture and understand how different components may help or hurt performance at high load, which got me to the question of "how do I actually load test Drupal".
In this post I want to cover how we can use a sitemap to run JMeter Load Tests against Drupal. This should lay the groundwork for being able to accurately understand how different architectural changes impact your site's performance.
The Why
Drupal is a popular CMS, but for better or worse Drupal is sometimes a mystery in terms of how it executes and performs. Cloud engineers and architects want to make sure their architectures are optimized and scaled to handle load, but usually there is no way to validate whether their design changes will truly improve their site before releasing it publicly. However, this isn't optimal since by then it's too late should we realize that our changes still don't improve performance at high-load times. On the flip side, we may realize that we are over-spending on resources to scale out for a load we may simply never receive. Ultimately, we would like a way to run experiments and understand our changes before we promote these changes to production.
The How
Prerequisite - Docker to Run Drupal
Before diving into the load test, I need a Drupal site that I can work with. I've decided to run this locally with the following Docker Compose file. You do not need to run your Drupal site as I do with containers, this is just the way I decided to get started quickly. I also use the demo unami site to create content when I navigate to the UI of the site and run the initial install:
version: '2'
services:
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: drupaldb
volumes:
- 'mysql_data:/var/lib/mysql'
drupal:
image: drupal:10
ports:
- '80:80'
depends_on:
- mysql
volumes:
mysql_data:
driver: local
Question: What Paths Exist in the Site
It would be ideal that we load test the site by hitting all the unique paths exposed. How do we find this list of paths exposed in the site? One way may be to leverage a sitemap - this should document all the paths of our site.
Now, how do we generate a sitemap? After a random search of Drupal modules, the following simple sitemap module looks promising. We expect that this module will produce a sitemap.xml file that includes all the paths within our site. Let's test that hypothesis.
First, install the module with composer. I had to exec into the container to run this command:
Next, enable the module in the admin UI and configure the following settings:
You should then see the sitemap when navigating to the sitemap.xml path:
Next Question: How Can We Run a Load Test Using the Sitemap Paths
An open-source tool that is used for load testing is Apache JMeter. This tool is also the backbone for the Azure Load Testing Service. The key to answering this question boils down to "How do I make a JMeter script that crawls the sitemap and then iterates over each url?".
This is a handy link I found to get an example JMeter script that already has a sitemap crawler developed. This builds a test that will iterate through each link in the sitemap. A few updates were made to the script included below (take note that you need to update the variable values before running the test):
When we run it locally with JMeter, it looks like it's working well!
Final Step: How do I Run The Test in Azure Load Testing
Now that you have the JMeter script and have executed it locally, you can upload it to Azure Load Testing to run a test from the cloud. The benefits include using more execution engines for increased load and also capturing nice results and metrics alonside your Drupal deployment.
First, create an Azure Load Testing resource and then create a new test by uploading a JMeter script:
Continue through the test creation, adding what is necessary. From there you should see the test begin execution.
Summary
This hopefully helps to get a testing framework setup for your Drupal site that you can then use to evaluate different changes. Another use for this script is to pre-warm any caches you may have - you could run this with a single thread and hit all pages on your site.