asp.net core 2.2 已经推出了一段时间,其中的新功能允许使用新的 aspnetcoremodulev2 并在 iis 上使用 inprocess 模式进行部署,以显著提升性能。最近 azure app service 完成了这个新版模块的部署,我立即将我的博客配置到新模块上,结果却出现了问题。让我们来探讨一下原因和解决方案。
如果您不了解 InProcess 模式,简而言之,之前的 ASP.NET Core 虽然可以在 IIS 上运行,但实际上是由一个名为 AspNetCoreModule 的 IIS 模块调用 dotnet.exe 来启动 kestrel,因此进程名称实际上是 dotnet.exe。
而在 ASP.NET Core 2.2 中,引入了 InProcess 模式,可以在 IIS 自己的 w3wp 进程中运行您的应用程序。这个 InProcess 的 "In" 就是指运行在 w3wp 进程中的意思。根据官方描述,这种运行方式可以带来 400% 的性能提升。
如果有兴趣,可以查看官网的详细介绍:https://www.php.cn/link/9a8d909d7652448b2dc301613a123aab
生产环境的大爆炸
基于我对 ASP.NET Core 的了解,我开发时通常不会使用 IIS 进行测试,而是使用 kestrel 在开发环境中测试完毕后,直接通过 Azure DevOps 部署到 Azure App Service 上运行。然而,在升级到 InProcess 模式后,生产环境却崩溃了,而开发机上的 kestrel 无论如何都运行正常。
启动失败,我的整个博客网站无法访问,真是令人震惊!
故障分析
幸运的是,微软的智慧云 Azure 提供的全球独一无二的 kudu 工具可以非常方便地查看日志。日志显示:
[2018-12-26 12:06:26.5616][RD00155DB8C92A][Fatal][Microsoft.AspNetCore.Hosting.Internal.WebHost] Application startup exception System.IO.FileNotFoundException: Could not find file 'D:\Windows\system32\urlrewrite.xml'.
File name: 'D:\Windows\system32\urlrewrite.xml'
这是怎么回事?我的代码明明是访问应用根目录下的文件,为什么会跑到系统目录去?再一看启动日志:
[2018-12-26 12:06:23.7946][RD00155DB8C92A][Info][Moonglade.Web.Program] Moonglade is starting, hail Microsoft!
--------------------------------------------------------
Version: 10.0.6934.1000
Directory: D:\Windows\system32
x64Process: True
OSVersion: Microsoft Windows 10.0.14393
AppDomain: Moonglade.Web
UserName: moonglade
--------------------------------------------------------
故障代码是这段:
using (var sr = File.OpenText("urlrewrite.xml"))
{
...
}
最终发现,在 kestrel 下运行时,Environment.CurrentDirectory 指向的是应用根目录,而在 IIS 的 InProcess 模式下运行时,则指向系统目录,最终导致应用中只要间接或直接使用 Environment.CurrentDirectory 的代码,都会崩溃。
解决办法
我们可以利用 IHostingEnvironment 接口中提供的 ContentRootPath 属性来获取当前应用目录的绝对路径,这在 kestrel 和 IIS 中行为一致。我的故障代码正好位于可以访问到 IHostingEnvironment 的地方,因此进行了如下修改:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
string baseDir = env.ContentRootPath;
using (var sr = File.OpenText(Path.Combine(baseDir, "urlrewrite.xml")))
{
...
}
}
对于无法直接访问 IHostingEnvironment 且不愿意做依赖注入的地方,可以这样做:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
string baseDir = env.ContentRootPath;
...
AppDomain.CurrentDomain.SetData(Constants.AppBaseDirectory, baseDir);
}
然后在需要使用的地方通过 GetData() 即可:
var configSource = $@"{AppDomain.CurrentDomain.GetData(Constants.AppBaseDirectory)}\mailConfiguration.xml";
再次部署上线,问题成功解决!
其他注意事项
如果您在 VS 中使用 IIS 进行调试,比如这样设置的话:
会生成一个用于调试的 web.config 文件,而这个文件在默认情况下会参与您的 CI/CD 环境的编译和发布,最终导致您指定使用 release 模式编译的网站,上线后却是 debug 标记的。一定要记得手动排除这个文件。
自从 ASP.NET Core 2.2 之后,不能再理所当然地认为开发 ASP.NET Core 时是否使用 IIS 无关紧要了,确实有些东西在 IIS 和 kestrel 下的行为是不一致的。因此,建议大家如果生产环境使用 IIS,请务必在本地 IIS 上使用相同配置进行测试。
以上就是ASP.NET Core 2.2使用IIS部署要注意的路径问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号