Skip to content

Commit b2c7d51

Browse files
[Kestrel] Move to GenericHost (#24279)
* [Kestrel] Move to GenericHost * Change TransportSelector * Add an empty app for TestServer * Add an empty app for TestServer * Set app * Stop host * Stop the TestSserver * Stop more hosts! * Stop host in dispose * implement IAsyncDisposable for TestServer * configure await * catch OperationCanceledException * Apply suggestions from code review Co-authored-by: Brennan <[email protected]>
1 parent 25948ab commit b2c7d51

35 files changed

+910
-730
lines changed

src/Servers/Kestrel/perf/Kestrel.Performance/InMemoryTransportBenchmark.cs

+14-9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using Microsoft.AspNetCore.Hosting;
1717
using Microsoft.AspNetCore.Http;
1818
using Microsoft.Extensions.DependencyInjection;
19+
using Microsoft.Extensions.Hosting;
1920

2021
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
2122
{
@@ -33,22 +34,26 @@ public class InMemoryTransportBenchmark
3334
private static readonly string _plaintextPipelinedExpectedResponse =
3435
string.Concat(Enumerable.Repeat(_plaintextExpectedResponse, RequestParsingData.Pipelining));
3536

36-
private IWebHost _host;
37+
private IHost _host;
3738
private InMemoryConnection _connection;
3839

3940
[GlobalSetup(Target = nameof(Plaintext) + "," + nameof(PlaintextPipelined))]
4041
public void GlobalSetupPlaintext()
4142
{
4243
var transportFactory = new InMemoryTransportFactory(connectionsPerEndPoint: 1);
43-
44-
_host = new WebHostBuilder()
45-
// Prevent VS from attaching to hosting startup which could impact results
46-
.UseSetting("preventHostingStartup", "true")
47-
.UseKestrel()
48-
// Bind to a single non-HTTPS endpoint
49-
.UseUrls("http://127.0.0.1:5000")
44+
45+
_host = new HostBuilder()
46+
.ConfigureWebHost(webHostBuilder =>
47+
{
48+
webHostBuilder
49+
// Prevent VS from attaching to hosting startup which could impact results
50+
.UseSetting("preventHostingStartup", "true")
51+
.UseKestrel()
52+
// Bind to a single non-HTTPS endpoint
53+
.UseUrls("http://127.0.0.1:5000")
54+
.Configure(app => app.UseMiddleware<PlaintextMiddleware>());
55+
})
5056
.ConfigureServices(services => services.AddSingleton<IConnectionListenerFactory>(transportFactory))
51-
.Configure(app => app.UseMiddleware<PlaintextMiddleware>())
5257
.Build();
5358

5459
_host.Start();

src/Servers/Kestrel/samples/Http2SampleApp/Program.cs

+45-41
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
using System;
22
using System.IO;
3-
using System.Net;
43
using System.Security.Authentication;
54
using Microsoft.AspNetCore.Connections;
65
using Microsoft.AspNetCore.Connections.Features;
76
using Microsoft.AspNetCore.Hosting;
87
using Microsoft.AspNetCore.Server.Kestrel.Core;
98
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.Hosting;
1010
using Microsoft.Extensions.Logging;
1111

1212
namespace Http2SampleApp
@@ -15,54 +15,58 @@ public class Program
1515
{
1616
public static void Main(string[] args)
1717
{
18-
var hostBuilder = new WebHostBuilder()
19-
.ConfigureLogging((_, factory) =>
18+
var hostBuilder = new HostBuilder()
19+
.ConfigureWebHost(webHostBuilder =>
2020
{
21-
// Set logging to the MAX.
22-
factory.SetMinimumLevel(LogLevel.Trace);
23-
factory.AddConsole();
24-
})
25-
.UseKestrel()
26-
.ConfigureKestrel((context, options) =>
27-
{
28-
var basePort = context.Configuration.GetValue<int?>("BASE_PORT") ?? 5000;
29-
30-
// Http/1.1 endpoint for comparison
31-
options.ListenAnyIP(basePort, listenOptions =>
32-
{
33-
listenOptions.Protocols = HttpProtocols.Http1;
34-
});
35-
36-
// TLS Http/1.1 or HTTP/2 endpoint negotiated via ALPN
37-
options.ListenAnyIP(basePort + 1, listenOptions =>
38-
{
39-
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
40-
listenOptions.UseHttps();
41-
listenOptions.Use((context, next) =>
21+
webHostBuilder
22+
.UseKestrel()
23+
.ConfigureKestrel((context, options) =>
4224
{
43-
// https://tools.ietf.org/html/rfc7540#appendix-A
44-
// Allows filtering TLS handshakes on a per connection basis
25+
var basePort = context.Configuration.GetValue<int?>("BASE_PORT") ?? 5000;
4526

46-
var tlsFeature = context.Features.Get<ITlsHandshakeFeature>();
27+
// Http/1.1 endpoint for comparison
28+
options.ListenAnyIP(basePort, listenOptions =>
29+
{
30+
listenOptions.Protocols = HttpProtocols.Http1;
31+
});
4732

48-
if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
33+
// TLS Http/1.1 or HTTP/2 endpoint negotiated via ALPN
34+
options.ListenAnyIP(basePort + 1, listenOptions =>
4935
{
50-
throw new NotSupportedException("Prohibited cipher: " + tlsFeature.CipherAlgorithm);
51-
}
36+
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
37+
listenOptions.UseHttps();
38+
listenOptions.Use((context, next) =>
39+
{
40+
// https://tools.ietf.org/html/rfc7540#appendix-A
41+
// Allows filtering TLS handshakes on a per connection basis
5242

53-
return next();
54-
});
55-
});
43+
var tlsFeature = context.Features.Get<ITlsHandshakeFeature>();
5644

57-
// Prior knowledge, no TLS handshake. WARNING: Not supported by browsers
58-
// but useful for the h2spec tests
59-
options.ListenAnyIP(basePort + 5, listenOptions =>
60-
{
61-
listenOptions.Protocols = HttpProtocols.Http2;
62-
});
45+
if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
46+
{
47+
throw new NotSupportedException("Prohibited cipher: " + tlsFeature.CipherAlgorithm);
48+
}
49+
50+
return next();
51+
});
52+
});
53+
54+
// Prior knowledge, no TLS handshake. WARNING: Not supported by browsers
55+
// but useful for the h2spec tests
56+
options.ListenAnyIP(basePort + 5, listenOptions =>
57+
{
58+
listenOptions.Protocols = HttpProtocols.Http2;
59+
});
60+
})
61+
.UseContentRoot(Directory.GetCurrentDirectory())
62+
.UseStartup<Startup>();
6363
})
64-
.UseContentRoot(Directory.GetCurrentDirectory())
65-
.UseStartup<Startup>();
64+
.ConfigureLogging((_, factory) =>
65+
{
66+
// Set logging to the MAX.
67+
factory.SetMinimumLevel(LogLevel.Trace);
68+
factory.AddConsole();
69+
});
6670

6771
hostBuilder.Build().Run();
6872
}

src/Servers/Kestrel/samples/LargeResponseApp/Startup.cs

+11-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Threading.Tasks;
88
using Microsoft.AspNetCore.Builder;
99
using Microsoft.AspNetCore.Hosting;
10+
using Microsoft.Extensions.Hosting;
1011

1112
namespace LargeResponseApp
1213
{
@@ -38,13 +39,17 @@ public void Configure(IApplicationBuilder app)
3839

3940
public static Task Main(string[] args)
4041
{
41-
var host = new WebHostBuilder()
42-
.UseKestrel(options =>
42+
var host = new HostBuilder()
43+
.ConfigureWebHost(webHostBuilder =>
4344
{
44-
options.Listen(IPAddress.Loopback, 5001);
45-
})
46-
.UseContentRoot(Directory.GetCurrentDirectory())
47-
.UseStartup<Startup>()
45+
webHostBuilder
46+
.UseKestrel(options =>
47+
{
48+
options.Listen(IPAddress.Loopback, 5001);
49+
})
50+
.UseContentRoot(Directory.GetCurrentDirectory())
51+
.UseStartup<Startup>();
52+
})
4853
.Build();
4954

5055
return host.RunAsync();

src/Servers/Kestrel/samples/PlaintextApp/Startup.cs

+10-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Microsoft.AspNetCore.Builder;
1111
using Microsoft.AspNetCore.Connections;
1212
using Microsoft.AspNetCore.Hosting;
13+
using Microsoft.Extensions.Hosting;
1314

1415
namespace PlaintextApp
1516
{
@@ -34,13 +35,17 @@ public void Configure(IApplicationBuilder app)
3435

3536
public static async Task Main(string[] args)
3637
{
37-
var host = new WebHostBuilder()
38-
.UseKestrel(options =>
38+
var host = new HostBuilder()
39+
.ConfigureWebHost(webHostBuilder =>
3940
{
40-
options.Listen(IPAddress.Loopback, 5001);
41+
webHostBuilder
42+
.UseKestrel(options =>
43+
{
44+
options.Listen(IPAddress.Loopback, 5001);
45+
})
46+
.UseContentRoot(Directory.GetCurrentDirectory())
47+
.UseStartup<Startup>();
4148
})
42-
.UseContentRoot(Directory.GetCurrentDirectory())
43-
.UseStartup<Startup>()
4449
.Build();
4550

4651
await host.RunAsync();

src/Servers/Kestrel/samples/QuicSampleApp/Program.cs

+52-47
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.AspNetCore.Connections;
77
using Microsoft.AspNetCore.Hosting;
88
using Microsoft.AspNetCore.Server.Kestrel.Core;
9+
using Microsoft.Extensions.Hosting;
910
using Microsoft.Extensions.Logging;
1011

1112
namespace QuicSampleApp
@@ -22,60 +23,64 @@ public void Configure(IApplicationBuilder app)
2223

2324
public static void Main(string[] args)
2425
{
25-
var hostBuilder = new WebHostBuilder()
26-
.ConfigureLogging((_, factory) =>
27-
{
28-
factory.SetMinimumLevel(LogLevel.Debug);
29-
factory.AddConsole();
30-
})
31-
.UseKestrel()
32-
.UseQuic(options =>
33-
{
34-
options.Certificate = null;
35-
options.Alpn = "QuicTest";
36-
options.IdleTimeout = TimeSpan.FromHours(1);
37-
})
38-
.ConfigureKestrel((context, options) =>
39-
{
40-
var basePort = 5555;
26+
var hostBuilder = new HostBuilder()
27+
.ConfigureWebHost(webHostBuilder =>
28+
{
29+
webHostBuilder
30+
.UseKestrel()
31+
.UseQuic(options =>
32+
{
33+
options.Certificate = null;
34+
options.Alpn = "QuicTest";
35+
options.IdleTimeout = TimeSpan.FromHours(1);
36+
})
37+
.ConfigureKestrel((context, options) =>
38+
{
39+
var basePort = 5555;
4140

42-
options.Listen(IPAddress.Any, basePort, listenOptions =>
43-
{
44-
listenOptions.Protocols = HttpProtocols.Http3;
41+
options.Listen(IPAddress.Any, basePort, listenOptions =>
42+
{
43+
listenOptions.Protocols = HttpProtocols.Http3;
4544

46-
async Task EchoServer(MultiplexedConnectionContext connection)
47-
{
48-
// For graceful shutdown
45+
async Task EchoServer(MultiplexedConnectionContext connection)
46+
{
47+
// For graceful shutdown
4948

50-
while (true)
51-
{
52-
var stream = await connection.AcceptAsync();
53-
while (true)
54-
{
55-
var result = await stream.Transport.Input.ReadAsync();
49+
while (true)
50+
{
51+
var stream = await connection.AcceptAsync();
52+
while (true)
53+
{
54+
var result = await stream.Transport.Input.ReadAsync();
5655

57-
if (result.IsCompleted)
58-
{
59-
break;
60-
}
56+
if (result.IsCompleted)
57+
{
58+
break;
59+
}
6160

62-
await stream.Transport.Output.WriteAsync(result.Buffer.ToArray());
61+
await stream.Transport.Output.WriteAsync(result.Buffer.ToArray());
6362

64-
stream.Transport.Input.AdvanceTo(result.Buffer.End);
65-
}
66-
}
67-
}
63+
stream.Transport.Input.AdvanceTo(result.Buffer.End);
64+
}
65+
}
66+
}
6867

69-
((IMultiplexedConnectionBuilder)listenOptions).Use(next =>
70-
{
71-
return context =>
72-
{
73-
return EchoServer(context);
74-
};
75-
});
76-
});
77-
})
78-
.UseStartup<Startup>();
68+
((IMultiplexedConnectionBuilder)listenOptions).Use(next =>
69+
{
70+
return context =>
71+
{
72+
return EchoServer(context);
73+
};
74+
});
75+
});
76+
})
77+
.UseStartup<Startup>();
78+
})
79+
.ConfigureLogging((_, factory) =>
80+
{
81+
factory.SetMinimumLevel(LogLevel.Debug);
82+
factory.AddConsole();
83+
});
7984

8085
hostBuilder.Build().Run();
8186
}

0 commit comments

Comments
 (0)