Asp.net core 发布部署模式的选择

前言

之前写代码的时候光顾着业务逻辑代码的编写,对ASP.net core的发布和部署基本上没去了解,对于部署模式的态度都是能跑起来就行,这段时间有空了打算认真把这个坑踩一下。
看了一下微软自家的说明文档,每个字都认识,但就是看不懂是什么意思。独立发布、框架依赖、IIS、Kestrel、Nginx,一堆选择实在搞得有点晕头转向。

选择流程

正如微软的文档说到,我们部署一个ASP.net core项目确实需要根据我们的应用类型或部署环境选择相应的部署模式。
选择的过程分两步走。第一,选择部署模式。第二,选择托管宿主。下面将展开说明。

部署模式选择

独立发布 VS 框架依赖

ASP.net Core目前部署模式有三种,独立发布(SCD)、框架依赖(FDD)、依赖框架的可执行文件(FDE)。其中FDD和FDE差别不大,这里不做讨论,有兴趣可以看看官方的文档。
https://docs.microsoft.com/zh-cn/dotnet/core/deploying/

独立发布

独立部署。 与 FDD 不同,独立部署 (SCD) 不依赖目标系统上存在的共享组件。 所有组件(包括 .NET Core 库和 .NET Core 运行时)都包含在应用程序中,并且独立于其他 .NET Core 应用程序。

框架依赖

依赖框架的部署。 顾名思义,依赖框架的部署 (FDD) 依赖目标系统上存在共享系统级版本的 .NET Core。 由于已存在 .NET Core,因此应用在 .NET Core 安装程序间也是可移植的。 应用仅包含其自己的代码和任何位于 .NET Core 库外的第三方依赖项。

如何选择

简单的说框架依赖和独立发布的区别就是装不装 .Net core运行时的区别。装上运行时之后,很多.net core的库都能共用,否则就需要另外打包进去,所以独立发布的程序体积会比框架依赖大得多。本人以ASP.net core默认样板应用实测,独立发布的大小约为100M,框架依赖的大小约为5M。
在这里插入图片描述
独立发布的话不需要安装.net core的运行时,而框架依赖则需要安装.net core 运行时或者直接安装SDK。
所以,重点来了。如果你的服务器平时都是跑其他程序,只是偶尔情况特殊需要跑几个ASP.net core,那么推荐你使用独立发布模式。如果你的服务器打算跑多个ASP.net core程序,并且将来也打算以ASP.net core作为技术路线,框架依赖是你最好的选择。
这里以Windows下 .Net Core 2.2为例,.net core 运行时仅89M。所以,如果跑两个以上ASP.net core或者想省事的同学,请直接选择安装框架依赖,省地又省事。
对于Linux,和上文的Windows一样,有个地方要注意的是,如果你选择的是独立发布,没有装.net core 运行时的话,那么就不能用dotnet xxx.dll 这个命令来运行程序了,就要cd 到程序目录然后 ./ xxx ,xxx是你输出的文件名。

托管宿主选择

IIS VS Kestrel VS Windows服务

选择好部署模式之后就该考虑选择托管宿主,托管宿主的选择体现在ASP.net core应用中的Program.cs,在 CreateWebHostBuilder 方法中可以选择UseIIS或者UseKestrel。
根据微软的文档,我们在Windows系统下有3种托管选择:IIS、Kestrel、Windows服务。首先,Windows服务实质上也是用Kerstrel,但是跑在服务里可以做到开机自启;同样的功能IIS也能做到。选择托管宿主在代码上怎么体现?下面会上代码说明。这里我们现在讨论一下不同情况下该怎么选宿主。
因为Windows服务实质上也是Kerstrel(亲测UseIIS根本跑不起来)。所以这里先讨论IIS和Kerstrel的区别。这里先借鉴一下这位大佬的文章,里面详细地对比了IIS和Kestrel的性能区别。
https://www.cnblogs.com/savorboard/p/dotnet-benchmarks.html#asp.net-core-vs-asp.net-corekestrel-vs-iis
首先,Kestrel的性能比IIS好这个是铁打的事实,但是Kestrel它没有反向代理的功能,简单的说,就是它做不到一个端口映射多个应用,假如它绑了443端口做https,其它应用就不能用443端口,而在IIS中,一个443端口绑多个应用可以说是基本操作。
所以,一般部署在外网的应用不会只使用Kestrel,而是会添加一个IIS、Nginx或者Apache作为反向代理,首先Kestrel部署在其他端口(假设为8081)上,Nginx监听443端口,收到请求后根据请求的域名区分它是请求哪个应用,再转发到对应的端口(8081)上处理。
在这里插入图片描述
这样就会产生一个很尴尬的现象,性能就变成了由反向代理或者Kestrel中最慢的一个来决定。假如我使用IIS作为反向代理,不管你Kestrel性能有多强悍,还不是要被IIS卡住?那为什么我不直接用IIS呢?还省了一步转发。
另外,Kestrel本质上是一个控制台应用,要是遇到特殊情况挂掉了那就真的挂掉了,不会开机自启,也不会自行重启,当然也可以把它部署在Windows服务里用看门狗监控它重启,而在IIS中就不需要理这些东西。
所以,我们选择宿主不能迷信性能,还要结合使用场景进行选择。
那么现在重点来了,如果你的应用部署内网,用IP+端口进行访问,那么选Kestrel就对了,为了让它运行得更稳定,可以把它部署在Windows服务里。如果你的应用是部署在外网,靠域名来访问,而且服务器上不止跑一个应用,那么就推荐使用Kestrel + 反向代理的操作。但是如果你的反向代理是用IIS的话,还是推荐你使用IIS作为宿主,另外在程序里配上InProcess模式,InProcess模式仅在使用IIS时才有用,可以提升一定的性能。所以,如果你的服务器上已经用IIS跑了一些应用,为了降低维护的复杂度就不要再搞那么多花里胡哨的东西,老老实实用回IIS,讲道理IIS性能也不差。
另外,这里选择反向代理,推荐使用Nginx。
宿主选择代码实现。

    public class Program
    {
        public static void Main(string[] args)
        {
            string runMode = "Kestrel"; //"IIS" "Kestrel" "Service"
            if (runMode == "Service")
            {
                var isService = !(Debugger.IsAttached || args.Contains("--console"));
                
                if (isService)
                {
                    var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
                    var pathToContentRoot = Path.GetDirectoryName(pathToExe);
                    Directory.SetCurrentDirectory(pathToContentRoot);
                }
                
                var builder = CreateWebHostBuilder(args.Where(arg => arg != "--console").ToArray());
                var host = builder.Build();
                
                if (isService)
                {
                    host.RunAsService();
                }
                else
                {
                    host.Run();
                }
            }
            else
            {
                CreateWebHostBuilder(args).Build().Run();
            }
        }
        
        public static IWebHostBuilder CreateWebHostBuilder(string[] args)
        {
            IWebHostBuilder builder = null;
            string runMode = "Kestrel"; //"IIS" "Kestrel" "Service"

            if (runMode == "IIS")
            {
                builder = WebHost.CreateDefaultBuilder(args)
                    .UseIIS()
                    .UseIISIntegration()
                    .UseStartup<Startup>();
            }
            else if (runMode == "Kestrel")
            {
                builder = WebHost.CreateDefaultBuilder(args)
                    .ConfigureKestrel((context, option) =>
                    {
                        option.Listen(System.Net.IPAddress.Any, 80, (cfg) =>
                        {
                            // 根据需要使用https
                            // cfg.UseHttps(caPath,caPsd);
                        });
                    })
                    .UseKestrel()
                    .UseStartup<Startup>();
            }
            else if (runMode == "Service")
            {
                builder = WebHost.CreateDefaultBuilder(args)
                    .ConfigureLogging((hostingContext, logging) =>
                    {
                        logging.AddEventLog();
                    })
                    .ConfigureAppConfiguration((context, config) =>
                    {
                        // Configure the app here.
                    })
                    .ConfigureKestrel((context, option) =>
                    {
                        option.Listen(System.Net.IPAddress.Any, 80, (cfg) =>
                        {
                            // 根据需要使用https
                            // cfg.UseHttps(caPath,caPsd);
                        });
                    })
                    .UseKestrel()
                    .UseStartup<Startup>();
            }

            return builder;
        }
    }

这里如果选择了Kestrel+反向代理,而且反向代理已经设置了https,那么代码里千万不要再UseHttps,这样相当于进行了两次https加解密操作,亲测会损耗比较可观的性能。

操作系统相关

Windows VS Linux

众所周知,Linux上是没有IIS这种东西的,以上关于托管宿主的讨论仅针对Windows系统。对于Linux系统下,首先根据需求选择部署模式(独立 or 框架依赖),然后宿主的话只能选Kestrel。如果是内网应用就没必要装反向代理了,如果是外网应用就需要用反向代理 + Kestrel + Linux服务的操作了,Linux Service和Windows Service的作用一样,都是为了使应用开机自启。
这里放上Asp.net core在Linux上的安装教程(可选装SDK或者只装运行时)。
安装 .net core SDK
https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/install
仅安装 .net core 运行时
https://dotnet.microsoft.com/download/linux-package-manager/centos7/runtime-current
Nginx反向代理 + Kestrel + Linux Service教程
https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.2

如果这篇文章有幸能帮助到你,请不要吝啬你的赞。

参考文献
https://docs.microsoft.com/zh-cn/dotnet/core/deploying/
https://www.cnblogs.com/savorboard/p/dotnet-benchmarks.html#asp.net-core-vs-asp.net-corekestrel-vs-iis
https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/install
https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.2

发布了15 篇原创文章 · 获赞 2 · 访问量 4858

猜你喜欢

转载自blog.csdn.net/weixin_38138153/article/details/100529246
今日推荐