簡體   English   中英

如何配置 Kestrel 以使用隨機動態端口並在運行時使用 ASP.NET Core 3.1 確定端口?

[英]How do you configure Kestrel to use a random dynamic port and determine the port at run-time with ASP.NET Core 3.1?

使用 ASP.NET Core 3.0 我已經能夠使用這個IHostedService方法......

確定綁定到的端口 Kestrel

... 在運行時確定 Kestrel 的動態端口。

此處為 ASP.NET 3.0 記錄了IServerAddressesFeature

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

IHostedService 方法不起作用的原因是因為在執行 IHostedServices 時 .Net Core 3 發生了變化。 在 .Net Core 2 中,IHostedService 在主機啟動后執行,因此服務器地址信息很容易獲得。 在 .Net Core 3 中,IHostedService 在主機構建之后運行,但在主機啟動之前且地址尚不可用時運行。 這個博客很好地解釋了發生了什么變化。

以下獲取綁定地址的方法(從此處復制)適用於 .Net Core 2 和 3。

您可以按照此處的建議調用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();
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM