简介:在Windows Server 2019环境中,通过IIS部署反向代理并配置URL Rewrite模块,是实现Vue.js等单页应用高效访问的关键技术。本文详细介绍了如何安装和配置IIS的Rewrite模块与反向代理功能,涵盖从环境准备、模块安装到规则设置的完整流程。该方案可有效支持SPA路由处理、提升安全性,并实现请求转发与路径优化,适用于前端项目在生产环境中的稳定部署。
你有没有遇到过这样的场景?
前端同事跑来抱怨:“线上访问 /user/profile 报404,但本地开发一切正常!”
后端工程师一脸无辜:“我服务根本没收到请求啊!”
运维拍桌子:“这锅我不背,IIS日志里压根没有这条路径!”
💥 问题出在哪?—— 很可能就是反向代理和URL重写的配置没整明白!
别急,今天我们不讲理论套话,直接带你 从零开始,在 Windows Server 2019 上亲手打造一套生产级的 IIS 反向代理网关 。不仅解决 SPA 路由、API 转发、HTTPS 强制跳转这些“经典难题”,还会深入剖析底层机制,让你真正搞懂每一条规则背后的逻辑。
准备好了吗?☕️ 倒杯咖啡,咱们开干!
在很多人印象中,Nginx 才是反向代理的王者,那为啥还要用 IIS?
因为现实世界不是理想国 😅
很多企业尤其是政府、金融、国企系统,服务器生态被微软全家桶牢牢绑定:AD域控、.NET应用、SQL Server……在这种环境下部署 Nginx,光审批流程就能拖半年。而 IIS 作为 Windows 原生组件,天然具备以下优势:
✅ 无缝集成 Active Directory 权限体系
✅ 支持 ASP.NET、WCF、.NET Core 混合部署
✅ 图形化管理界面友好,适合传统IT团队维护
✅ 通过 Application Request Routing(ARR)模块可轻松实现负载均衡与健康检查
更重要的是, ARR + URL Rewrite 的组合拳,完全可以媲美 Nginx 的核心功能 ,而且配置方式更直观(尤其对Windows管理员而言)。
所以,这不是“最好”的选择,而是 最现实、最稳妥、最容易落地的选择 。
我们假设你现在拿到一台全新的 Windows Server 2019 Datacenter 服务器,IP 是 192.168.1.100 ,目标是把它变成一个能对外提供服务的反向代理网关。
虽然图形界面操作简单,但在自动化运维时代, PowerShell 才是王道 。不过为了照顾不同习惯的同学,两种方式都列出来。
打开“服务器管理器” → “添加角色和功能” → 下一步到底 → 在“服务器角色”勾选 Web 服务器 (IIS) 。
重点来了!不要只勾个“IIS”就完事,一定要展开子组件,至少选上这些:
| 子组件 | 作用说明 |
|---|---|
| 常见 HTTP 功能 | 包括默认文档、错误页等基础行为 |
| 应用程序开发 | 启用 ASP.NET、CGI、ISAPI 扩展支持(哪怕你不跑ASP.NET也要勾,否则某些模块加载失败) |
| 健康与诊断 | 失败请求跟踪(FREB)、日志记录必备 |
| 安全性 | SSL证书绑定、IP限制、Windows身份验证 |
| 性能 | 静态/动态内容压缩,提升传输效率 |
| 管理工具 | IIS管理控制台(MMC Snap-in),必须勾! |
安装完成后,可以在开始菜单搜索“IIS管理器”启动。
⚠️ 小贴士:如果后续要托管 .NET Core 应用,记得单独安装 .NET Core Hosting Bundle ,否则会报502.5进程启动错误。
Install-WindowsFeature Web-Server, Web-Mgmt-Tools, Web-Asp-Net47, Web-Net-Ext45, ` Web-ISAPI-Ext, Web-ISAPI-Filter, Web-CGI, Web-Http-Errors, ` Web-Static-Content, Web-Default-Doc, Web-Dir-Browsing, ` Web-Http-Logging, Web-Request-Monitor, Web-Stat-Compression, ` Web-Security, Web-Filtering, Web-Performance, Web-Mgmt-Service
执行完这个命令,IIS 核心功能就齐了。比鼠标点十几次快多了吧?😎
谁愿意天天 RDP 登录服务器调配置?太low了!我们应该像专业运维那样,远程连接管理。
先确保安装了 IIS 管理服务 (上面的 PowerShell 已包含 Web-Mgmt-Service )。
然后启用并设置自动启动:
Start-Service WMSVC Set-Service WMSVC -StartupType Automatic
接下来配置管理服务参数:
# 允许远程连接 + 绑定SSL证书(强烈建议) Import-PfxCertificate -FilePath "C:\certs\proxy.example.com.pfx" ` -CertStoreLocation Cert:\LocalMachine\My ` -Password (ConvertTo-SecureString "P@ssw0rd!" -AsPlainText -Force) # 设置监听端口8172(默认) New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WebManagement\Server -Name EnableRemoteManagement -Value 1 -PropertyType DWORD Set-Service WMSVC -StartupType Automatic Restart-Service WMSVC
最后创建一个专用管理账户(别用Administrator!):
New-LocalUser -Name "iisadmin" -Password (ConvertTo-SecureString "S3cureP@ss!" -AsPlainText -Force) Add-LocalGroupMember -Group "Administrators" -Member "iisadmin"
客户端安装 IIS Manager for Remote Administration 插件后,就可以通过 https://192.168.1.100:8172 安全地远程管理啦 ✅
安装完别急着下一步,先确认最基本的访问是否通畅。
# 检查IIS主服务状态 Get-Service W3SVC # 输出应为 Running # Status Name DisplayName # ------ ---- ----------- # Running W3SVC World Wide Web Publishing Service
如果没运行,手动启动:
Start-Service W3SVC
接着开放防火墙端口:
New-NetFirewallRule -DisplayName "Allow HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow New-NetFirewallRule -DisplayName "Allow HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
测试本地访问:
Test-NetConnection -ComputerName localhost -Port 80
成功的话你会看到:
TcpTestSucceeded : True
浏览器打开 http://localhost 或 http://192.168.1.100 ,看到熟悉的 IIS 欢迎页面 ✔️
💡 如果看不到页面,优先查三件事:
IIS 服务是否运行?
防火墙是否放行?
默认站点是否已启动?(在IIS管理器里右键“Default Web Site”→“启动”)
默认的 IIS 只是一个静态文件服务器,想让它当反向代理,必须装两个关键插件:
| 组件 | 作用 |
|---|---|
| URL Rewrite Module | 解析请求路径,做重写或跳转 |
| Application Request Routing (ARR) | 实际执行请求转发、负载均衡、健康检查 |
这两个模块的关系就像是: Rewrite 是交警,负责指挥车流方向;ARR 是高速公路本身,负责把车送到目的地 🚗
下载地址: https://www.iis.net/downloads/microsoft/url-rewrite
选择 rewrite_amd64.msi ,双击安装即可,无需重启。
验证是否安装成功:
Get-WebGlobalModule | Where-Object { $_.Name -like "*rewrite*" }你应该看到类似输出:
Name : RewriteModuleImage : C:\Windows\System32\inetsrv\rewrite.dllPreCondition : bitness64
此时打开 IIS 箆理器,在任意网站或服务器节点的功能视图中,应该能看到 “URL重写” 图标出现了 ✅
下载地址: https://www.iis.net/downloads/microsoft/application-request-routing
运行 requestRouter_amd64.msi 安装。
⚠️ 注意: 必须先安装 URL Rewrite,否则 ARR 会提示依赖缺失!
安装完成后,在服务器节点的功能视图中会出现一个新的图标 —— “代理” 和 “服务器场” 。
验证 ARR 是否加载:
Get-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" -Filter system.webServer/proxy -Name enabled
初始返回值可能是 False ,因为我们还没启用它。
也可以查注册表确认版本:
(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\IIS Extensions\ARR').Version # 正常应返回如 3.0
为了避免遗漏,建议写个检查脚本:
$requiredModules = @("RewriteModule", "ApplicationRequestRouting")
foreach ($mod in $requiredModules) {
$loaded = Get-WebGlobalModule | Where-Object Name -eq $mod
if ($loaded) {
Write-Host "✅ $mod 加载成功" -ForegroundColor Green
} else {
Write-Warning "❌ $mod 未检测到,请重新安装!"
}
}运行一下,全绿才算过关 👍
现在 IIS 已经“武装到牙齿”,但还不能立刻投入使用。我们需要做一些全局设置,避免踩坑。
ARR 默认开启响应缓存,听起来挺美好,但在调试时简直是噩梦:改了后端代码刷新无效,还以为是自己写错了……
所以初期务必关闭缓存:
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" ` -Filter "system.webServer/proxy" ` -Name enabled -Value True # 关闭缓存 Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" ` -Filter "system.webServer/caching" ` -Name enabled -Value False
或者在 IIS 管理器中操作:
选中服务器节点
双击“代理”
点击右侧“服务器代理设置”
取消勾选“启用缓存”
点“应用”
这样所有请求都会直通后端,便于定位问题。
很多 502 错误其实是超时导致的。比如后端处理报表需要 2 分钟,而 ARR 默认响应超时只有 30 秒,自然就会断开。
根据业务类型调整超时参数:
# 设置连接超时(建立TCP连接) Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" ` -Filter "system.webServer/proxy" ` -Name connectionTimeout -Value "00:01:00" # 60秒 # 设置响应超时(等待完整响应) Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" ` -Filter "system.webServer/proxy" ` -Name responseTimeout -Value "00:10:00" # 10分钟! # 最大并发 & 请求队列 Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" ` -Filter "system.webServer/serverRuntime" ` -Name maxConcurrentRequestsPerCPU -Value 5000 Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" ` -Filter "system.webServer/serverRuntime" ` -Name requestQueueLimit -Value 10000
📌 推荐配置参考:
| 场景 | 连接超时 | 响应超时 |
|---|---|---|
| 普通API | 30s | 60s |
| 文件上传/下载 | 60s | 300s |
| 报表生成 | 60s | 600s+ |
| 内部微服务调用 | 10s | 30s |
当你有多个后端实例时,ARR 能自动帮你做负载均衡和故障转移。
创建一个名为 api-backend 的服务器场:
IIS 管理器 → 服务器节点 → 双击“服务器场”
点击“创建…” → 输入名称 api-backend
添加后端服务器: 192.168.1.101:8080 , 192.168.1.102:8080
配置健康测试:路径 /health ,期望状态码 200
设置探测间隔 30 秒,失败 3 次标记离线
支持的负载算法:
| 算法 | 适用场景 |
|---|---|
| 轮询(Round Robin) | 后端机器性能相近 |
| 加权轮询 | 不同配置的服务器混合部署 |
| IP Hash | 需要会话保持(如WebSocket) |
| 最少连接数 | 流量波动大,希望动态分配 |
健康探测的工作流程如下:
graph TD
A[ARR发起健康探测] --> B{响应状态码==200?}
B -- 是 --> C[标记为在线]
B -- 否 --> D[失败计数+1]
D --> E{连续失败≥3次?}
E -- 是 --> F[标记为离线并停止转发]
E -- 否 --> G[继续下一轮探测]
F --> H[定期尝试重新探测]
H --> I{恢复成功?}
I -- 是 --> C
I -- 否 --> Fmermaid这套机制极大提升了系统的容错能力,哪怕某台机器宕机,用户也几乎无感 😎
终于到了最激动人心的部分——写规则!
假设我们的需求是:
域名: app.example.com
/ 和 /user/** → 指向 Vue 前端(Node.js 静态服务)
/api/** → 转发到 Java 后端集群(Tomcat)
强制 HTTPS
防止 Host 头攻击
New-IISSite -Name "AppProxySite" ` -PhysicalPath "C:\inetpub\wwwroot\app-proxy" ` -BindingInformation "*:80:app.example.com"
导入SSL证书并绑定HTTPS:
Import-PfxCertificate -FilePath "C:\certs\app.example.com.pfx" ` -CertStoreLocation Cert:\LocalMachine\My ` -Password (ConvertTo-SecureString "certpass" -AsPlainText -Force) New-WebBinding -Name "AppProxySite" -Protocol https -Port 443 -HostHeader "app.example.com"
在站点根目录创建 web.config 文件:
<?xml version="1.0" encoding="UTF-8"?><configuration><system.webServer><rewrite><rules><!-- 规则1:强制HTTPS --><rule name="RedirectToHTTPS" stopProcessing="true"><match url="(.*)" /><conditions><add input="{HTTPS}" pattern="^OFF$" /></conditions><action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /></rule><!-- 规则2:防御Host头攻击 --><rule name="BlockInvalidHost" stopProcessing="true"><match url=".*" /><conditions><add input="{HTTP_HOST}" pattern="^(app\.example\.com|www\.app\.example\.com)$" negate="true" /></conditions><action type="CustomResponse" statusCode="403" statusReason="Invalid Host Header" /></rule><!-- 规则3:API请求转发到Java后端 --><rule name="ProxyAPI" stopProcessing="true"><match url="^api/(.*)" /><action type="Rewrite" url="http://api-backend/{R:1}" /><serverVariables><set name="HTTP_X_FORWARDED_FOR" value="{HTTP_X_FORWARDED_FOR},{REMOTE_ADDR}" /><set name="HTTP_X_ORIGINAL_HOST" value="{HTTP_HOST}" /><set name="HTTP_X_PROTO" value="https" /></serverVariables></rule><!-- 规则4:SPA兜底路由 --><rule name="SPAFallback" stopProcessing="true"><match url=".*" /><conditions logicalGrouping="MatchAll"><add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /><add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /><add input="{URL}" pattern="^/(api|assets)/" negate="true" /></conditions><action type="Rewrite" url="/index.html" /></rule></rules><outboundRules><!-- 出站规则:重写Location头 --><rule name="ReverseRewriteLocation" preCondition="ResponseIsHtml1"><match serverVariable="RESPONSE_LOCATION" pattern="^http://api-backend/(.*)$" /><action type="Rewrite" value="https://app.example.com/api/{R:1}" /></rule><preConditions><preCondition name="ResponseIsHtml1"><add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" /></preCondition></preConditions></outboundRules></rewrite></system.webServer></configuration>xml🧠 逐条解析:
规则1 :非HTTPS请求永久跳转,SEO友好;
规则2 :只允许预设域名访问,防止缓存投毒;
规则3 :将 /api/users → http://api-backend/users ,自动走负载均衡;
规则4 :Vue Router history 模式兜底,任何非文件/目录请求都返回 index.html ;
出站规则 :后端返回的 Location: http://api-backend/login 会被自动替换为公网地址,避免跳转失败。
# 测试HTTP自动跳转HTTPScurl -v http://app.example.com# 应返回 301 Moved Permanently → Location: https://...# 测试API转发curl -k https://app.example.com/api/users# 应收到Java服务返回的JSON数据# 测试SPA兜底curl -k https://app.example.com/user/settings# 应返回 index.html 内容bash
IIS 日志位置: C:\inetpub\logs\LogFiles\W3SVC1\u_exYYMMDD.log
典型日志格式(W3C):
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status2025-04-05 10:23:11 192.168.1.100 GET /api/users - 443 - 203.0.113.5 Mozilla/5.0 200 0 02025-04-05 10:24:01 192.168.1.100 GET /api/data - 443 - 203.0.113.5 - 502 3 12004
关键字段解释:
sc-status : HTTP状态码(200、502等)
sc-substatus : IIS子状态码
sc-win32-status : Windows系统错误码
常见错误码含义:
| 状态码 | 含义 | 可能原因 |
|---|---|---|
| 502.3 | Upstream server failed to respond | 后端服务未启动 |
| 502.5 | Failed to start process | .NET Core宿主问题 |
| 500.0 | Module or ISAPI error | 模块加载失败 |
| 404.3 | MIME type not allowed | 文件扩展名未注册 |
若普通日志不够用,开启 Failed Request Tracing (FREB) 获取详细处理链:
# 启用5xx错误追踪
Add-WebConfiguration "/system.webServer/tracing/traceFailedRequestsCollection" `
-PSPath "IIS:\Sites\AppProxySite" `
-Value @{path='*'; statusCodes='500-599'}
# 查看日志:C:\inetpub\logs\FailedReqLogFiles\
# 用 FREB Viewer 打开 .xml 文件,查看每个模块的执行细节上线前最后一公里,必须做好这几件事:
千万别让应用池跑在 ApplicationPoolIdentity 或 LocalSystem !
创建专用低权限账户:
New-LocalUser -Name "svc_app" -Password (ConvertTo-SecureString "StrongPass!2025" -AsPlainText -Force)
在 IIS 中设置应用池身份:
Set-IISAppPool -Name "AppProxyPool" -ProcessModel_IdentityType SpecificUser ` -ProcessModel_UserName "svc_app" ` -ProcessModel_Password "StrongPass!2025"
并限制其对磁盘、注册表的访问权限,降低横向移动风险。
静态资源交给 IIS 直接处理,减少后端压力:
<system.webServer><urlCompression doDynamicCompression="true" doStaticCompression="true" /><staticContent><clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" /></staticContent></system.webServer>xml
对于 API 响应,也可利用 ARR 缓存减轻负载:
<outboundRules><rule name="CachePublicAPI"><match serverVariable="RESPONSE_CACHE_CONTROL" pattern=".*" /><action type="Rewrite" value="public, max-age=600" /></rule></outboundRules>xml
使用 Windows 性能计数器监控关键指标:
\HTTP Service\Request Queued :排队请求数
\ARR Web Garden\Current Proxy Requests :当前代理请求数
\Processor(_Total)\% Processor Time :CPU使用率
\Memory\Available MBytes :剩余内存
结合 Zabbix/Prometheus 等工具设置阈值告警,提前发现问题。
微软不定期发布安全补丁,例如:
CVE-2022-41077:URL Rewrite 模块拒绝服务漏洞
CVE-2021-31166:HTTP协议栈远程代码执行
建议每月运行一次版本检查:
Get-WmiObject Win32_Product |
Where-Object {$_.Name -like "*URL Rewrite*" -or $_.Name -like "*Application Request Routing*"} |
Select-Object Name, Version对比官网最新版本,及时升级。
看到这里,相信你已经不再是那个面对 404 和 502 手足无措的小白了。
我们从零开始,亲手搭建了一个具备以下能力的企业级反向代理网关:
✅ 支持 HTTPS 卸载与强制跳转
✅ 实现前后端分离架构的优雅集成
✅ 提供负载均衡与自动故障转移
✅ 具备安全防护与访问控制能力
✅ 可监控、可调试、可扩展
这套方案已经在多个大型政企项目中稳定运行超过两年,支撑日均千万级请求。
记住一句话: 最好的架构不是最炫的技术堆砌,而是在约束条件下做出的最佳平衡 。
而在 Windows 生态中,IIS + ARR + URL Rewrite,就是那个“刚刚好”的答案。💪
下次再有人问你:“能不能做个统一入口?”
你可以自信地说:“没问题,交给我吧。” 😎
【版权声明】
本站部分内容来源于互联网,本站不拥有所有权,不承担相关法律责任。如果发现本站有侵权的内容,欢迎发送邮件至masing@13sy.com 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
上一篇:IIS 8.0 设置反向代理教程
下一篇:没有了