You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IIS发布ASP.NET Core应用 无需停止整站实现单应用更新

IIS单站点多子应用独立更新无锁方案

核心可行方案:ASP.NET Core 内置app-offline模式

该方案完全适配当前部署环境,不需要调整现有Jenkins+PowerShell的CI/CD流程,更新全程不需要停止根IIS站点,其他非更新子应用完全不受影响,待更新应用仅存在秒级到分钟级的可控停机时间。

操作逻辑

当需要更新指定子应用时,只需要操作该子应用对应的独立物理目录即可,不需要对IIS站点、应用池做全局停止操作:

  • 向子应用物理根目录写入命名为app_offline.htm的文件
  • ASP.NET Core Module(ANCM)检测到该文件存在后,会自动执行以下动作:
    • 立刻阻断所有发往该子应用的新请求,直接返回app_offline.htm中编写的维护提示内容
    • 等待该子应用当前正在处理的存量请求执行完成,默认等待超时为30秒
    • 直接卸载该子应用的运行实例,释放所有被占用的程序集、静态资源文件锁
  • 文件锁释放后,直接执行新版本文件的替换覆盖操作即可
  • 文件替换完成后,删除根目录下的app_offline.htm,ANCM会自动重新拉起该子应用实例,恢复请求接入

实操踩坑提示

  • app_offline.htm文件大小必须大于等于512字节,否则IIS会直接返回默认错误页,不会触发ANCM的应用卸载逻辑,可在文件中填充足够的维护提示文案、空白注释满足大小要求
  • 如果子应用存在WebSocket、长轮询这类长连接场景,写入app_offline.htm后可手动执行一次对应子应用独立应用池的回收操作,等待10-15秒即可完全释放所有文件锁,不需要停止应用池
  • 可直接将该逻辑集成到现有PowerShell发布脚本中,核心参考代码如下:
# 配置待更新子应用的物理路径
$targetAppPath = "D:\IIS_Deploy\MainSite\OrderSubApp"
$offlineFile = Join-Path $targetAppPath "app_offline.htm"

# 写入维护页触发应用卸载
$maintainPage = @"
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><title>系统维护中</title></head>
<body>
<h2>当前模块正在版本更新,预计1-2分钟后恢复访问</h2>
<p>站点其他模块可正常使用,给您带来不便敬请谅解</p>
<!-- 冗余填充内容,确保文件总大小超过512字节,避免IIS拦截不触发卸载逻辑 -->
<!-- 冗余内容省略 -->
</body>
</html>
"@
Out-File -FilePath $offlineFile -InputObject $maintainPage -Encoding utf8

# 等待实例卸载、文件锁释放
Start-Sleep -Seconds 15

# 执行原有发布逻辑:清理旧文件、拷贝新版本发布产物到$targetAppPath
# 发布逻辑省略

# 删除离线文件,恢复应用访问
Remove-Item $offlineFile -Force

之前停止应用池无法释放锁的原因

单独停止子应用对应的WebAppPool后文件仍被锁定,是因为IIS的w3wp工作进程存在默认的延迟退出机制,且应用池停止逻辑不会主动断开长连接、强制回收未释放的文件句柄,部分持锁请求会导致进程无法及时退出,文件锁会长时间保留。而app-offline模式是ANCM在托管层直接触发的应用域卸载,锁释放逻辑更精准,耗时更短,完全不会影响同站点下其他应用的运行。


内容的提问来源于stack exchange,提问作者Michael Thrift

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 04:42:36