- A+
前言
.NET在跨平台后对于应用的部署而言,不在像.NET Framework的时候那么单一化了,一个.NET Core应用的部署工作就可以涉及到很多知识点。
就对于windows而言,我们可以选择使用IIS和Kestrel作为我们的Web服务器。既可以把网站的部署用“进程内托管”方式插入IIS管道中运行,以获得更好的性能、更好的操控性。又可以用“进程外托管”方式将IIS作为反向代理服务器将请求转发给Kestrel服务器进行处理,以获得更多的配置项和安全性。
对于Linux而言,不光需要具备基本的系统知识和操作命令,还需要了解掌握虚拟机的安装和使用。另外,还需要为部署的ASP.NET Core应用创建守护进程,以免系统在出现意外情况后,可以保证ASP.NET Core应用的正常运行。
不同的部署方式、不同的操作系统、不同的守护进程、不同的负载均衡服务器等,在安装、配置、使用上都有不同点。所以对于.NET的部署必须要有一个基本的了解和认识,并且需要对不同环境的部署具备一定的实际操作能力,我为此进行了大量的学习和总结,并撰写了一些列有关ASP.NET Core部署的文章。
- 《ASP.NET Core部署手册:部署基础知识》
- 《ASP.NET Core部署手册:Hyper-V虚拟机》
- 《ASP.NET Core部署手册:Windows篇》
- 《ASP.NET Core部署手册:注意事项和问题排查》
- 《ASP.NET Core部署手册:Linux篇》
本系列文章主要的目的是作为常规部署的操作性指南,所以无法对每个细节点逐一进行介绍,如果想要深入细节,读者可参考微软文档等资料进行综合性学习。
1.部署模式
.NET Core应用程序在发布的过程中会有两种部署模式进行选择,分别为“框架依赖”和“独立”。
如果采用“独立”模式进行发布,那么发布生成的文件不仅包含项目程序集及其依赖的程序集,还会包含.NET运行时相关的文件,促使以该模式发布的文件可以部署在没有安装.NET运行时的服务器。
如果采用“框架依赖”的模式进行发布,那么发布生成的文件只会包含项目中程序集及其依赖的程序集,以该模式部署的时候必须确保目标服务器上安装了.NET运行时。
在我看来“独立”和“框架依赖”没有好坏之分,它们各有千秋,我们需要结合实际的应用场景进行选择,下面对两种模式做一个简短的分析:
“框架依赖”:发布后文件体积相对较小,并且项目框架所依赖的运行时在安装后可以供给其他应用程序进行复用。最主要的是它可以生成用于所有操作系统平台的“可执行文件”,所以在部署上具有跨平台性,适用于一套应用部署在多个不同的操作系统。相比“独立”模式而言,不足的就是必须单独在目标服务器上安装.NET运行时。
“独立”:相比“框架依赖”而言由于自身包含了.NET运行时,所以在文件体积上大很多,但是基于这一特点,促使在部署的时候更加方便和稳定(排查兼容性问题)。由于生成的“可执行文件”是专属于某个操作系统平台的,所以如果要换其他的操作系统部署则必须重新编译发布。
PS:本系其他文章涉及到的部署方式都是所采用“框架依赖”的模式。
2.生成可执行文件
由于.NET Core是跨平台的应用,所以对于在不同的操作系统和CPU体系结构上运行都会存在一些差异性,因此.NET Core应用在发布后会生成“可执行文件”,该文件主要用于处理不同平台上运行时的差异性,该文件在发布后主要在发布目录的“runtimes”文件夹中。
对于“框架依赖”模式而言它在选择“目标运行时”时可以选择.NET支持的所有操作系统平台,也就是选择“可移植”选项,因此具备各个平台的“可执行文件”。而对于“独立”模式而言,则必须根据部署服务器的系统情况选择一个具体的“目标运行时”,因此只具备一个平台的“可执行文件”。
4.跨平台可运行程序集
.NET应用在经过生成发布的操作后,生成的程序集都是可以跨平台的,而对于启动项目的DLL程序集是直接可以通过dotnet命令,在包含了.NET运行时的任何操作系统运行。该dll文件通常与解决方案中启动名称相同(在分层的解决方案中,启动项目通常为UI层),通常在Linux系统中都是以这种方式来运行项目。
5.为什么“配置”选择Debug或Release都会又pdb文件?
通常在默认的情况下,在发布的时候不管“配置”选项选择的Debug或Release,在最后发布的文件夹中,对于每个项目都会生成一个pdb文件。这是因为“配置”选项本身和生成pdb文件是无关的,两者都是单独的设置。发布时的“配置”选项的作用主要是用于优化生成后的程序集代码,如果选择“Release”,则编译器会对代码进行优化,将部署的程序集实现更小、更快、更高效的运行,这也是为什么在进行“项目部署工作”的时候需要选择“Release”,反之如果选择Debug,那么生成的程序集将更有利于我们进行程序调式。
对于pdb文件而言,它本身记录了代码中的断点以及调式信息,专门用于我们调式程序,官方称之为“调试符号文件”。由于pdb文件的生成会增加“发布文件”的体积,所以通常情况下部署在生产环境中,pdb文件不是必须的,除非你想要远程调式代码。
如果部署项目时不需要pdb文件,推荐3种处理方式:
- 在使用“Release配置”发布项目后,在发布文件夹中人为手动删除掉pdb文件即可;
- 在VS中打开项目的属性设置,然后在左侧点击“生成”进入对于的设置页面,找到“调式符合”区域在Release对于的下拉列表中选择“未发出任何符合”,以VS2022为例如图:
- 在VS中双击项目进入项目文件配置界面,在文件中新增“DebugType”节点,如图:
6.Kestrel简介
微软为我们提供Web服务器除了IIS以外的又一个选择——Kestrel,该Web服务器会内置到我们ASP.NET Core的项目模板中,换种直接的说法就是,我们的ASP.NET Core应用自带了Web服务器。Kestrel本身可以作为面向互联网的Web服务器,直接处理客户端传入的HTTP请求。
在Kestrel中,用于托管应用程序的进程是dotnet.exe,而非以往在IIS中的w3wp.exe了。当我们使用.NET CLI命令直接运行应用程序或直接打开exe文件时,此时应用程序就已经将Kestrel作为Web服务器。
尽管Kestrel让我们的部署运行更加方便,并且跨平台、功能丰富、性能强大,且已经足以作为一个独立Web服务器使用了,但是在实际的工作项目中,我们通常不会让Kestrel作为最终的Web服务器直接处理终端用户的请求。
因为Kestrel中很多操作都需要编写代码来完成,比如配置域名证书、记录请求日志、URL重写等,而这些操作在Nginx、IIS等服务器中,都不需要我们编写代码,我们只需要修改配置文件即可完成这些任务,所以Kestrel对运维工作不太友好。
并且对于比较复杂的项目而言,为了提高系统的可用性,我们通常会加入代理服务器,由代理服务将请求转发给Kestrel,并实现负载均衡,将同样的网站部署到多台Web服务器上,由负载均衡服务器决定把用户请求转发给哪台服务器。
7.进程内托管和进程外托管
ASP.NET Core 应用在Web服务器上进行部署托管,其中划分为了两种托管模型,分别为即进程内托管(InProcess)和进程外托管(OutOfProcess)。
7.1.进程内
对于直接将ASP.NET Core 应用部署运行在IIS工作进程(w3wp.exe)或IIS Express进程(iisexpress.exe)中的方式称为进程内托管(InProcess)。 进程内托管的方式相较进程外托管提供更优的性能,因为请求并不通过环回适配器进行代理,环回适配器是一个网络接口,用于将传出的网络流量返回给同一计算机。
下图说明了 IIS、ASP.NET Core 模块和进程内托管的应用之间的关系:
7.2.进程外
对于进程外托管(OutOfProcess)的部署而言,ASP.NET Core 应用不会直接部署运行在IIS工作进程中。通常会采用两种方式,第一种是直接使用Kestrel作为Web服务器面向外部处理HTTP请求,第二种则是通过一个代理服务器(IIS、Nginx)进行请求转发,在将请求转发到Kestrel服务器进行处理。
由于运行 ASP.NET Core 的进程与 IIS 工作进程分开,因此 ASP.NET Core Module模块会负责管理ASP.NET Core应用的进程,其中包含Kestrel和应用程序。该模块在第一个请求到达时会自动启动 ASP.NET Core 应用的进程,并在应用关闭或崩溃时重新启动该应用。
7.3.配置
下面只针对IIS中如何配置这两种托管模型进行介绍,因为对于其他的Web服务而言都属于的是进程外托管这一种方式了,就谈不上配置了。
将ASP.NET Core应用部署到IIS上默认采用的是进程内的托管方式,如果想要显示的设置为托管方式,首先需要打开项目文件csproj,然后在其中加入<AspNetCoreHostingModel>标签,标签的值可设为:
- OutOfProcess(进程外)
- InProcess(进程内)
注意:如果你不使用IIS作为Web服务器,而是直接使用Kestrel或代理服务器,那么无论标签指定的值是InProcess或OutOfProcess,其运行方式都始终按照进程外托管(OutOfProcess)。
结语
在.NET开源跨平台后,应用程序发布这项工作不在比以往.NET Framework时代那么简单了,个人觉得对于应用程序发布相关的知识必须系统的学习下,并且掌握或尝试各主流操作系统下的部署技巧,这显得尤为重要。虽然所涉及的知识面广,但可以先进行粗略的全盘了解,然后在根据所处的工作实际情况,对所涉及的知识点在进行深入。