High Performance Networking in .NET with Kestrel and YARP

Patrick KearnsPatrick Kearns
4 min read

I've continuously sought effective solutions for building high performance applications. Among the various technologies I've worked with, Kestrel and YARP have emerged as powerful tools, particularly when optimising network performance and scalability in .NET applications. Below, I'll share deeper insights and advanced techniques that I've discovered and refined through experience, aiming to help you harness these powerful frameworks effectively.

A look at Kestrel's Performance

Kestrel's introduction was transformative for the ASP.NET community. Built specifically for high performance, Kestrel supports asynchronous request handling, dramatically improving scalability. My initial adoption of Kestrel required an understanding beyond basic configurations to achieve enterprise level performance.

I soon realised that tuning connection limits, keep alive settings, and request buffering had a direct impact on throughput. These optimisations significantly improved handling large spikes in web traffic without compromising service reliability.

An example of optimising Kestrel's configurations:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 200_000;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 20_000;
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(3);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(60);
    serverOptions.Limits.Http2.MaxStreamsPerConnection = 100;
});

Leveraging YARP for Scalability

In large distributed applications, managing multiple microservices becomes complex. My experience deploying YARP showed me its exceptional capabilities for request routing, load balancing, and dynamic configuration.

A particularly valuable feature of YARP is its advanced session affinity, which allows sticky sessions to particular servers, enhancing performance for stateful services. Here's a look at configuring session affinity:

"Clusters": {
  "webCluster": {
    "SessionAffinity": {
      "Enabled": true,
      "Policy": "Cookie",
      "Cookie": {
        "Name": "AffinityCookie",
        "Expiration": "00:30:00"
      }
    },
    "Destinations": {
      "server1": {"Address": "https://localhost:7001"},
      "server2": {"Address": "https://localhost:7002"}
    }
  }
}

Implementing affinity was crucial in maintaining user state without extensive overhead in our user intensive applications.

Load Balancing Strategies

Load balancing in YARP can be customised extensively. I’ve found customising the load balancing strategy to fit specific application needs can lead to substantial performance gains.

An example of configuring a round robin load balancer with custom health checks:

"HealthCheck": {
  "Active": {
    "Enabled": true,
    "Interval": "00:00:10",
    "Timeout": "00:00:05",
    "Policy": "ConsecutiveFailures",
    "FailureThreshold": 3
  }
},
"LoadBalancing": {
  "Policy": "RoundRobin"
}

Through iterative testing, I discovered that tuning the health check interval and thresholds was pivotal in maintaining optimal load distribution and quick recovery from outages.

Diagnostic and Observability Techniques

Achieving high performance isn't only about initial setup but also about maintaining visibility. I've integrated structured logging and distributed tracing through OpenTelemetry, enabling detailed diagnostics and facilitating quicker issue resolution.

Here's an example of integrating OpenTelemetry with Kestrel:

builder.Services.AddOpenTelemetryTracing(builder =>
{
    builder
        .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MyKestrelApp"))
        .AddAspNetCoreInstrumentation()
        .AddHttpClientInstrumentation()
        .AddConsoleExporter();
});

This setup provided crucial insights during performance tuning, helping identify bottlenecks and latencies precisely.

Security and Performance Considerations

Security often impacts performance. Initially, configuring HTTPS introduced performance overhead, but fine tuning certificate handling and connection settings allowed me to mitigate these effects.

Optimising certificate loading and SSL configurations:

serverOptions.ListenAnyIP(5001, listenOptions =>
{
    listenOptions.UseHttps(httpsOptions =>
    {
        httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
            CertificateLoader.LoadFromStoreCert("MyCertificate", "MyStore", StoreLocation.CurrentUser, true);
    });
});

Through careful management of certificates and encryption settings, performance impact was reduced significantly without compromising security.

Other Performance Tweaks

Real deployment scenarios have continually taught me invaluable lessons. For instance, leveraging the reverse proxy cache of YARP dramatically reduced latency and server load:

"Caching": {
  "Enabled": true,
  "ExpirationTime": "00:05:00"
}

Caching also significantly reduced response times and improved client experience during peak traffic hours.

Benchmarking and Continuous Optimisation

Performance is not static; regular benchmarking has become integral to my process. Using BenchmarkDotNet for micro benchmarks and Apache JMeter for load testing, I've maintained and continually improved performance.

BenchmarkDotNet example for a basic HTTP endpoint:

[Benchmark]
public async Task TestEndpointPerformance()
{
    var response = await _httpClient.GetAsync("https://localhost:5001/api/data");
    response.EnsureSuccessStatusCode();
}

Regular testing and analysis informed ongoing optimisations and ensured consistent high performance.

My experience with Kestrel and YARP has revealed a wealth of potential when building high performance, scalable .NET applications. By mastering advanced configuration, observability, security, and continuous benchmarking, I've managed to build systems resilient to heavy loads and capable of maintaining exceptional performance.

The ideas outlined here come from practical experience, experimentation, and iterative learning. My advice is immerse yourself deeply in these tools, continually refine your approach, play around, and never underestimate the value of thorough testing and monitoring.

0
Subscribe to my newsletter

Read articles from Patrick Kearns directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Patrick Kearns
Patrick Kearns