0

I am trying to force an asp.net app to be single threaded ie: can only serve one request at time (need to do this to simulate a legacy application).

All I could think of was use a static variable to lock and Monitor.TryEnter and sleep the thread for 5 seconds to simulate as through there is only one thread processing requests.

Is there a better/elegant way to force an asp.net app to be single threaded only ie: able to strictly process one request only at a time.

This will be run as Docker container with Kestrel serving the requests.

This is what I have so far that seems to work, when calling the /test enpoint it blocks the whole app for 5 seconds

public class Program
{
    private static readonly object LockObject = new();

    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // Add services to the container.
        builder.Services.AddAuthorization();

        builder.Services.AddEndpointsApiExplorer();
        builder.Services.AddSwaggerGen();

        builder.Services.AddApplicationInsightsTelemetry();


        var app = builder.Build();

        // Configure the HTTP request pipeline.
        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }

        app.UseAuthorization();

        app.MapGet("/test", (HttpContext httpContext) =>
        {
            if (Monitor.TryEnter(LockObject, new TimeSpan(0, 0, 6)))
            {
                try
                {
                    Thread.Sleep(5000);
                }
                finally
                {
                    Monitor.Exit(LockObject);
                }
            }

            return ("Hello From Container: " + System.Environment.MachineName);
        });

        app.Run();
    }
}
Ricky Gummadi
  • 4,559
  • 2
  • 41
  • 67
  • 1
    Is your goal to only accept a single connection at a time, or to only process a single request at a time? – ProgrammingLlama Aug 16 '22 at 05:13
  • @DiplomacyNotWar Ideally only accepts a single connection at a time, not sure if this is possible with Kestrel, so the next best thing will be to process a single request at a time. This app will be hosted in a container so Kestrel will be serving the app – Ricky Gummadi Aug 16 '22 at 10:50
  • 1
    Gotta go for dinner, but maybe look at this property for Kestrel: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserverlimits.maxconcurrentconnections?view=aspnetcore-6.0#microsoft-aspnetcore-server-kestrel-core-kestrelserverlimits-maxconcurrentconnections – ProgrammingLlama Aug 16 '22 at 10:53
  • thanks @DiplomacyNotWar that looks very promising will try that out! – Ricky Gummadi Aug 16 '22 at 10:55
  • 1
    You can use the concurrency limiter middleware https://www.nuget.org/packages/Microsoft.AspNetCore.ConcurrencyLimiter – davidfowl Aug 18 '22 at 04:07
  • 1
    I was going to say that you could easily build your own middleware with the async `SemaphoreSlim` to limit concurrency without blocking threads. But will this be enough to achieve what you want? – Jeremy Lakeman Aug 18 '22 at 05:43

2 Answers2

2

if you application is hosted on iis
in application selected the pool for application

click in Advanced Settings
Option Queue Length: 1

enter image description here

look at https://docs.revenera.com/installshield23helplib/helplibrary/IIS-AppPoolsNode.htm

if you are running from iis express

IIS Express can be configured using applicationHost.config file. It is located at %userprofile%\my documents\IISexpress\config

look in this post Configure Maximum Number of Requests in IIS Express

In kestrel

builder.WebHost.ConfigureKestrel(serverOptions =>
{
   serverOptions.Limits.MaxConcurrentConnections = 1;
});

more info https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/options?view=aspnetcore-6.0

Carlos Cocom
  • 937
  • 1
  • 8
  • 23
1

You can use the ConcurrencyLimiter middleware to limit concurrent requests.

Though, to be clear, this isn't single threaded, it's single request at a time.

davidfowl
  • 37,120
  • 7
  • 93
  • 103