×

.NET 应用部署 Windows Server 避坑指南:全面驯服 IIS 网关

独孤求败 独孤求败 发表于2026-07-03 09:54:18 浏览26 评论0

抢沙发发表评论

.NET 应用部署到 Windows Server,绕不开 IIS。但很多人把它当成"托管容器"来用,结果配出来各种 502、500.30,跑不起来还不知道问题出在哪。

其实在 .NET Core 之后的架构里,IIS 的角色已经变了——它不再直接执行你的代码,而是一个网关。搞清楚这一点,部署问题就解决了一大半。

这篇文章说清楚 IIS 作为网关解决什么问题、怎么接入、以及真实项目里最容易踩的坑。

IIS 是什么

IIS(Internet Information Services)是微软出品的 Web 服务器,官网地址为 


https://www.iis.net
图片

在 .NET Framework 时代,IIS 通过 aspnet_isapi.dll 直接托管 ASP.NET 应用,工作进程既负责请求接收也负责代码执行。但从 .NET Core 开始,你的应用运行在独立的 Kestrel 进程中,IIS 不再直接执行业务代码,而是通过 ASP.NET Core 模块(ANCM)充当反向代理,将请求转发给 Kestrel。

所以,IIS 在 .NET 部署架构中的核心定位是网关,而非应用容器。它的价值在于:

  • TLS 终止:

     集中管理 SSL 证书,后端 Kestrel 只处理 HTTP 流量。
  • 请求分发:

     通过 URL Rewrite 和 ARR 模块,按路径或主机头将请求路由到不同后端。
  • 静态文件处理:

     CSS、JS、图片等由 IIS 直接响应,不往后端转发,效率更高。
  • 前置过滤:

     IP 黑白名单、请求大小限制等安全策略在网关层统一处理。

怎么引入

第一步:装运行时

服务器上必须安装 .NET Hosting Bundle(托管捆绑包)

下载地址:


https://dotnet.microsoft.com/zh-cn/download/dotnet
图片

注意:先装 IIS,再装 Hosting Bundle,顺序反了模块注册不上。装完建议重启。根据你的项目编译使用的.NET 版本,自行选择对应大版本下载 ,版本必须匹配,高低版本不兼容。

第二步:按需装扩展

模块
什么时候要装
URL Rewrite
需要 URL 重写/路由分发时(多服务聚合、API 版本路由)
ARR
需要负载均衡或多后端复杂分发时

大多数单站点 Web API 部署:这两个都不用装,IIS 通过 ASP.NET Core 模块直接转发即可。

装 ARR 后需手动启用代理:IIS 管理器 → 服务器节点 → Application Request Routing Cache → Server Proxy Settings → 勾选 Enable proxy。

第三步:代码配置转发头

ScreenShot_2026-07-03_095911_960.jpg

注意:如果只调用 Clear() 而不添加信任的代理 IP,.NET 的安全策略会直接忽略来自 IIS 的转发请求头,导致 RemoteIpAddress 依然停留在 127.0.0.1。

验证接入成功: IIS 建站,应用程序池的".NET CLR 版本"设为"无托管代码",访问站点能正常返回即通。

快速上手

以下示例适用于将 IIS 作为独立反向代理、配合 ARR 转发至自主运行的 Kestrel 进程的场景。

示例 1:单站点转发

IIS 站点下配置 URL 重写规则:匹配 .*,重写为 http://127.0.0.1:5000/{R:0},所有请求转发到本地 Kestrel。

示例 2:按路径路由多后端

规则示例:匹配 ^order/(.*),重写为 http://127.0.0.1:5001/api/order/{R:1}。订单、用户、商品三个服务分别监听不同端口,IIS 根据 URL 前缀分发。

示例 3:转发配置实操案例

同一台服务器上 3 个独立 API 服务(订单 5001、用户 5002、商品 5003),通过 IIS 统一暴露 https://api.yourcompany.com 。配置三条重写规则按路径前缀(/order/*、/user/*、/product/*)转发到对应后端。不需要装 ARR,URL Rewrite 就够了。后端如需识别真实 IP,参考上文转发头配置。

常见报错

错误码
原因
修复
502.5(旧版本 .NET Core 常见,现多表现为 500.30)
没装 Hosting Bundle,或装反了
装 Hosting Bundle,顺序错了重跑安装程序
500.30
运行时版本不匹配
检查服务器运行时版本与项目目标版本是否一致
500.19
web.config 格式错误
检查 system.webServer/aspNetCore 节点

几个常见的 IIS 配置问题

问题 1:IIS 无法支持 APK 文件的下载

部署 Android 应用下载站点时,IIS 默认不支持 .apk 文件的下载,访问会返回 404。原因是 IIS 的 MIME 类型列表中默认没有注册 APK 文件的 MIME 类型。

解决方法:在 IIS 管理器中找到目标网站,双击"MIME 类型",点击右侧"添加",输入扩展名 .apk,MIME 类型填 application/vnd.android.package-archive,确定即可。添加后 APK 文件就能正常下载了。

问题 2:IIS 首次访问加载慢(冷启动)

部署 ASP.NET Core 项目时,经常会遇到首次访问很慢的情况。IIS 默认的应用程序池空闲超时(Idle Time-out)为 20 分钟,如果 20 分钟没有访问,应用池就会被回收,下次访问会触发重新启动,这就是冷启动。

解决方法:打开 IIS 管理器 → 应用程序池 → 找到你的应用池 → 右键"高级设置",修改两个参数:

  • Start Mode

     设为 AlwaysRunning
  • Idle Time-out

     设为 0(永不回收)或调大(如 1440 分钟)

然后进入网站 → 高级设置 → "预加载已启用"设为 true

真正彻底解决冷启动的组合是:AlwaysRunning + 预加载启用 + 应用程序池高级设置里的"特定时间回收"(如配置在凌晨 3:00 自动回收)。这样回收会伴随自动预热,用户无感知。

适用场景

适合: Windows Server + .NET 部署,需要 SSL 集中管理、多应用路由聚合、前置安全过滤。团队有 Windows 运维能力时,IIS 是成熟稳定的方案。

不太适合: 容器化/Linux 环境、对延迟极敏感的超高并发场景、团队缺乏 Windows 运维经验。

实战建议

坑位 1:应用程序池的 .NET CLR 版本设为 v4.0

沿用 .NET Framework 习惯设为 v4.0 会导致 IIS 错误地加载旧版 CLR 运行时,白白浪费服务器内存与性能。正确做法:改为"无托管代码"。

坑位 2:转发头只 Clear() 没加信任 IP

options.KnownNetworks.Clear() 和 options.KnownProxies.Clear() 都调用后,不添加任何信任 IP,转发头中间件会因安全策略直接忽略转发头,RemoteIpAddress 拿到的仍是 127.0.0.1。修复:清空后显式添加对 Loopback 和 IPv6Loopback 的信任。

坑位 3:ARR 改写了响应头里的 Host

导致重定向地址变成内部地址、Cookie 的 Domain 异常。修复:ARR 的 Server Proxy Settings 里取消勾选 "Reverse rewrite host in response headers"。

选型建议

Windows Server + 几千 QPS 以内的中小规模部署,IIS + Kestrel 完全够用。大规模微服务(几十个服务、需精细化流量治理)则更适合 Ocelot、YARP 或服务网格,IIS 的网关能力相对有限。

总结收尾

IIS 在 .NET Core 之后是网关,不是容器。它做 TLS 终止、路由分发、静态文件,业务代码跑在 Kestrel。搞清这个分工,502 和 500 就知道从哪查了。

Windows Server 上部署 .NET 应用,别把 Kestrel 直接暴露。装好 Hosting Bundle,调对转发头和应用程序池,再顺手把 MIME 类型和冷启动配置好,IIS 能帮你省掉一堆麻烦。


群贤毕至

访客