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.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.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.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" />
|
||||
|
|
|
|||
|
|
@ -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