KestrelServer

Kestrel 是一个跨平台的适用于 Kestrel。 Kestrel 是 Web 服务器,默认包括在 ASP.NET Core 项目模板中。

如何使用

可以单独使用 Kestrel,也可以将其与反向代理服务器(如 IIS、Nginx 或 Apache)结合使用。 反向代理服务器接收来自网络的 HTTP 请求,并将这些请求转发到 Kestrel。

如果你的应用只接收来自内部网络的请求,你可以只使用Kestrel本身。

Kestrel原理 kestrel iis_Kestrel原理


如果你将你的应用部署在公共网络上,我们建议你使用IIS,Nginx或者Apache作为反向代理服务器。一个反向代理服务器接收来自网络的HTTP请求并且在经过一些初步处理后将请求传递到Kestrel服务器。

在没有反向代理服务器的情况下用作边缘服务器的 Kestrel 不支持在多个进程间共享相同的 IP 和端口。 如果将 Kestrel 配置为侦听某个端口,Kestrel 会处理该端口的所有流量(无视请求的 Host 标头)。 可以共享端口的反向代理能在唯一的 IP 和端口上将请求转发至 Kestrel。

Kestrel原理 kestrel iis_json_02

即使不需要反向代理服务器,使用反向代理服务器可能也是个不错的选择。
反向代理:

  • 可以限制所承载的应用中的公开的公共外围应用。
  • 提供额外的配置和防护层。
  • 可以更好地与现有基础结构集成。
  • 简化了负载均和和安全通信 (HTTPS) 配置。 仅反向代理服务器需要 X.509 证书,并且该服务器可使用普通 HTTP 在内部网络上与应用服务器通信。

KestrelServer:

1: public class KestrelServer : IServer
   2: {   
   3:     public IFeatureCollection       Features { get; }
   4:     public KestrelServerOptions     Options { get; }
   5:  
   6:     public KestrelServer(IOptions<KestrelServerOptions> options,IApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory);
   7:     public void Dispose();
   8:     public void Start<TContext>(IHttpApplication<TContext> application);
   9: }

类型为KestrelServerOptions的只读属性Options表示对KestrelServer所作的相关设置
我们一般通过调用WebHostBuilder的扩展方法UseKestrel方法来完成对KestrelServer的注册。如下面的代码片段所示,UseKestrel方法具有两个重载,其中一个具有同一个类型为Action的参数,我们可以利用这个参数直接完成对KestrelServerOptions的设置。

1: public static class WebHostBuilderKestrelExtensions
   2: {
   3:     public static IWebHostBuilder UseKestrel(this IWebHostBuilder hostBuilder);
   4:     public static IWebHostBuilder UseKestrel(this IWebHostBuilder hostBuilder, Action<KestrelServerOptions> options);
   5: }

KestrelServerOptions

由于Server负责请求的监听、接收和响应,所以Server是影响整个Web应用响应能力和吞吐量最大的因素之一,为了更加有效地使用Server,我们往往针对具体的网络负载状况对其作针对性的设置。我们针对KestrelServer所做的设置主要体现在KestrelServerOptions类型的如下5个属性上。

1: public class KestrelServerOptions
   2: {   
   3:     //省略其他成员
   4:     public int          MaxPooledHeaders { get; set; }
   5:     public int          MaxPooledStreams { get; set; }
   6:     public bool         NoDelay { get; set; }
   7:     public TimeSpan     ShutdownTimeout { get; set; }
   8:     public int          ThreadCount { get; set; }
   9: }

设置监听地址

默认情况下,ASP.NET Core 绑定到:http://localhost:5000、https://localhost:5001(存在本地开发证书时)
IServer中定义了属性Features,它表示用于描述当前Server的特性集合,IServerAddressesFeature包含在集合中,该接口具有一个唯一的只读属性返回Server的监听地址列表。ASP.NET Core默认使用的ServerAddressesFeature是具有如下定义的同名类型。

1: public interface IServerAddressesFeature
   2: {
   3:     ICollection<string> Addresses { get; }
   4: }

对于WebHost在通过依赖注入的方式创建的Server,由它的Features属性表示的特性集合中会默认包含这么一个ServerAddressesFeature对象。如果没有一个合法的监听地址被添加到这个 ServerAddressesFeature对象的地址列表中,WebHost会将显式指定的地址(一个或者多个)添加到该列表中。我们显式指定的监听地址实际上是作为WebHost的配置保存在一个Configuration对象上,配置项对应的Key为“urls”,WebHostDefaults.ServerUrlsKey返回的就是这么一个Key。

1: new WebHostBuilder()
   2:     .UseSetting(WebHostDefaults.ServerUrlsKey, "http://localhost:3721/")
   3:     .UseMyKestrel()
   4:     .UseStartup<Startup>()
   5:     .Build()
   6:      .Run();

7种配置监听方式

  • lanuchSettings.json,使用applicationUrls属性来配置URLs,发布后无此文件,适合调试使用
  • UseUrls(),在Program.cs配置程序监听的URLs,硬编码配置监听方式,适合调试使用
  • appsettings.json中添加urls节点--"urls": "http://:9991;https://:9993"
  • appsettings.json中添加Kestrel节点
  • 环境变量,使用DOTNET_URLS或者ASPNETCORE_URLS配置URLs
  • 命令行参数,当使用命令行启动应用时,使用--urls参数指定URLs
  • KestrelServerOptions.Listen(),使用Listen()方法手动配置Kestral服务器监听的地址(此方式可以自己添加证书)

前五种都是通过添加配置urls的方式配置监听

配置监听方式案例

UseUrls()

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
                webBuilder.UseUrls("http://localhost:5003", "https://localhost:5004");
            });
}

UseUrls源码:

public static IWebHostBuilder UseUrls(this IWebHostBuilder hostBuilder, params string[] urls)
    {
        if (urls == null)
        {
            throw new ArgumentNullException(nameof(urls));
        }
 
        return hostBuilder.UseSetting(WebHostDefaults.ServerUrlsKey, string.Join(';', urls));
    }

UseSetting的作用是添加配置项,WebHostDefaults.ServerUrlsKey的值是urls

环境变量

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "profiles": {
    "CoreApi3._1": {
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:5557"
      }
    }
  }
}

设置环境变量后发现多了配置项urls

var urls = configuration["urls"]; //  http://localhost:5557

命令行

dotnet run --urls "http://localhost:5100"
dotnet run --urls "http://localhost:5100;https://localhost:5101"

KestrelServerOptions

ASP.NET Core应用默认使用Kestrel服务器。

public static IServiceCollection AddKestrelServer(this IServiceCollection services)
        {
            services.Configure<KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;//允许同步IO
                options.AddServerHeader = true;
                //http
                options.Listen(System.Net.IPAddress.Parse(endPoint.Address), endPoint.Port);
                //https
                options.Listen(System.Net.IPAddress.Parse(endPoint.Address), endPoint.Port,
                    opts =>
                    {
                        opts.UseHttps(new System.Security.Cryptography.X509Certificates.X509Certificate2("certificateFileName", "certificatePassword"));
                    });
            });
            return services;
        }

appsettings.json中添加Kestrel节点

"Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://*:9601"
      },
      "Http": {
        "Url": "http://*:9600"
      }
    }
}