[英]How do you configure Kestrel to use a random dynamic port and determine the port at run-time with ASP.NET Core 3.1?
With ASP.NET Core 3.0 I have been able to use this IHostedService
method ...使用 ASP.NET Core 3.0 我已经能够使用这个
IHostedService
方法......
Determine port Kestrel binded to 确定绑定到的端口 Kestrel
... to determine Kestrel's dynamic port at run-time. ... 在运行时确定 Kestrel 的动态端口。
IServerAddressesFeature
is documented for ASP.NET 3.0 here:此处为 ASP.NET 3.0 记录了
IServerAddressesFeature
:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.server.features.iserveraddressesfeature?view=aspnetcore-3.0 https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.server.features.iserveraddressesfeature?view=aspnetcore-3.0
But when changing the version to ASP.NET Core 3.1 then the page redirects back to ASP.NET 3.0 with the hint that the document is not available for ASP.NET Core 3.1.但是当将版本更改为 ASP.NET Core 3.1 时,页面会重定向回 ASP.NET 3.0,并提示该文档不可用于 ASP.NET Core 3.1。 Is
IServerAddressesFeature
no longer working? IServerAddressesFeature
不再工作了吗? Using IServerAddressesFeature
with ASP.NET Core 3.1 still compiles, but the port in the returned ServerAddresses
is always zero.在 ASP.NET Core 3.1 中使用
IServerAddressesFeature
仍然可以编译,但返回的ServerAddresses
的端口始终为零。
Program:程序:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost().Run();
}
public static IWebHost BuildWebHost() =>
WebHost.CreateDefaultBuilder()
.UseKestrel()
.UseUrls("http://127.0.0.1:0") // port zero to use random dynamic port
.UseStartup<Startup>()
.Build();
}
Later, when Configure
is called ...后来,当
Configure
被调用时......
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
HostedService.ServerAddresses = app.ServerFeatures.Get<Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature>();
... the server addresses are assigned to the HostedService.ServerAddresses
static variable as in the linked example. ...服务器地址分配给
HostedService.ServerAddresses
静态变量,如链接示例中所示。 However, ServerAddresses
contain only the loopback address with port zero: "http://127.0.0.1:0"
.但是,
ServerAddresses
仅包含端口为零的环回地址: "http://127.0.0.1:0"
。
Am I overlooking something?我是否忽略了什么? Is there a different, proper way to resolve the problem in v3.1?
在 v3.1 中是否有不同的、正确的方法来解决这个问题? How do I configure Kestrel to use a random dynamic port and determine which port it is at run-time (before any controller action takes place) with ASP.NET Core 3.1?
在 ASP.NET Core 3.1 中,如何配置 Kestrel 以使用随机动态端口并确定它在运行时(在任何控制器操作发生之前)是哪个端口?
Update更新
Here is an ugly workaround that helps determine the port.这是一个丑陋的解决方法,可帮助确定端口。 It appears that the timing or sequence of dynamic port allocation has changed.
动态端口分配的时间或顺序似乎发生了变化。 Returning from the
HostedService.StartAsync
method and reading the server address a bit later seems to be enough.从
HostedService.StartAsync
方法返回并稍后读取服务器地址似乎就足够了。 Surely there must be a better way?当然一定有更好的方法吗?
public Task StartAsync(CancellationToken cancellationToken)
{
System.Threading.Tasks.Task.Run(async () =>
{
int port = 0;
while (port == 0)
{
await System.Threading.Tasks.Task.Delay(250);
var address = ServerAddresses.Addresses.FirstOrDefault();
if (string.IsNullOrEmpty(address))
continue;
// address is always in form http://127.0.0.1:port
var pos = address.LastIndexOf(':');
if (pos > 0)
{
var portString = address.Substring(pos + 1);
port = int.Parse(portString);
}
}
// have determined the dynamic port now
});
return System.Threading.Tasks.Task.CompletedTask;
}
The reason the IHostedService method does not work is because .Net Core 3 changed when IHostedServices are executed. IHostedService 方法不起作用的原因是因为在执行 IHostedServices 时 .Net Core 3 发生了变化。 In .Net Core 2, IHostedService was executed after the host starts so the server address information was readily available.
在 .Net Core 2 中,IHostedService 在主机启动后执行,因此服务器地址信息很容易获得。 In .Net Core 3, IHostedService runs after the host is built, but before the host starts up and the address is not yet available.
在 .Net Core 3 中,IHostedService 在主机构建之后运行,但在主机启动之前且地址尚不可用时运行。 This blog has a nice explanation of what changed.
这个博客很好地解释了发生了什么变化。
The following method of getting the bound address, copied from here , works in both .Net Core 2 & 3.以下获取绑定地址的方法(从此处复制)适用于 .Net Core 2 和 3。
You can call IWebHost.Start()
instead of IWebHost.Run()
as suggested here .您可以按照此处的建议调用
IWebHost.Start()
而不是IWebHost.Run()
。 This will allow execution of your Main
method to continue so you can get the desired information from IWebHost.ServerFeatures
.这将允许您继续执行
Main
方法,以便您可以从IWebHost.ServerFeatures
获取所需的信息。 Just remember, your application will shutdown immediately unless you explicitly tell it not to using IWebHost.WaitForShutdown()
.请记住,您的应用程序将立即关闭,除非您明确告诉它不要使用
IWebHost.WaitForShutdown()
。
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseStartup<Startup>()
.UseUrls("http://*:0") // This enables binding to random port
.Build();
host.Start();
foreach(var address in host.ServerFeatures.Get<IServerAddressesFeature>().Addresses)
{
var uri = new Uri(address);
var port = uri.Port;
Console.WriteLine($"Bound to port: {port}");
}
//Tell the host to block the thread just as host.Run() would have.
host.WaitForShutdown();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.