部署ASP.NET Core MVC 2无法覆盖mysite.dll的问题咨询
为什么MVC5可以直接替换,Core却不行?
在ASP.NET MVC 5(基于.NET Framework)中,IIS默认启用了**影子复制(Shadow Copy)**机制:当应用启动时,IIS会把bin目录下的程序集复制到一个临时目录,然后从临时目录加载这些文件。这意味着原bin目录下的DLL文件不会被进程锁定,你可以直接通过FTP替换,下次应用回收或重启时就会加载新的文件。
而ASP.NET Core默认使用**进程内托管(InProcess)**模式:此时IIS工作进程(w3wp.exe)直接加载Core应用的DLL文件,没有影子复制的保护,文件会被进程持续锁定,自然无法直接替换。即使你用进程外托管(OutOfProcess)模式,Core应用运行在独立的Kestrel进程中,DLL同样会被该进程锁定,除非进程停止。
如何实现像MVC5那样直接FTP上传更新?
这里有几个针对性的方案,按复杂度从低到高排列:
1. 启用Core应用的影子复制
在项目的web.config中,修改aspNetCore节点,添加shadowCopyBinAssemblies="true"配置:
<aspNetCore processPath="dotnet" arguments=".\YourApp.dll" hostingModel="InProcess" shadowCopyBinAssemblies="true" />
启用后,IIS会将bin目录的文件复制到临时目录加载,原文件就可以自由替换了。注意这个配置仅适用于InProcess托管模式。
2. 切换到OutOfProcess托管模式
修改web.config中的hostingModel为OutOfProcess:
<aspNetCore processPath="dotnet" arguments=".\YourApp.dll" hostingModel="OutOfProcess" />
这种模式下,Core应用运行在独立的Kestrel进程中。你可以在上传DLL前,先回收对应的IIS应用程序池(或者停止站点),上传完成后再启动站点/回收池,IIS会自动重启Kestrel进程并加载新的DLL。相比InProcess,这种方式的文件锁定问题更容易通过常规IIS操作解决。
3. 使用IIS应用程序池回收替代停止站点
不需要完全停止站点,而是在上传DLL前,先手动回收应用程序池:
- 打开IIS管理器,找到目标应用的应用程序池
- 右键选择“回收”,等待几秒让旧进程释放文件
- 此时FTP上传新DLL就不会被锁定,新的请求会自动加载更新后的程序集
你也可以把这个步骤做成自动化脚本(比如PowerShell),减少手动操作的麻烦。
其他可行的解决方法
- 使用Web Deploy替代FTP:Web Deploy是微软官方的部署工具,支持增量部署、自动回收应用池、文件同步等功能,比FTP更可靠,还能避免手动操作的失误。
- 蓝绿部署/部署槽:如果你的服务器支持,可以创建两个部署槽(比如“蓝”和“绿”),在其中一个槽部署更新,验证无误后切换流量到新槽,实现零停机更新。不过这个方案对服务器配置有一定要求。
内容的提问来源于stack exchange,提问作者niico

