说实话,Windows环境下配Nginx反向代理这件事,我一开始也是拒绝的。总觉得Nginx天生是Linux的东西,在Windows上跑就是"将就"。但后来帮几个团队处理前后端分离项目、多服务聚合、以及本地联调环境时发现,Windows下用Nginx做反向代理不仅可行,而且很多时候是最省事的方案——不用装虚拟机、不用改代码、不用额外买机器,一个10MB不到的绿色软件就把入口网关、静态资源托管、接口转发全包了。这篇文章我就把从下载安装到复杂负载均衡的完整实操过程写下来,包括那些我踩过的坑,希望能帮你少走弯路。
1. 为什么我坚持在Windows环境里用Nginx做反向代理
1.1 先搞懂反向代理在替我们解决什么问题
很多人第一次听到"反向代理"这个词会觉得高大上,其实理解起来没那么玄乎。正向代理是你帮别人出去找资源,典型的就是浏览器插件代理,代理服务器代替你去访问外部网站;反向代理则是别人来找你,但你不想把真正干活的服务器直接暴露给对方,于是让一台入口服务器负责收请求,再按规则转给后面的实际服务。
举个例子,你电脑上跑着三个服务:Spring Boot后端占8080端口、Vue前端开发服务器占5173端口、MySQL占了3306。总不能让用户去记端口号吧?也总不能把后端接口直接裸奔暴露在公网上吧?通过nginx反向代理,你只需要暴露一个80端口,用户访问http://你的IP/,nginx一看路径就知道把请求转发给谁。这就相当于给整个系统装了一个"前台接待",所有请求先到前台,前台再帮你分发到对应的办公室。
我在Windows上做这个方案最大的感触是,调试特别方便。后端服务起在IDE里,前端起在Node环境里,Nginx只负责当中间人,代码改动后按一下reload配置就生效了,根本不用重新部署,联调效率高出一大截。
1.2 同类方案对比:IIS、Apache、Caddy和Nginx怎么选
在Windows上做反向代理,常见的选项不止Nginx一个,我做了一张对比表,方便你按场景选择:
| 方案 | 配置复杂度 | 性能 | Windows友好度 | 适合场景 |
|---|---|---|---|---|
| Nginx | 中等,配置语法独特 | 高,事件驱动模型 | 良好,绿色解压即用 | 绝大多数Web场景 |
| IIS + ARR | 较低,图形化界面 | 中等 | 原生支持 | 纯Windows技术栈团队 |
| Apache | 中等偏复杂 | 中低,进程模型较重 | 一般,配置路径容易坑 | 老项目迁移,兼容.htaccess |
| Caddy | 极低,自动HTTPS | 中等 | 良好 | 个人项目、快速原型 |
我个人推荐Nginx的原因有三点。第一,配置文件是纯文本,整个团队可以版本化管理,改动可追溯,这一点比图形界面友好得多;第二,Nginx的并发处理能力是这几个里最强的,Windows版虽然性能略逊于Linux版,但对中小规模项目完全够用;第三,网上关于Nginx的案例最多,你遇到的任何问题几乎都有人踩过坑,搜索就能找到答案。
1.3 这篇文章适合谁,能帮你省下多少时间
这篇文章不是写给运维大佬看的,运维大佬早就在Linux上玩出花了。我主要面向这几类人:
- 本地开发用Windows,但需要模拟生产环境的多服务部署结构做联调
- 团队交付物是前后端分离项目,需要给客户提供一个"一键启动"的演示环境
- 个人开发者有一台Windows服务器,想同时部署多个网站或应用
- 刚接触Nginx,想弄明白反向代理、负载均衡这些概念到底怎么落地
如果你属于上面任何一类,这篇文章都能让你省下大半天查文档的时间。我把从下载到配置再到排障的完整链路都走了一遍,你只需要跟着操作就行。
2. Windows下Nginx的下载、安装与自启
2.1 版本怎么选:mainline还是stable
Nginx官网下载页面一般提供两个版本线:Mainline version(主线版)和Stable version(稳定版)。很多新手看到"最新版"三个字就直接点了Mainline,然后过两天就发现某个配置指令写法变了,或者某个第三方模块兼容不了。
我的原则是,生产环境和本地演示环境一律用Stable版本,除非你需要体验新功能。在Windows上尤其要注意的是,选择版本号中带Windows字样的压缩包,例如nginx/Windows-1.24.0这种,下载下来是一个zip压缩包,解压就能用。不推荐使用Windows安装器版本,因为Nginx官方其实没有提供正式的Windows安装器,网上那些exe安装包大多是非官方封装,容易捆绑乱七八糟的东西。
2.2 解压即安装,5分钟跑起第一个站点
下载完成后,把zip包解压到一个路径中不包含中文和空格的目录,比如D:\nginx。注意我特别强调中文和空格这个问题,因为你把Nginx放在C:\Program Files\nginx或D:\工具\nginx这类路径下,后面启动时经常会遇到意料之外的问题,具体表现我后面在坑那一章细说。
解压完进入目录,你会看到这些关键文件:
D:\nginx ├─ conf │ ├─ nginx.conf # 主配置文件 │ ├─ mime.types # 文件类型映射 │ └─ ... ├─ contrib # 辅助脚本 ├─ docs # 文档 ├─ html # 默认站点目录 ├─ logs # 日志目录 ├─ temp # 临时目录 └─ nginx.exe # 主程序启动方式很简单,打开命令提示符,进入nginx目录,执行:
cd D:\nginx start nginx.exe注意是start nginx.exe而不是直接双击nginx.exe。直接双击运行时,关掉命令行窗口Nginx也会被一起关掉。用start命令可以把它作为后台进程启动。
启动后验证是否成功,打开浏览器访问http://localhost,如果看到"Welcome to nginx!"页面,说明Nginx已经跑起来了。也可以在命令行执行tasklist | findstr nginx,能看到nginx.exe进程就说明在运行。
这里有个小细节,Nginx启动后实际会有两个nginx.exe进程,一个是master进程,一个是worker进程。这是正常现象,在Windows上它的多进程模型就是通过这种方式模拟的,别看到两个进程就以为"中病毒了"或者"重复启动了"。
2.3 让Nginx随Windows开机自启(NSSM/WinSW)
如果你只是本地联调用,手动启动就够了。但如果你是把Windows当作生产服务器,每次开机都要手动敲命令实在不像话。Nginx官方在Windows上不支持注册成系统服务,不过我们可以借助第三方工具解决。
我用得最多的是NSSM(Non-Sucking Service Manager),它可以把任意exe程序包装成Windows服务,配置非常简单。去NSSM官网下载对应系统位数的版本,解压后执行:
nssm install Nginx弹出来的界面里,Path填D:\nginx\nginx.exe,Startup directory填D:\nginx,Arguments可以留空。然后在I/O选项卡里把Output和Error都指向日志文件,方便排查。点Install Service,再到服务管理器里启动"Nginx"服务就行了。
除了NSSM,还有一个轻量的方案是用WinSW,它只需要一个xml配置文件就能完成服务注册。不过NSSM有图形界面,对新手更友好,我推荐优先用NSSM。配置完成后,Windows开机就会自动拉起Nginx,省事很多。
3. 反向代理核心配置逐行拆解
3.1 nginx.conf整体结构:从http到location的关系
Nginx的配置文件看起来指令很多,但本质上是嵌套结构的,弄懂层级关系后一切都很清晰。以nginx.conf为例,最外层是events块和http块,http块里可以定义多个server,每个server代表一个虚拟主机,server里面又可以定义多个location,用来做路径匹配和分流。
http { upstream backend { # upstream:定义一组后端服务器(负载均衡用) server 127.0.0.1:8081; } server { # server:虚拟主机配置 listen 80; # 监听端口 server_name localhost; # 域名 location / { # location:路径匹配规则 proxy_pass http://backend; } } }这种结构很像快递分拣中心:http是总仓库,server是分拣通道,location是货物标签对应的出货口。请求进来后,Nginx先根据server_name和端口找到server,再根据URI路径匹配location,最终决定转发到哪个后端。
3.2 一个最小可用的反向代理:本地服务转发
假设你在本地8080端口跑了一个Java服务,不想让用户直接访问这个端口,想统一走80端口。在http块里加一个server:
server { listen 80; server_name localhost; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }这里有几个指令要重点说明。proxy_pass就是转发目标地址,关键中的关键;后面四行proxy_set_header则是把客户端的原始信息传递到后端,否则后端看到的IP永远是127.0.0.1,这在做日志分析、权限校验时会出大问题。
很多人在这一步会踩一个坑:proxy_pass后面的URL末尾到底要不要加斜杠?这里的规则是,如果location是/,加不加斜杠影响不大;但如果location是具体路径,比如location /api/,那么proxy_pass http://127.0.0.1:8080;(不带斜杠)会把完整的/api/xxx路径传给后端,而proxy_pass http://127.0.0.1:8080/;(带斜杠)则会去掉匹配到的/api/前缀。这个差异会导致后端路由404,是高频排障点。
3.3 一个Nginx托管多个Web项目(按端口/路径/域名区分)
在一台Windows服务器上部署多个Web项目,这是被问得最多的问题。分三种情况来看。
第一种,用不同端口区分。这个最简单,每个项目一个server块,监听不同的端口,比如项目A监听8081,项目B监听8082:
server { listen 8081; server_name localhost; location / { proxy_pass http://127.0.0.1:9001; } } server { listen 8082; server_name localhost; location / { proxy_pass http://127.0.0.1:9002; } }第二种,用不同域名区分。前提是你有域名或者改了hosts文件做本机域名映射。这时用server_name区分:
server { listen 80; server_name project1.local; location / { proxy_pass http://127.0.0.1:9001; } } server { listen 80; server_name project2.local; location / { proxy_pass http://127.0.0.1:9002; } }在Windows上要模拟域名,需要编辑C:\Windows\System32\drivers\etc\hosts文件,加上一行:
127.0.0.1 project1.local 127.0.0.1 project2.local第三种,用同一端口同一域名下不同路径区分。这种场景多见于把多个独立服务统一入口,比如/app1/转发到项目1,/app2/转发到项目2:
server { listen 80; server_name localhost; location /app1/ { proxy_pass http://127.0.0.1:9001/; } location /app2/ { proxy_pass http://127.0.0.1:9002/; } }需要注意路径代理时静态资源的加载问题。很多前端项目打包后资源路径是绝对路径/static/xxx.js,这时如果你按路径区分部署,资源请求会跑到根路径/,找不到对应的location,页面样式就会全挂。解决的思路是,在打包时配置publicPath:'/app1/',让资源路径带上前缀。
3.4 客户端真实IP到底还保不保留(五元组信息与请求头转发)
这个问题的完整说法是"IP头部的五元组信息nginx转发会带吗",其实很多同行都有这个疑问。先说结论:Nginx作为反向代理转发HTTP请求时,默认情况下,TCP层五元组里的源IP会被替换成Nginx所在机器的IP,因为从TCP连接的角度看,后端服务器确实是从Nginx这个IP建立的连接,原始客户端的IP在TCP层拿不到。
那业务系统需要拿到客户端真实IP怎么做?只能靠应用层的Header传递。上面配置里的X-Real-IP和X-Forwarded-For就是干这个的。$remote_addr是Nginx直连客户端的IP,在没有经过任何代理的情况下就是用户真实IP;$proxy_add_x_forwarded_for则会把已有的X-Forwarded-For头追加上当前直连IP,这样经过多级代理时能保留完整的链路。
如果你的项目用了Spring Boot,在后端获取客户端IP通常是这样:
String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); }而且我还建议设置proxy_set_header X-Forwarded-Proto $scheme;,这个头告诉后端本次请求的原始协议是HTTP还是HTTPS。如果缺少它,后端做HTTP重定向或生成回调URL时,可能会把HTTPS请求重定向到HTTP,导致出现一个奇怪的"重定向到80端口"问题。
3.5 WebSocket反向代理:长连接别忽略的两个头
前面说的都是普通HTTP请求,一次请求一次响应就结束了。但如果你的项目里有WebSocket长连接,比如用Socket.js实现消息推送、在线客服,Nginx默认配置会导致连接直接失败。原因在于WebSocket在握手阶段需要Upgrade和Connection两个头,而Nginx转发时默认不会带上。
在location块里加上这段:
location /ws/ { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; proxy_send_timeout 3600s; }proxy_http_version 1.1也是必须的,因为HTTP/1.0协议不支持Upgrade机制。proxy_read_timeout设置为3600秒是因为WebSocket连接一旦建立,会长时间占着通道,如果还沿用默认的60秒超时,连接就经常被掐断。这里要提醒一下,这个超时时间建议和你的业务心跳机制配合设置,一般要大于心跳间隔,否则会出现"服务端没断、Nginx先断了"的尴尬情况。
4. 负载均衡与微服务网关场景实战
4.1 upstream策略:轮询、权重、ip_hash选哪个
反向代理解决的是"转发到哪台服务",而负载均衡解决的是"在多台服务之间怎么分"。Nginx用upstream定义一组后端服务器,默认按轮询策略分发:
upstream backend { server 127.0.0.1:8081; server 127.0.0.1:8082; server 127.0.0.1:8083; } server { listen 80; location / { proxy_pass http://backend; } }三个后端服务会被依次轮流访问,第一个请求去8081,第二个去8082,第三个去8083,第四个又回到8081。这种策略适合后端无状态、服务能力相同的场景。
但真实情况往往是机器配置有差异,或者接口对某台服务有依赖,这时可以用权重和ip_hash:
upstream backend { ip_hash; # 按客户端IP哈希,同一IP固定访问同一台后端 server 127.0.0.1:8081 weight=3; # weight=3,分配3/4的流量 server 127.0.0.1:8082 weight=1; # 分配1/4的流量 server 127.0.0.1:8083 backup; # 只在前面两台都挂了才启用 }weight参数很好理解,机器性能好就多分点流量;backup是备用机,平时不参与流量分配,只有其他节点不可用时才顶上。ip_hash则是根据客户端IP计算哈希值,保证同一个IP永远打到同一台后端服务器,这个特性在早期做session本地存储时很有用,但今天更多推荐用分布式session,不依赖这种策略。
4.2 前后端分离项目(以若依为例)的Nginx部署
很多团队在Windows上部署前后端分离项目,比如若依(RuoYi)这类微服务管理系统。这类项目的典型结构是:前端是一堆静态文件(HTML/CSS/JS),后端是Spring Boot服务,有时候还拆分了多个微服务模块,还有一个网关统一入口。
我以一个典型的若依微服务部署为例,画一下Nginx需要做的三件事:托管前端静态文件、把/prod-api开头的接口转发到网关端口、把上传文件路径映射到本机磁盘目录。
server { listen 80; server_name localhost; # 前端静态资源 location / { root D:/ruoyi-ui/dist; index index.html; try_files $uri $uri/ /index.html; } # 后端接口统一走网关 location /prod-api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 上传文件访问映射 location /profile/ { alias D:/ruoyi/upload/; } }这里有两个点值得展开。try_files $uri $uri/ /index.html;这一行是前端路由的核心,因为Vue等框架使用了前端路由,刷新深层页面时服务器找不到对应的物理文件,必须把请求回退到index.html,让前端路由自己处理。
proxy_pass http://127.0.0.1:8080/;末尾带斜杠,意味着匹配/prod-api/后会把/prod-api/前缀去掉再转发,比如请求/prod-api/login,后端收到的是/login。如果你的后端接口本来就有/prod-api前缀,那这里就不带斜杠,具体以你项目实际情况为准。
4.3 健康检查与故障转移配置
使用负载均衡时,最怕的是某台后端服务挂了,Nginx还在傻乎乎地往里发请求。Nginx默认对upstream里的服务器不提供主动健康检查,但可以通过max_fails和fail_timeout实现被动探测:
upstream backend { server 127.0.0.1:8081 max_fails=3 fail_timeout=30s; server 127.0.0.1:8082 max_fails=3 fail_timeout=30s; }这段配置的含义是,如果30秒内往某台服务器转发请求失败了3次,Nginx就认为这台服务器挂了,在接下来的30秒内不再向它转发请求(但不会从列表里移除)。当故障服务器恢复后,Nginx会继续分发流量给它。
如果你的场景对可用性要求更高,可以使用第三方模块如nginx-upsync实现动态更新后端列表,但Windows版Nginx编译这类模块比较折腾,我建议先用max_fails方案,实际效果完全能满足多数业务。另外还有一个技巧:在Windows上做双机容灾时,可以把主备服务都配上,配合backup参数让备用节点在关键时刻自动顶上。
4.4 负载均衡下session共享要注意什么
很多人一上来就把负载均衡配置好了,结果发现用户登录之后,刷新一下页面就被踢回登录页,这就是session问题。原因很简单:用户第一次请求打到了8081,session存在8081上;第二次请求被轮询到了8082,8082没有这个用户的session,于是判定未登录。
解决办法有三种。第一,用ip_hash策略让用户固定访问同一台后端,这是改动最小的方案,但缺点是负载均衡效果会被削弱,而且如果客户端IP变化(比如手机切了WiFi),session也会丢。第二,把session数据存到Redis等外部存储,让所有后端共享同一份session,这是最推荐的方案,但需要改业务代码。第三,用JWT之类的token机制,把用户状态信息放在客户端,后端无状态,这是现代前后端分离项目的主流方案。
如果你只是本地演示或者个人项目,我建议用第一种方法,改一行配置就解决。如果是要上生产的项目,建议早点切换到token或Redis session的方案,早改早省心。
5. HTTPS、日志与可视化运维
5.1 让反向代理支持HTTPS:证书生成与443配置
项目一旦要暴露到公网,HTTPS就是绕不开的坎。哪怕只是Windows服务器上的一个小服务,浏览器也会对HTTP页面打上"不安全"的标记。配置HTTPS的核心是拿到证书,然后让Nginx监听443端口并加载证书。
对于没有独立域名的内网项目,可以用自签名证书先满足加密需求。生成自签名证书最简单的方式是用OpenSSL(Windows下可以用Git自带的OpenSSL):
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout D:/nginx/conf/cert/private.key -out D:/nginx/conf/cert/cert.crt -subj "/CN=localhost"然后在nginx.conf里新增一个80端口跳转的server和443的server:
server { listen 80; server_name localhost; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name localhost; ssl_certificate D:/nginx/conf/cert/cert.crt; ssl_certificate_key D:/nginx/conf/cert/private.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header X-Forwarded-Proto $scheme; } }这里我建议把X-Forwarded-Proto加上,因为后端需要知道原始请求是不是HTTPS,否则在用request.getScheme()获取协议时会得到http,导致生成的链接不对。如果项目有公网域名,更推荐申请免费的SSL证书(比如Let's Encrypt系),然后定期自动续期,配置方法和自签名基本一样。
5.2 日志配置:访问日志和错误日志怎么切分查看
排障时最痛苦的是什么?后端说"我没收到请求",前端说"我明明发了请求",到底谁在撒谎?这时候看一眼Nginx的访问日志就知道。Nginx的日志默认写在logs目录下,访问日志是access.log,错误日志是error.log。
默认的访问日志格式比较简单,但不利于分析,我习惯自定义一个格式,加入响应时间和上游地址:
log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '"$http_x_forwarded_for" ' 'rt=$request_time uct=$upstream_connect_time uht=$upstream_header_time'; access_log logs/access.log main;这样每条日志都包含了耗时数据,后端接口慢还是Nginx转发慢,一看便知。$upstream_connect_time是Nginx与后端建立连接的时间,$upstream_header_time是等待后端响应头的时间。如果这两个值很大但$request_time不大,说明瓶颈在后端。
Windows下还有一个很实际的问题,Nginx在Windows上不会自动切分日志,时间长了access.log会膨胀到几个GB。我的习惯是用Windows计划任务每天定时把access.log改名并压缩,再让Nginx重新打开日志文件:
rename D:\nginx\logs\access.log access-%date:~0,4%%date:~5,2%%date:~8,2%.log然后执行nginx -s reopen让Nginx重新创建新的access.log。这个脚本我配合robocopy和压缩工具,每天凌晨自动跑一遍。
5.3 可视化配置工具:图形化也能玩转Nginx
每次改配置都要打开记事本写半天,还要小心语法错误,有没有更省事的方案?我在Windows上用过几款Nginx可视化工具,有的确实能提高效率。
第一类是Nginx的官方Dashboard替代品,比如nginxWebUI,这是一个开源项目,通过Web界面来管理Nginx配置文件,支持在线修改、语法检查、证书申请,配置完还能一键reload。它本质是Java写的,在Windows上能直接运行,还能反向代理、负载均衡、stream转发都给你提供表单操作,对不习惯命令行的人很友好。
第二类是nginx-editor之类的桌面工具,功能相对简单,主要是语法高亮和模板生成。这类工具适合新手学习,但不建议依赖它们,因为最终你还是要理解nginx.conf里每一行的含义。
还有一类值得注意,Nginx官方从1.26版本开始其实在逐步增强对动态配置的支持(如NJS模块),但Windows版的模块往往需要自己编译,门槛较高。我的建议是:工具可以用,但基础配置能力一定要自己会。毕竟出问题时,图形化界面给不了你排查思路,还是得回到配置文件和日志本身。
6. Windows下Nginx的坑,我都替你踩过了
6.1 端口被占用:80端口被System进程抢走的处理
Nginx启动失败的报错里,最常见的就是bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)。在Windows上,80端口往往被System进程占用,这个System进程不是别的,很可能是IIS或者SQL Server Reporting Services这类软件占用。
处理步骤我建议这么走:
netstat -ano | findstr :80看看80端口被哪个PID占用,然后去任务管理器里查这个PID对应的进程。如果是IIS占用,在"启用或关闭Windows功能"里把IIS关掉;如果是SQL Server Reporting Services,在服务管理器里停止服务并改成手动启动;如果是其他程序,根据你的情况决定是停掉还是改Nginx监听端口。
顺带提供一个备用方案,如果你明确知道80端口会被别的东西占用,那就把Nginx监听其他端口,比如8080,然后让防火墙做端口转发。但这样用户体验不好,一般还是建议腾出80端口。
6.2 修改配置后不生效:reload、stop和start的区别
我刚用Nginx时犯过一个错误,改完nginx.conf后直接双击nginx.exe,发现配置根本没生效,然后又开始怀疑是不是文件保存错了,折腾了半天才发现问题的根源是操作方式不对。
修改配置后,正确的操作是在命令行执行:
nginx -t # 先测试配置语法是否正确 nginx -s reload # 重新加载配置nginx -t是检查语法,很多配置错误在这一步就会暴露。如果输出syntax is ok和test is successful,再执行nginx -s reload,这样Nginx会重新读取配置,而不需要停止再启动。如果你直接双击nginx.exe,由于端口已经被占用,新进程其实不会再监听,你看到的还是旧配置。
还有些特殊情况,比如你改了监听端口,reload可能不生效,需要彻底重启:
nginx -s stop start nginx.exe记住一个口诀:改配置用reload,换端口用重启,改依赖系统资源(如日志路径)也要重启。
6.3 中文路径、空格目录导致启动失败
这个问题我前面提过,这里展开说。Nginx在Windows上对路径中的中文字符支持得不好,尤其是root、proxy_pass、ssl_certificate这些指令里的路径,一旦包含中文,轻则加载失败,重则启动不了。最经典的症状是浏览器访问时404,但文件明明存在。
我的建议是,Nginx的所有路径规划都用英文。项目前端打包产物放到D:\www\project1这类纯英文路径下,上传文件目录同理。如果实在改不了中文目录名,可以尝试用短路径名(8.3格式)或者映射网络驱动器的方式绕过,但都不推荐,治标不治本。
另外一个类似的问题是路径结尾的斜杠。在root指令里路径末尾不要加多余的斜杠,root D:/www/project1;是标准写法;在alias指令里末尾必须加斜杠,否则资源路径会拼接错误。这两种写法的差异我专门背过,但还是会偶尔搞混,建议你也在配置后立即用浏览器验证一下。
6.4 性能调优:worker_processes、keepalive与缓存
Windows版的Nginx性能优化思路和Linux类似,但要结合实际。首先是worker_processes,在Linux上建议设为CPU核心数,Windows版我建议设为1或者最多2,因为Windows下Nginx的进程模型性能损耗较大,开太多反而降低稳定性。你可以打开任务管理器看看自己CPU核心数,一般设置worker_processes 2;就够了。
第二个值得调的是keepalive,它控制Nginx与上游后端服务器之间的长连接数量。在http块里加upstream的keepalive配置:
upstream backend { server 127.0.0.1:8081; keepalive 32; # 保留32个空闲长连接 } server { location / { proxy_pass http://backend; proxy_http_version 1.1; # 必须开启1.1才支持keepalive proxy_set_header Connection ""; } }注意proxy_http_version必须设为1.1,并且把Connection头清空,否则keepalive不生效。这个配置对高并发场景的提升非常明显,因为每条新TCP连接都有握手成本,复用长连接能省下大量耗时。
第三个是静态资源缓存,如果你用Nginx托管前端静态文件,可以对图片、CSS、JS设置缓存时间:
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 7d; add_header Cache-Control "public, no-transform"; }这样浏览器会缓存这些资源,减少重复请求。但要小心,当重新部署前端版本时,如果文件名没变(没有hash命名的旧项目),用户浏览器可能会加载到旧缓存,此时最好让运维在发布后顺手清一下缓存或改文件名。
我还想再分享一个小技巧:在Windows防火墙里,别忘记放行Nginx监听的端口。很多人配置完一切正常,但局域网内其他机器就是访问不了,查了一圈发现是Windows防火墙默认拦截了入站连接。在控制面板的防火墙高级设置里,新建入站规则,放行80、443以及Nginx占用的端口,然后在浏览器里用另一台设备测一下http://你的IP是否通得过。
Nginx在Windows下跑生产环境的稳定性虽然不及Linux,但作为开发环境、演示环境、中小规模项目的入口网关,完全够用。我在实际项目中这套配置跑了将近两年,除了偶尔Windows更新后会强制重启导致服务需要重新拉起(这个用NSSM注册成服务后也能解决),其他时候基本没有因为Nginx本身出过问题。如果你之前一直在Linux上玩Nginx,现在被迫换到Windows也不用慌,配置文件的语法和逻辑完全一致,只需要注意路径写法、启动方式这些小细节就好了。希望这篇文章能让你少踩几个坑,一次配通。