【问题标题】:How do you configure Kestrel to use a random dynamic port and determine the port at run-time with ASP.NET Core 3.1?如何将 Kestrel 配置为使用随机动态端口并在运行时使用 ASP.NET Core 3.1 确定端口?
【发布时间】:2019-12-06 12:59:08
【问题描述】:

有了 ASP.NET Core 3.0,我已经能够使用这个IHostedService 方法...

Determine port Kestrel binded to

...在运行时确定 Kestrel 的动态端口。

IServerAddressesFeature 在此处记录了 ASP.NET 3.0:

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.server.features.iserveraddressesfeature?view=aspnetcore-3.0

但是当将版本更改为 ASP.NET Core 3.1 时,页面会重定向回 ASP.NET 3.0,并提示该文档不适用于 ASP.NET Core 3.1。 IServerAddressesFeature 不再工作了吗?在 ASP.NET Core 3.1 中使用 IServerAddressesFeature 仍然可以编译,但返回的 ServerAddresses 中的端口始终为零。

程序:

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();
}

稍后,当Configure 被调用时...

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        HostedService.ServerAddresses = app.ServerFeatures.Get<Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature>();

...服务器地址分配给HostedService.ServerAddresses静态变量,如链接示例中所示。但是,ServerAddresses 仅包含端口为零的环回地址:"http://127.0.0.1:0"

我是否忽略了什么?是否有不同的、正确的方法来解决 v3.1 中的问题?如何使用 ASP.NET Core 3.1 将 Kestrel 配置为使用随机动态端口并确定它在运行时(在任何控制器操作发生之前)是哪个端口?

更新

这是一个有助于确定端口的丑陋解决方法。动态端口分配的时间或顺序似乎发生了变化。从HostedService.StartAsync 方法返回并稍后读取服务器地址似乎就足够了。肯定有更好的方法吗?

        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;
        }

【问题讨论】:

    标签: c# asp.net-core asp.net-core-3.1


    【解决方案1】:

    IHostedService 方法不起作用的原因是因为 .Net Core 3 在执行 IHostedServices 时发生了变化。在 .Net Core 2 中,IHostedService 在主机启动后执行,因此服务器地址信息随时可用。在 .Net Core 3 中,IHostedService 在主机构建之后运行,但在主机启动之前并且地址尚不可用。 This blog 很好地解释了变化。

    here 复制的以下获取绑定地址的方法适用于.Net Core 2 和3。

    您可以按照建议的here 调用IWebHost.Start() 而不是IWebHost.Run()。这将允许您继续执行您的Main 方法,以便您可以从IWebHost.ServerFeatures 获得所需的信息。请记住,除非您明确告诉它不要使用 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();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-22
      • 1970-01-01
      • 1970-01-01
      • 2020-05-20
      • 2018-02-27
      • 1970-01-01
      • 2017-12-25
      相关资源
      最近更新 更多