Tutorial: Run a load test to identify performance bottlenecks in a web app
In this tutorial, you'll learn how to identify performance bottlenecks in a web application by using Azure Load Testing. You'll create a load test for a sample Node.js application.
The sample application consists of a Node.js web API, which interacts with a NoSQL database. You'll deploy the web API to Azure App Service web apps and use Azure Cosmos DB as the database.
Learn more about the key concepts for Azure Load Testing.
In this tutorial, you'll learn how to:
- Deploy the sample app.
- Create and run a load test.
- Identify performance bottlenecks in the app.
- Remove a bottleneck.
- Rerun the load test to check performance improvements.
- An Azure account with an active subscription. If you don't have an Azure subscription, create a free account before you begin.
- Azure CLI version 2.2.0 or later. Run
az --versionto find the version that's installed on your computer. If you need to install or upgrade the Azure CLI, see How to install the Azure CLI.
- Visual Studio Code. If you don't have it, download and install it.
- Git. If you don't have it, download and install it.
Deploy the sample app
Before you can load test the sample app, you have to get it deployed and running. Use Azure CLI commands, Git commands, and PowerShell commands to make that happen.
Open Windows PowerShell, sign in to Azure, and set the subscription:
az login az account set --subscription <your-Azure-Subscription-ID>
Clone the sample application's source repo:
git clone https://github.com/Azure-Samples/nodejs-appsvc-cosmosdb-bottleneck.git
The sample application is a Node.js app that consists of an Azure App Service web component and an Azure Cosmos DB database. The repo includes a PowerShell script that deploys the sample app to your Azure subscription. It also has an Apache JMeter script that you'll use in later steps.
Go to the Node.js app's directory and deploy the sample app by using this PowerShell script:
cd nodejs-appsvc-cosmosdb-bottleneck .\deploymentscript.ps1
At the prompt, provide:
- Your Azure subscription ID.
- A unique name for your web app.
- A location. By default, the location is
eastus. You can get region codes by running the Get-AzLocation command.
For your web app's name, use only lowercase letters and numbers. Don't use spaces or special characters.
After deployment finishes, go to the running sample application by opening
https://<yourappname>.azurewebsites.netin a browser window.
To see the application's components, sign in to the Azure portal and go to the resource group that you created.
Now that you have the application deployed and running, you can run your first load test against it.
Configure and create the load test
In this section, you'll create a load test by using a sample Apache JMeter test script.
The sample application's source repo includes an Apache JMeter script named SampleApp.jmx. This script makes three API calls to the web app on each test iteration:
add: Carries out a data insert operation on Azure Cosmos DB for the number of visitors on the web app.
get: Carries out a GET operation from Azure Cosmos DB to retrieve the count.
lasttimestamp: Updates the time stamp since the last user went to the website.
The sample Apache JMeter script requires two plugins:
Custom Thread Groups and
Throughput Shaping Timer. To open the script on your local Apache JMeter instance, you need to install both plugins. You can use the Apache JMeter Plugins Manager to do this.
Create the Azure Load Testing resource
The Load Testing resource is a top-level resource for your load-testing activities. This resource provides a centralized place to view and manage load tests, test results, and related artifacts.
If you already have a Load Testing resource, skip this section and continue to Create a load test.
If you don't yet have a Load Testing resource, create one now:
Sign in to the Azure portal by using the credentials for your Azure subscription.
Select the menu button in the upper-left corner of the portal, and then select + Create a resource.
Use the search bar to find Azure Load Testing.
Select Azure Load Testing.
On the Azure Load Testing pane, select Create.
Provide the following information to configure your new Azure Load Testing resource:
Field Description Subscription Select the Azure subscription that you want to use for this Azure Load Testing resource. Resource group Select an existing resource group. Or select Create new, and then enter a unique name for the new resource group. Name Enter a unique name to identify your Azure Load Testing resource.
The name can't contain special characters, such as \/"":|<>+=;,?*@&, or whitespace. The name can't begin with an underscore (_), and it can't end with a period (.) or a dash (-). The length must be 1 to 64 characters.
Location Select a geographic location to host your Azure Load Testing resource.
This location also determines where the test engines are hosted and where the JMeter client requests originate from.
Optionally, you can configure more details on the Tags tab. Tags are name/value pairs that enable you to categorize resources and view consolidated billing by applying the same tag to multiple resources and resource groups.
After you're finished configuring the resource, select Review + Create.
Review all the configuration settings and select Create to start the deployment of the Azure Load Testing resource.
When the process has finished, a deployment success message appears.
To view the new resource, select Go to resource.
Optionally, manage access to your Azure Load Testing resource.
Azure Load Testing uses role-based access control (RBAC) to manage permissions for your resource. If you encounter this message, your account doesn't have the necessary permissions to manage tests.
Create a load test
To create a load test in the Load Testing resource for the sample app:
Go to the Load Testing resource and select Create new test on the command bar.
On the Basics tab, enter the Test name and Test description information. Optionally, you can select the Run test after creation checkbox to automatically start the load test after creating it.
On the Test plan tab, select the JMeter script test method, and then select the SampleApp.jmx test script from the cloned sample application directory. Next, select Upload to upload the file to Azure and configure the load test.
Optionally, you can select and upload additional Apache JMeter configuration files or other files that are referenced in the JMX file. For example, if your test script uses CSV data sets, you can upload the corresponding .csv file(s).
On the Parameters tab, add a new environment variable. Enter webapp for the Name and
<yourappname>.azurewebsites.netfor the Value. Replace the placeholder text
<yourappname>with the name of the newly deployed sample application. Don't include the
The Apache JMeter test script uses the environment variable to retrieve the web application URL. The script then invokes the three APIs in the web application.
On the Load tab, configure the following details. You can leave the default value for this tutorial.
Setting Value Description Engine instances 1 The number of parallel test engines that run the Apache JMeter script.
On the Monitoring tab, specify the application components that you want to monitor with the resource metrics. Select Add/modify to manage the list of application components.
Select Review + create, review all settings, and select Create.
You can update the test configuration at any time, for example to upload a different JMX file. Choose your test in the list of tests, and then select Edit.
Run the load test in the Azure portal
In this section, you'll use the Azure portal to manually start the load test that you created previously. If you checked the Run test after creation checkbox, the test will already be running.
Select Tests to view the list of tests, and then select the test that you created.
You can use the search box and the Time range filter to limit the number of tests.
On the test details page, select Run or Run test. Then, select Run on the Run test confirmation pane to start the load test.
Azure Load Testing begins to monitor and display the application's server metrics on the dashboard.
You can see the streaming client-side metrics while the test is running. By default, the results refresh automatically every five seconds.
You can apply multiple filters or aggregate the results to different percentiles to customize the charts.
You can stop a load test at any time from the Azure portal by selecting Stop.
Wait until the load test finishes fully before you proceed to the next section.
Identify performance bottlenecks
In this section, you'll analyze the results of the load test to identify performance bottlenecks in the application. Examine both the client-side and server-side metrics to determine the root cause of the problem.
First, look at the client-side metrics. You'll notice that the 90th percentile for the Response time metric for the
getAPI requests is higher than it is for the
You can see a similar pattern for Errors, where the
lasttimestampAPI has fewer errors than the other APIs.
The results of the
getAPIs are similar, whereas the
lasttimestampAPI behaves differently. The cause might be database related, because both the
getAPIs involve database access.
To investigate this bottleneck in more detail, scroll down to the Server-side metrics dashboard section.
The server-side metrics show detailed information about your Azure application components: Azure App Service plan, Azure App Service web app, and Azure Cosmos DB.
In the metrics for the Azure App Service plan, you can see that the CPU Percentage and Memory Percentage metrics are within an acceptable range.
Now, look at the Azure Cosmos DB server-side metrics.
Notice that the Normalized RU Consumption metric shows that the database was quickly running at 100% resource utilization. The high resource usage might have caused database throttling errors. It also might have increased response times for the
You can also see that the Provisioned Throughput metric for the Azure Cosmos DB instance has a maximum throughput of 400 RUs. Increasing the provisioned throughput of the database might resolve the performance problem.
Increase the database throughput
In this section, you'll allocate more resources to the database, to resolve the performance bottleneck.
For Azure Cosmos DB, increase the database RU scale setting:
Go to the Azure Cosmos DB resource that you provisioned as part of the sample application deployment.
Select the Data Explorer tab.
Select Scale & Settings, and update the throughput value to 1200.
Select Save to confirm the changes.
Validate the performance improvements
Now that you've increased the database throughput, rerun the load test and verify that the performance results have improved:
On the test run dashboard, select Rerun, and then select Rerun on the Rerun test pane.
You'll see a new test run entry with a status column that cycles through the Provisioning, Executing, and Done states. At any time, select the test run to monitor how the load test is progressing.
After the load test finishes, check the Response time results and the Errors results of the client-side metrics.
Check the server-side metrics for Azure Cosmos DB and ensure that the performance has improved.
The Azure Cosmos DB Normalized RU Consumption value is now well below 100%.
Now that you've changed the scale settings of the database, you see that:
- The response time for the
getAPIs has improved.
- The normalized RU consumption remains well under the limit.
As a result, the overall performance of your application has improved.
Clean up resources
You can reuse the Azure Load Testing resource that you created for other Azure Load Testing tutorials and how-to articles.
If you don't plan to use any of the resources that you created, delete them so you don't incur any further charges. If you've deployed the sample application in a different resource group, you might want to repeat the following steps.
To delete resources by using the Azure portal:
Select the menu button in the upper-left corner, and then select Resource groups.
From the list, select the resource group that you created.
Select Delete resource group.
Enter the resource group name. Then select Delete.
To delete resources by using the Azure CLI, enter the following command:
az group delete --name <yourresourcegroup>
Remember, deleting the resource group deletes all of the resources within it.
Advance to the next tutorial to learn how to set up an automated regression testing workflow by using Azure Pipelines or GitHub Actions.