跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 世界
  • 用户
  • 群组
皮肤
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(不使用皮肤)
  • 不使用皮肤
折叠

乐达

  1. 主页
  2. 软件工程
  3. IIS
  4. 深度解析:.NET Core / .NET 6+ 在 Windows IIS 下的托管机制

深度解析:.NET Core / .NET 6+ 在 Windows IIS 下的托管机制

已定时 已固定 已锁定 已移动 IIS
1 帖子 1 发布者 7 浏览 1 关注中
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • Z 离线
    Z 离线
    zhongfangxiong
    写于 最后由 编辑
    #1

    这篇文档将剥离 CI/CD 的外壳,直击运行时的核心:为什么 .NET Core 能在 IIS 上跑?它是怎么跑的?配置的关键点在哪里?


    📚 深度解析:.NET Core / .NET 6+ 在 Windows IIS 下的托管机制

    1. 核心架构:从 "Pipeline" 到 "Reverse Proxy"

    在传统的 .NET Framework (ASP.NET 4.x) 时代,IIS 深度集成 System.Web,IIS 工作进程 (w3wp.exe) 直接加载 CLR 并运行代码。

    但在 .NET Core / .NET 6+ 时代,架构发生了根本性的变化。IIS 不再直接“运行”你的代码,而是扮演了一个 反向代理 (Reverse Proxy) 的角色。

    1.1 关键组件:ASP.NET Core Module (ANCM)

    IIS 本身不懂 .NET Core。为了让它们配合,微软推出了一个名为 ASP.NET Core Module (ANCM) 的原生 IIS 模块。
    当请求到达 IIS (端口 80/443) 时,IIS 会将请求交给 ANCM,由 ANCM 负责启动和管理你的 .NET 应用程序。

    1.2 两种托管模式 (Hosting Models)

    这是配置中最关键的概念,决定了你的应用性能和运行方式。

    A. 进程内托管 (In-Process Hosting) - 默认推荐

    • 原理:.NET Core 运行时直接加载到 IIS 的工作进程 (w3wp.exe) 中。
    • 性能:极高。请求在进程内部传递,没有网络开销。
    • Web Server:使用 IISHttpServer 实现。
    • 表现:任务管理器里只有一个 w3wp.exe。

    B. 进程外托管 (Out-of-Process Hosting)

    • 原理:IIS (w3wp.exe) 仅仅是一个转发器。它启动一个独立的 dotnet.exe 进程运行你的应用(使用 Kestrel 服务器)。IIS 通过 HTTP 将请求转发给 Kestrel。
    • 性能:略低(有进程间通讯开销)。
    • 表现:任务管理器里能看到 w3wp.exe (负责转发) 和 dotnet.exe (负责业务)。
    • 场景:主要用于兼容性测试或完全隔离。

    2. 环境准备与安装细节

    要在 Windows Server 上运行 .NET 6 API,单纯复制文件是不够的。

    2.1 必须安装:Hosting Bundle

    必须下载并安装 .NET Core Hosting Bundle (托管捆绑包)。它包含三个东西:

    1. .NET Runtime (运行时,负责跑代码)
    2. ASP.NET Core Runtime (Web 库)
    3. ASP.NET Core Module v2 (关键!这是 IIS 的插件)

    弯路总结:如果我们只安装 SDK 或 Runtime,而没装 Hosting Bundle,IIS 里就没有 ANCM 模块,访问网站会直接报 HTTP 500.19 或 模块未找到。


    3. IIS 配置详解:那些“反直觉”的设置

    习惯了传统 ASP.NET 的开发者,在配置 .NET Core 站点时容易踩坑。

    3.1 应用程序池 (Application Pool) 设置

    这是最容易错的地方。

    • 配置项:.NET CLR 版本
    • 正确设置:无托管代码 (No Managed Code)
    • 原因:IIS 不需要加载旧的 .NET Framework CLR。现代 .NET 运行时由 ANCM 负责启动,IIS 只需要作为一个原生宿主。如果你选了 .NET v4.0,反而会造成不必要的资源浪费,甚至冲突。

    3.2 Web.Config 的角色转变

    在 .NET 6 中,web.config 不再负责 AppSettings(那些去 appsettings.json 了)。它的主要职责变成了配置 ANCM。

    一个标准的 .NET Core web.config 如下:

    <configuration>
      <system.webServer>
        <handlers>
          <!-- 注册 ANCM 处理器,接管所有请求 -->
          <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
        </handlers>
        <!-- 核心配置段 -->
        <aspNetCore processPath="dotnet" 
                    arguments=".\Sellers.Platform.Web.Host.dll" 
                    stdoutLogEnabled="false" 
                    stdoutLogFile=".\logs\stdout" 
                    hostingModel="inprocess" />
      </system.webServer>
    </configuration>
    
    • processPath: 指示 IIS 如何启动应用。通常是 dotnet,或者直接指向 .exe。
    • arguments: 指定启动的 DLL。
    • hostingModel: 显式指定 inprocess (进程内) 或 outofprocess (进程外)。

    4. 故障排查:当 "HTTP 500" 发生时

    IIS 报错通常很含糊(如 500.30 ANCM Startup Failure)。要看到真实的 .NET 异常,需要开启 stdout 日志。

    4.1 开启 stdout 日志

    这是调试启动崩溃的唯一手段。

    1. 打开部署目录下的 web.config。
    2. 设置 stdoutLogEnabled="true"。
    3. 确保 logs 文件夹存在(且 IIS 用户有写入权限)。
    4. 重启网站,请求一次。
    5. 查看 logs 目录下的文件,里面会包含完整的 C# 异常堆栈(比如数据库连接失败、依赖注入错误)。

    注意:生产环境务必关闭此选项,否则日志文件会无限增长填满磁盘。


    5. 我们的工作与弯路总结 (LODA.Seller 实战)

    回顾我们刚才的部署过程,其实就是在通过自动化脚本,精准地控制上述所有环节。

    5.1 我们做了什么(成功路径)

    1. 文件隔离:我们采用了按日期 (20251118) 分离的物理路径,避免了覆盖文件时的文件锁问题。
    2. 配置注入:通过 ensure-iis-config.ps1,我们自动检测服务器环境,并强制修正了 AppPool 的设置为 No Managed Code(您应该记得日志里那句 Auto-correcting StartMode...)。
    3. Web.Config 生成:我们没有完全依赖代码库里的 web.config,而是根据部署环境动态调整参数(如 processPath 指向)。
    4. 端口绑定:我们强制指定了 Staging (8062) 和 Prod (8063),确保了不同环境在同一台服务器上并行不悖。

    5.2 我们走的弯路(经验教训)

    1. 端口推断的陷阱:

      • 现象:最开始脚本试图自动分配端口,结果导致 CI 认为部署在 8062,但实际可能冲突或未生效。
      • 教训:在 servers.yml 中显式定义端口是 DevOps 的黄金法则。永远不要让脚本去“猜”配置。
    2. 健康检查的兼容性:

      • 现象:使用 Linux 思维的 curl 去检查 Windows IIS 站点,因 Shell 差异导致 HTTP 000 假死。
      • 教训:入乡随俗。在 Windows 上,PowerShell 的 Invoke-WebRequest 才是原生的王者。
    3. 文件锁死:

      • 现象:重试 Job 时,因为版本号没变,试图覆盖正在运行的 DLL,导致 Access Denied。
      • 教训:.NET Core 运行时会死死锁住 DLL。原子发布(部署到新目录 -> 切换 IIS 指向)是解决此问题的唯一完美方案。

    希望这份文档能帮助您从底层原理上理解我们的部署工作。它不仅是一个网站,更是一个精密配合的进程协作系统。

    1 条回复 最后回复
    0
    回复
    • 在新帖中回复
    登录后回复
    • 从旧到新
    • 从新到旧
    • 最多赞同


    • 登录

    • 登录或注册以进行搜索。
    • 第一个帖子
      最后一个帖子
    0
    • 版块
    • 最新
    • 标签
    • 热门
    • 世界
    • 用户
    • 群组