start of request queue
This commit is contained in:
parent
117dd8cff4
commit
5956609846
|
|
@ -79,6 +79,7 @@
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HttpOverrides" ProjectPath="$(RepoRoot)src\Middleware\HttpOverrides\src\Microsoft.AspNetCore.HttpOverrides.csproj" RefProjectPath="$(RepoRoot)src\Middleware\HttpOverrides\ref\Microsoft.AspNetCore.HttpOverrides.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HttpOverrides" ProjectPath="$(RepoRoot)src\Middleware\HttpOverrides\src\Microsoft.AspNetCore.HttpOverrides.csproj" RefProjectPath="$(RepoRoot)src\Middleware\HttpOverrides\ref\Microsoft.AspNetCore.HttpOverrides.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HttpsPolicy" ProjectPath="$(RepoRoot)src\Middleware\HttpsPolicy\src\Microsoft.AspNetCore.HttpsPolicy.csproj" RefProjectPath="$(RepoRoot)src\Middleware\HttpsPolicy\ref\Microsoft.AspNetCore.HttpsPolicy.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HttpsPolicy" ProjectPath="$(RepoRoot)src\Middleware\HttpsPolicy\src\Microsoft.AspNetCore.HttpsPolicy.csproj" RefProjectPath="$(RepoRoot)src\Middleware\HttpsPolicy\ref\Microsoft.AspNetCore.HttpsPolicy.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization.Routing" ProjectPath="$(RepoRoot)src\Middleware\Localization.Routing\src\Microsoft.AspNetCore.Localization.Routing.csproj" RefProjectPath="$(RepoRoot)src\Middleware\Localization.Routing\ref\Microsoft.AspNetCore.Localization.Routing.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization.Routing" ProjectPath="$(RepoRoot)src\Middleware\Localization.Routing\src\Microsoft.AspNetCore.Localization.Routing.csproj" RefProjectPath="$(RepoRoot)src\Middleware\Localization.Routing\ref\Microsoft.AspNetCore.Localization.Routing.csproj" />
|
||||||
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.RequestQueue" ProjectPath="$(RepositoryRoot)src\Middleware\RequestQueue\src\Microsoft.AspNetCore.RequestQueue.csproj" RefProjectPath="$(RepositoryRoot)src\Middleware\RequestQueue\ref\Microsoft.AspNetCore.RequestQueue.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization" ProjectPath="$(RepoRoot)src\Middleware\Localization\src\Microsoft.AspNetCore.Localization.csproj" RefProjectPath="$(RepoRoot)src\Middleware\Localization\ref\Microsoft.AspNetCore.Localization.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization" ProjectPath="$(RepoRoot)src\Middleware\Localization\src\Microsoft.AspNetCore.Localization.csproj" RefProjectPath="$(RepoRoot)src\Middleware\Localization\ref\Microsoft.AspNetCore.Localization.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.MiddlewareAnalysis" ProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\src\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" RefProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\ref\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.MiddlewareAnalysis" ProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\src\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" RefProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\ref\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.NodeServices" ProjectPath="$(RepoRoot)src\Middleware\NodeServices\src\Microsoft.AspNetCore.NodeServices.csproj" RefProjectPath="$(RepoRoot)src\Middleware\NodeServices\ref\Microsoft.AspNetCore.NodeServices.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.NodeServices" ProjectPath="$(RepoRoot)src\Middleware\NodeServices\src\Microsoft.AspNetCore.NodeServices.csproj" RefProjectPath="$(RepoRoot)src\Middleware\NodeServices\ref\Microsoft.AspNetCore.NodeServices.csproj" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!-- This file is automatically generated. -->
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
||||||
|
<Compile Include="Microsoft.AspNetCore.HttpsPolicy.netcoreapp3.0.cs" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Http" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Http.Extensions" />
|
||||||
|
<Reference Include="Microsoft.Extensions.Configuration.Binder" />
|
||||||
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Builder
|
||||||
|
{
|
||||||
|
public static partial class HstsBuilderExtensions
|
||||||
|
{
|
||||||
|
public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHsts(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { throw null; }
|
||||||
|
}
|
||||||
|
public static partial class HstsServicesExtensions
|
||||||
|
{
|
||||||
|
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHsts(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<Microsoft.AspNetCore.HttpsPolicy.HstsOptions> configureOptions) { throw null; }
|
||||||
|
}
|
||||||
|
public static partial class HttpsPolicyBuilderExtensions
|
||||||
|
{
|
||||||
|
public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHttpsRedirection(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { throw null; }
|
||||||
|
}
|
||||||
|
public static partial class HttpsRedirectionServicesExtensions
|
||||||
|
{
|
||||||
|
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHttpsRedirection(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionOptions> configureOptions) { throw null; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace Microsoft.AspNetCore.HttpsPolicy
|
||||||
|
{
|
||||||
|
public partial class HstsMiddleware
|
||||||
|
{
|
||||||
|
public HstsMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.HttpsPolicy.HstsOptions> options) { }
|
||||||
|
public HstsMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.HttpsPolicy.HstsOptions> options, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
|
||||||
|
public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) { throw null; }
|
||||||
|
}
|
||||||
|
public partial class HstsOptions
|
||||||
|
{
|
||||||
|
public HstsOptions() { }
|
||||||
|
public System.Collections.Generic.IList<string> ExcludedHosts { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||||
|
public bool IncludeSubDomains { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
|
public System.TimeSpan MaxAge { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
|
public bool Preload { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
|
}
|
||||||
|
public partial class HttpsRedirectionMiddleware
|
||||||
|
{
|
||||||
|
public HttpsRedirectionMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionOptions> options, Microsoft.Extensions.Configuration.IConfiguration config, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
|
||||||
|
public HttpsRedirectionMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionOptions> options, Microsoft.Extensions.Configuration.IConfiguration config, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature serverAddressesFeature) { }
|
||||||
|
public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) { throw null; }
|
||||||
|
}
|
||||||
|
public partial class HttpsRedirectionOptions
|
||||||
|
{
|
||||||
|
public HttpsRedirectionOptions() { }
|
||||||
|
public int? HttpsPort { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
|
public int RedirectStatusCode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||||
|
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.HttpsPolicy" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.HttpsPolicy;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace RequestQueueSample
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment environment)
|
||||||
|
{
|
||||||
|
app.Run(async context =>
|
||||||
|
{
|
||||||
|
await context.Response.WriteAsync("Hello world!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry point for the application.
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var host = new WebHostBuilder()
|
||||||
|
.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory()) // for the cert file
|
||||||
|
.ConfigureLogging(factory =>
|
||||||
|
{
|
||||||
|
factory.SetMinimumLevel(LogLevel.Debug);
|
||||||
|
factory.AddConsole();
|
||||||
|
})
|
||||||
|
.UseStartup<Startup>()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Description>ASP.NET Core middleware for queuing incoming HTTP requests, to avoid threadpool starvation.</Description>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<WarningsNotAsErrors>$(WarningsNotAsErrors);CS1591</WarningsNotAsErrors>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Http" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Http.Extensions" />
|
||||||
|
<Reference Include="Microsoft.Extensions.Configuration.Binder" />
|
||||||
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.RequestQueue
|
||||||
|
{
|
||||||
|
internal class SemaphoreWrapper
|
||||||
|
{
|
||||||
|
private static SemaphoreSlim semaphore;
|
||||||
|
|
||||||
|
public SemaphoreWrapper(int qlength)
|
||||||
|
{
|
||||||
|
semaphore = new SemaphoreSlim(qlength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task EnterQueue()
|
||||||
|
{
|
||||||
|
return semaphore.WaitAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LeaveQueue()
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SpotsLeft
|
||||||
|
{
|
||||||
|
get => semaphore.CurrentCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.AspNetCore.RequestQueue" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.RequestQueue.Tests
|
||||||
|
{
|
||||||
|
public class SemaphoreWrapperTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task TestBehavior()
|
||||||
|
{
|
||||||
|
var s = new SemaphoreWrapper(1);
|
||||||
|
Assert.Equal(1, s.SpotsLeft);
|
||||||
|
|
||||||
|
await s.EnterQueue();
|
||||||
|
Assert.Equal(0, s.SpotsLeft);
|
||||||
|
|
||||||
|
s.LeaveQueue();
|
||||||
|
Assert.Equal(1, s.SpotsLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestQueueLength()
|
||||||
|
{
|
||||||
|
var s = new SemaphoreWrapper(2);
|
||||||
|
|
||||||
|
var t1 = s.EnterQueue();
|
||||||
|
Assert.True(t1.IsCompleted);
|
||||||
|
|
||||||
|
var t2 = s.EnterQueue();
|
||||||
|
Assert.True(t2.IsCompleted);
|
||||||
|
|
||||||
|
var t3 = s.EnterQueue();
|
||||||
|
Assert.False(t3.IsCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task TestWaiting()
|
||||||
|
{
|
||||||
|
var s = new SemaphoreWrapper(1);
|
||||||
|
await s.EnterQueue();
|
||||||
|
|
||||||
|
var waitingTask = s.EnterQueue();
|
||||||
|
Assert.False(waitingTask.IsCompleted);
|
||||||
|
|
||||||
|
s.LeaveQueue();
|
||||||
|
await waitingTask.TimeoutAfter(TimeSpan.FromSeconds(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
@ECHO OFF
|
||||||
|
SET RepoRoot=%~dp0..\..
|
||||||
|
%RepoRoot%\build.cmd -projects %~dp0\**\*.*proj %*
|
||||||
Loading…
Reference in New Issue