Skip to main content

Load Tests

Last updated on

This page describes how to perform load tests on MagicOnion applications.

MagicOnion uses a custom protocol based on gRPC, so it cannot be load tested using common load testing tools such as JMeter or k6.

This may seem like a disadvantage, but MagicOnion clients are written in C# (.NET), making it easy to create and execute custom scenarios for load testing using .NET applications.

MagicOnion applications often execute scenarios with multiple steps using real-time communication, and when creating such complex scenarios, you can maximize the reuse of code and the implementation knowledge of the client.

Choose a Load Testing Framework​

Since the workers and clients for load testing must be MagicOnion clients, they must be .NET applications. The following are some load testing frameworks that meet this requirement:

You can also implement your own .NET applications, such as console applications or Unity headless clients, without using a framework.

Load Testing with DFrame​

DFrame is an open-source distributed .NET-based load testing framework provided by Cysharp. DFrame allows you to write load test scenarios in Workloads and apply load using multiple workers.

The following is an example of a load test using DFrame. For more information, refer to the DFrame documentation.

using DFrame;
using MagicOnion;

DFrameApp.Run(7312, 7313); // WebUI:7312, WorkerListen:7313

public class SampleWorkload : Workload
{
public override async Task ExecuteAsync(WorkloadContext context)
{
using var channel = GrpcChannel.ForAddress("https://api.example.com");

var apiClient = MagicOnionClient.Create<IAccountService>(channel);
var accessToken = await apiClient.CreateUserAsync($"User-{Guid.CreateVersion7()}", "p@ssword1");

var hubClient = await StreamingHubClient.ConnectAsync<IGreeterHub, IGreeterHubReceiver>(
channel,
new GreeterHubReceiver(),
StreamingHubClientOptions.CreateWithDefault(callOptions: new CallOptions(){
Headers = new Metadata
{
{ "Authorization", $"Bearer {accessToken}" },
}
})
);
var result = await hubClient.HelloAsync();
}
}
note

DFrame uses MagicOnion for communication between the DFrame controller and workers, so be careful of version conflicts with MagicOnion.Client.

Load Testing with NBomber​

NBomber is a .NET-based distributed load testing framework commercially provided by NBomber LLC.

The following is an example of a load test scenario using NBomber. For more information, refer to the NBomber documentation.

var scenario = Scenario.Create("MagicOnionTest", async ctx =>
{
using var channel = GrpcChannel.ForAddress("https://api.example.com");

var createUser = await Step.Run("create", ctx, async () =>
{
var apiClient = MagicOnionClient.Create<IAccountService>(channel);
var accessToken = await apiClient.CreateUserAsync($"User-{Guid.CreateVersion7()}", "p@ssword1");
return Response.Ok();
});

IGreeterHub? hubClient = null;
var receiver = new GreeterHubReceiver();
var connect = await Step.Run("connect", ctx, async () =>
{

hubClient = await StreamingHubClient.ConnectAsync<IGreeterHub, IGreeterHubReceiver>(
channel,
new GreeterHubReceiver(),
StreamingHubClientOptions.CreateWithDefault(callOptions: new CallOptions(){
Headers = new Metadata
{
{ "Authorization", $"Bearer {accessToken}" },
}
})
);
return Response.Ok();
});

var hello = await Step.Run("hello", ctx, async () =>
{
var result = await hubClient.HelloAsync();
return Response.Ok();
});

return Response.Ok();
});