👉🏼 Click here to Join I ❤️ .NET WhatsApp Channel to get 🔔 notified about new articles and other updates.
Using NBomber for Performance, Load and Stress testing in ASP.NET WEB API

Using NBomber for Performance, Load and Stress testing in ASP.NET WEB API

Authors - Abdul Rahman (Content Writer), Regina Sharon (Graphic Designer)

Web API

20 Articles

Improve

Table of Contents

  1. What we gonna do?
  2. Why we gonna do?
  3. How we gonna do?
  4. Summary

What we gonna do?

Performance testing helps you understand how your application behaves under heavy load, such as when 10, 100, or 10,000 users access it simultaneously. This involves using performance, load, and stress tests to identify bottlenecks and ensure your application performs reliably. Focus on high-usage features (hot paths), as they are most likely to slow down under load. Begin with simple tests, particularly those targeting shared resources like databases, to establish a foundation for optimization.

When conducting these tests, avoid running them in production environments unless it's carefully planned, as they can strain resources and disrupt users. Leverage metrics and telemetry to identify performance issues and prioritize fixes. Keep in mind that addressing one bottleneck can shift the issue elsewhere, which is a natural part of performance testing. To perform these tests, use tools like NBomber for .NET, which allows you to write tests in C#. For more advanced needs, consider JMeter, a standard load-testing framework.

It's best to test APIs rather than UIs, as the backend typically contains shared resources that need optimization. Run your tests in release mode to obtain the most accurate results. Always compare the performance of new code versions against previous ones to identify potential regressions or improvements. These comparisons will help you refine your application's performance iteratively.

Why we gonna do?

Performance testing revolves around answering key questions about your application's behavior. Monitor metrics like throughput and response times to ensure consistent performance after an initial warm-up period. Pay close attention to memory usage, as uncontrolled growth could indicate leaks that eventually lead to crashes. Stabilizing memory under load is critical to maintaining application reliability.

Another key focus is identifying the breaking point of your application. Use varying load levels and durations to pinpoint when performance starts to degrade. This analysis helps determine whether scaling , such as adding API instances or increasing persistence layer resources, is necessary. If you've released a new version of your application, compare its performance to previous versions. Look for differences in response times or throughput and evaluate whether the changes are acceptable.

Performance testing is an iterative process. Refine your test code and parameters based on the results to continuously improve. Analyzing metrics and acting on the data will help you ensure your application performs reliably under different load conditions.

How we gonna do?

To perform performance testing in ASP.NET Web API,

  1. Create a Console App: Create a new console app using the built-in template. Place the project in a separate subfolder , such as `perf`, within your main code repository to keep it independent of your main application code.

    Solution Structure
  2. Install NBomber: Check the NBomber documentation for guidance. Add the NBomber NuGet package to your console app. NBomber is free for personal use and offers simple setup instructions, including a Hello World tutorial.

  3. Define a Scenario: Create a scenario using NBomber. Write logic to perform a specific task (e.g., hitting an API endpoint). Return a status (`Ok` or `Fail`) based on the response. Use a shared HttpClient to avoid excessive resource consumption.

    Code Sample - Define Scenario

  4. Configure Load Generation: Set up load generation logic. For example, inject 100 requests per second for 30 seconds. Register the scenario with the NBomber runner and configure it to run.

    Code Sample - Configure Load Generation

  5. Build and Run the App: Build the app to ensure everything is set up correctly. Run your API in release mode using `dotnet run --configuration Release` to ensure optimized performance during testing.

    API Project Running in Release Mode
    Weather Forecast Response
  6. Execute the Test: Run the test from the terminal using dotnet run. Monitor the displayed information, including injection rates and response times. Adjust parameters as needed for further runs.

    Performance Test Run Logs
  7. Review the Reports: After the test, review the HTML reports generated by NBomber. Analyze key metrics like throughput, latency, response times, and CPU/memory usage. Watch for patterns such as continually climbing CPU/memory, which might indicate issues.

    Performance Reports Generated
    Performance Report Dashboard
    DotNet Process Metrics

Measuring Http Metrics

The NBomber.Http library enhances load testing for HTTP-based APIs, offering simplified code and additional metrics. By using the HTTP object and enabling the HttpMetricsPlugin, developers gain insights into their API's performance, such as connection and queue duration trends. This process, coupled with iterative refinement, ensures comprehensive performance testing and improved application resilience.

Code Sample - Measuring Http Metrics

Performance Report Dashboard with Http Metrics

Flat and Ramping Inject

  1. Experiment with Load Values: Gradually increase the injection rate to observe system behavior under higher loads. For example, ramp up from 100 to 800 new requests per second and analyze the latency, queue duration, and connection metrics.

  2. Handle Test Completion: Note that when the test ends, NBomber waits for any pending requests to complete before finalizing reports. This ensures all data is captured accurately.

  3. Explore Load Simulations: Review the NBomber documentation on load simulation. Understand different methods like RampingInject, which gradually transitions from a starting point to a target load over a specified duration.

    Code Sample - Changing Load to Ramping Inject

  4. Analyze Results: Run the test and evaluate the metrics. Check for trends such as increasing latency or operation timeouts as the load changes. Examine the HTML report for a detailed breakdown of the scenario chart and request performance.

    Latency Increase
    Increase in Connection and Queuing

Running Multiple Scenarios and Authentication

  1. We can also run multiple scenario's in parallel. In this example, we have two scenarios: one for reading the Weather forecast with different query parameters. Note that I have used NBomber.Data nuget package to use IDataFeed to pass query parameters from pre defined set. In the another scenario, I have used WithInit() to obtain bearer token and store it in a variable and use it in request header with the help of IdentityModel nuget package. Finally we need to resgiter the scenarios in the test run as shown below.

    Code Sample - Multiple Scenarios with Authentication

Grafana Dashboard and InfluxDB Integration

  1. Why Use InfluxDB and Grafana: For longer-running load tests or advanced analysis, leverage InfluxDB, a time-series database, and Grafana, a visualization tool. These tools enable detailed reporting and real-time exploration of test data.

  2. Add the InfluxDBSink NuGet Package: Integrate NBomber.InfluxDBSink by adding its NuGet package to your project. Configure the connection details using a JSON file to link to your InfluxDB instance.

    Code Sample - Infra Configuration JSON

    Code Sample - Link Infra Configuration with NBomber Performance Test

  3. Set Up InfluxDB and Grafana Locally: Use Docker Compose for a quick setup. Obtain the sample docker-compose.yaml file, which includes configurations for running InfluxDB (v1.8.1) and Grafana (v8.5.2) containers. Update ports if needed to avoid conflicts with other services.

    Code Sample - Docker Compose YML

  4. Run Containers: Pull the required Docker images and run the containers using docker compose up --detach. This will run InfluxDB and Grafana in the background while keeping your terminal available. Stop the containers later with docker compose down.

  5. Configure InfluxDB as a Data Source in Grafana: Access Grafana (e.g., on http://localhost:3010) and log in with the default credentials (admin/admin). Add a new data source for InfluxDB and use the Docker Compose service name (InfluxDB ) and port 8086. Specify the database name as NBomber.

    Grafana Login
    Add Data Source
    Select Influx DB
    Setup URL
    Setup Database
    Save Setup
  6. Import Dashboards: Import preconfigured dashboards from JSON files provided in the NBomber repository. Use the nbomber_sessions JSON for session data and the NBomber JSON for detailed test metrics. Link the imported dashboards to your InfluxDB data source.

    Note: Find the JSON files to import dashboards inside the PerformanceLoadStressTesting repo

    Import Dashboards
    NBomber Dashboard in Grafana with Influx DB
    NBomber Dashboards inside Grafana
  7. Run and Monitor Tests: Start your NBomber load tests. During test execution, the NBomber Sessions dashboard displays real-time metrics such as CPU usage, throughput, latency, and data movement. Switch to the NBomber dashboard for scenario-specific details.

    Performance Test Run Sessions
    NBomber Performance Run Visualisation Dashboard
  8. Benefits of Aggregated Reporting: While overkill for single-instance tests, this setup is highly beneficial for aggregating results across multiple machines in a cluster, enabling more comprehensive performance analysis.

Summary

In this article, we learned about NBomber, a performance testing framework for .NET applications, We learned how to run a simple performance test and then with HttpMetricsPlugin for capturing HTTP-specific metrics, and then using NBomber.Data for customizing query string parameters using IDataFeed, and advanced load simulations like RampingInject along with how to use bearer token in WithInit setup.

Additionally, we explored integrating InfluxDB and Grafana to enhance test reporting and visualization by leveraging Docker Compose for setup, configuring InfluxDBSink, and importing prebuilt dashboards for monitoring test metrics.

👉🏼 Click here to Join I ❤️ .NET WhatsApp Channel to get 🔔 notified about new articles and other updates.
  • Web API
  • Performance Test
  • Load Test
  • Stress Test
  • NBomber