Skip to content
This repository has been archived by the owner on Aug 25, 2021. It is now read-only.

redhat-developer/kestrel-linux-transport

Repository files navigation

This code is no longer maintained, and won't be updated for new versions of .NET.

Introduction

The ASP.NET Core Kestrel webserver has been using libuv as a cross-platform network library. It is possible to replace libuv with another implementation thanks to the Transport abstraction.

In this repo we explore creating a Transport for Linux specifically.

Using the package

Add the myget feed to your NuGet.Config file:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="rh" value="https://www.myget.org/F/redhat-dotnet/api/v3/index.json" />
  </packageSources>
</configuration>

Include a package reference in your project csproj file:

  <ItemGroup>
    <PackageReference Include="RedHat.AspNetCore.Server.Kestrel.Transport.Linux" Version="3.1.0-*" />
  </ItemGroup>

Call UseLinuxTransport when creating the WebHost in your Program.cs:

public static IWebHost BuildWebHost(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder
                        .UseLinuxTransport()
                        .UseStartup<Startup>();
                });

note: It's safe to call UseLinuxTransport on non-Linux platforms, it will no-op.

Repo structure

There are 5 projects in this repository:

  • src/RedHat.AspNetCore.Server.Kestrel.Transport.Linux: managed library implementing Transport
  • samples/KestrelSample: Kestrel app for benchmarking
  • test/RedHat.AspNetCore.Server.Kestrel.Transport.Linux.Test: xunit test projects, has access to internals of managed library
  • test/RedHat.AspNetCore.Server.Kestrel.Transport.Linux.TestApp: empty application to use during development, has access to internals of managed library

The library can be packaged by running the dotnet pack on src/RedHat.AspNetCore.Server.Kestrel.Transport.Linux.

$ dotnet pack src/RedHat.AspNetCore.Server.Kestrel.Transport.Linux --configuration Release

To build the library and run the tests execute dotnet test on test/RedHat.AspNetCore.Server.Kestrel.Transport.Linux.Test.

$ dotnet test test/RedHat.AspNetCore.Server.Kestrel.Transport.Linux.Test

Design

Similar to other implementations, this library makes use of the non-blocking socket and epoll. Like the corefx Socket implementation, the eventloop is implemented in managed (C#) code. This is different from the libuv loop which is part of the native libuv library.

This library does not provide a generic xplat network API. It uses the kernel primitives directly to implement the Transport API. This reduces the number of heap allocated objects (e.g. uv_buf_t, SocketAsyncEventArgs), which means there is less GC pressure. Implementations building on top of an xplat API will pool objects to achieve this.

The implementation starts a number of threads that each accept connections. This is based on SO_REUSEPORT socket option. This option allow multiple sockets to concurrently bind and listen to the same port. The kernel performs load-balancing between the listen sockets.

The Transport has these options:

  • DeferSend: This defers sends to the Transport Thread which increases chances for multiple sends to coalesce. This options defaults to true.

  • ThreadCount: Specifies the number of Transport Threads. This defaults to the number of logical processors in the system, maxed to 16.

  • AioSend/AioReceive: Uses Linux AIO system calls to batch send and receive calls. AioSend implies DeferSend. These options default to true.