拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Nginx基础教程:从安装配置到反向代理与负载均衡实战

说起Nginx很多人第一次见面是在部署项目的时候——浏览器里一片空白系统提示80端口被占用或者代理接口报502。干后台开发的、做运维的、甚至前端想自己搭个演示环境都绕不开它。Nginx是一款轻量级的高性能Web服务器和反向代理服务器最早由俄罗斯工程师Igor Sysoev在2004年发布十几年过去它仍然是全球使用率最高的Web服务器之一。它最拿手的本事是抗高并发一个进程能同时管理成千上万个连接内存占用却非常低所以被大量用在静态资源服务、反向代理、负载均衡、网关入口这些场景。这篇文章是基础篇。我会从Nginx能解决什么问题讲起接着带你完成下载安装、启动停止、配置解读再到反向代理、负载均衡、HTTPS证书、WebSocket代理这些日常开发最高频的场景最后把常见的报错和排查思路整理成速查表。不管你是刚转行做运维还是后端开发想自己搭环境或者前端要临时起个静态服务这份教程都够用已经会一些Nginx的人也可以把它当成一份随手能翻的手册。1. Nginx初识它是什么为什么人人都要学1.1 Nginx的核心定位与优势Nginx的官方定义是HTTP服务器和反向代理服务器同时也能当邮件代理。但我觉得更准确的说法是它是一个“流量入口处理器”。它不负责处理复杂的业务逻辑而是负责把请求接进来、分发给合适的下游、再把结果返回给客户端。整个过程中它用极低的资源占用撑住了极大的并发量。这个“低资源占用”怎么来的值得多讲两句。Nginx采用master-worker进程模型master进程负责管理和调度worker进程真正处理请求。每个worker内部用的是事件驱动、非阻塞IO就像一个餐厅里只安排一个全能吧员他同时接好几桌的单谁的点单好了就先处理谁而不是来一桌客人就派一个专人伺候。传统Apache那种进程/线程模型在高并发下每个连接都要占用一份内存连接一多内存直接见底Nginx则可以用极小的开销覆盖数万并发连接。这也是为什么很多互联网公司都在前端放一层Nginx而不是让后端应用直接面对用户。不过Nginx不是万能的。它擅长的是IO密集型任务比如转发、读取静态文件、负载均衡但如果你的业务需要大量CPU计算比如复杂的加密解密、图像处理Nginx就不合适。这一点在选型时要想清楚。1.2 它到底解决了什么问题从三个场景说起我在日常工作里Nginx最常出现在三个场景。第一个是静态资源服务。图片、CSS、JavaScript、PDF、视频这些文件不涉及动态计算用Nginx直接读磁盘返回响应速度极快。网上那些免费Nginx网站、个人博客、文档站很多就是Nginx直接托管静态文件。第二个是反向代理和负载均衡。公司内部有Java服务、PHP服务、Node服务不可能每个服务都直接暴露公网于是让Nginx统一监听80/443端口根据不同域名或路径把请求转发到内网不同端口。流量大了之后后端部署多台机器Nginx还能把请求分摊到各个节点这就是负载均衡。第三个是统一网关入口。HTTPS证书放在Nginx上统一管理一次配置后端服务不用各自处理证书还可以在Nginx层做访问控制、限流、请求日志记录。对后端开发来说有个经验之谈任何HTTP相关的通用能力尽量提到Nginx层做代码平时只需要关注业务逻辑。这个思路能省掉很多重复劳动。1.3 学习路径与本文覆盖范围基础篇的学习路径按“安装 → 配置 → 场景 → 排查”推进是比较高效的方式。别一上来就啃官方文档官方文档的配置项有几百个基础阶段根本用不完也别只看不练Nginx是典型的动手型工具很多问题和理解都是在实际操作中砸出来的。这篇博文覆盖五块内容安装与启停、核心配置文件nginx.conf拆解、静态站点与多项目部署、反向代理与负载均衡、HTTPS和WebSocket代理最后是高频报错的排查思路。注意这里讲的是“基础篇”像Nginx的限流、缓存、动态模块编译、灰度发布这些进阶内容我会在后续单独展开。基础打牢了后面那些都是水到渠成的事。2. 下载安装5分钟把你的Nginx跑起来2.1 安装前先想清楚三件事Nginx的安装方式多到让人觉得选择困难Windows有现成的zip包Linux可以用系统包管理器装也可以源码编译还能用Docker一条命令拉起来。面对这么多选择动手之前先想清楚三件事。第一目标系统。你是在自己电脑上折腾还是给生产服务器部署生产环境我默认推荐Linux绝大多数公司的服务器都是CentOS、Ubuntu这类系统。Windows上虽然也有Nginx但性能和稳定性不如Linux只适合做本地开发测试。第二版本选择。Nginx官方分为stable稳定版和mainline主线版。主线版功能新、迭代快但可能还没经过足够时间验证稳定版则相对保守可靠。非特殊情况生产环境一律选stable。平时看到一些新版本号比如1.31.x这种说明主线版迭代很活跃别盲目追求版本号。第三安装方式。系统包管理器最简单依赖自动处理卸载也干净源码编译灵活可以自定义模块但需要自己处理依赖升级也麻烦Docker方式最省心环境隔离删了重建都方便适合本地验证和微服务场景。到底选哪个本质上是在“安装成本”和“控制力”之间做取舍。2.2 常见系统安装姿势一览先说最省事的Docker方式。本地有Docker环境的话一条命令就能把Nginx跑起来docker run -d --name nginx -p 80:80 -v /some/content:/usr/share/nginx/html:ro nginx:stable-v参数把宿主机的目录挂载到容器里的HTML目录本地改代码容器立刻生效。生产环境如果已经用Docker管理应用直接在编排文件里加一个Nginx服务就行。Ubuntu/Debian系统用apt安装sudo apt update sudo apt install -y nginx装完系统会自动启动Nginx访问http://127.0.0.1就能看到欢迎页。CentOS/RHEL系统用yum或dnfsudo yum install -y nginx sudo systemctl start nginx如果你用的是企业内网环境或者出于安全原因不能连接外网那就走离线安装。思路是找一台同样操作系统、能联网的机器下载好Nginx的rpm包以及依赖拷到内网机器后执行rpm -ivh安装或者把源码包和编译依赖一起准备好在内网机器上./configure、make、make install。这也是所谓“二进制包部署”的核心流程。注意离线机器上最好提前装好gcc、pcre-devel、zlib-devel这些编译库否则源码编译会卡在检查环节。Windows用户直接在官网下载zip压缩包解压到你喜欢的目录。目录里就有nginx.exe双击就能启动。常见误区是直接双击导致窗口一关Nginx就停了后面我会专门讲Windows下的启动细节。官网地址就是nginx.org所有版本都能免费下载完全开源。网上有些第三方站点打着“Nginx下载教程”的旗号提供各种精简便携版我不推荐。这类版本可能捆绑了来路不明的模块出了问题不好排查还是用官方源最干净。2.3 启动、停止、重载与开机自启Linux下如果用systemd管理命令格式很统一sudo systemctl start nginx # 启动 sudo systemctl stop nginx # 停止 sudo systemctl restart nginx # 重启 sudo systemctl reload nginx # 平滑重载配置重点说reload。改完nginx.conf之后不需要重启Nginx执行reload就可以让新配置生效。Nginx会重新读取配置文件用新配置启动新的worker进程再优雅关闭旧的worker进程。整个过程不中断正在处理的请求这是生产环境最常用的操作。restart则会让服务短暂中断一般只在改了监听端口、涉及二进制升级时才会用。源码编译安装的Nginx没有systemd服务启动方式更原始/usr/local/nginx/sbin/nginx # 启动 /usr/local/nginx/sbin/nginx -s stop # 强制停止 /usr/local/nginx/sbin/nginx -s quit # 处理完当前请求后优雅退出 /usr/local/nginx/sbin/nginx -s reload /usr/local/nginx/sbin/nginx -t # 检查配置语法Windows下通过在解压目录执行nginx.exe启动停止和重载用nginx -s stop、nginx -s reload。但要注意Windows下经常出现进程没有真正退出的情况需要打开任务管理器检查nginx.exe进程必要时手动结束。开机自启这块systemd管理的系统直接执行sudo systemctl enable nginx如果安装时的服务文件没有自动生成或者你是源码编译安装也可以自己写一个系统服务文件指向Nginx二进制路径然后enable。旧一点的SysVinit系统用chkconfig nginx on。总之一句话服务器重启之后Nginx必须自动回来别让业务等一个手动启动的命令。2.4 安装完必做的健康检查安装启动后别急着写配置先做一轮健康检查确认环境是干净的。第一步看进程是否存活。执行ps -ef | grep nginx正常会看到1个master进程和多个worker进程。如果只有master没有worker多半是配置有问题去日志里找原因。第二步验证HTTP响应。在服务器本地执行curl -I http://127.0.0.1如果返回HTTP/1.1 200 OK说明服务已经通了。再用浏览器访问服务器公网IP应该能看到Nginx欢迎页。生产环境如果这台服务器有防火墙记得放行80端口常见云平台的安全组规则也要同步放开否则外部永远访问不到。第三步看日志。默认错误日志在/var/log/nginx/error.log访问日志在/var/log/nginx/access.log。源码编译的话日志在安装目录下的logs文件夹。养成装完先查看日志的习惯很多潜在问题在日志里早就有苗头。3. 配置文件详解从nginx.conf看懂一切3.1 nginx.conf的四大配置块Nginx的配置文件默认叫nginx.conf核心思路是分块配置。我把这套结构理解为快递公司全局配置是公司总部的规章制度events是各站点处理包裹的流水线规则http块是全国所有网点的总调度server块是某一个具体的快递网点location块是网点里面对不同包裹的具体分拣标准。下面是一份最典型的nginx.conf骨架user nginx; worker_processes auto; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } } }逐行拆开看。user指定worker进程以哪个用户身份运行权限过大会有安全风险权限过小则可能读不了网站目录。worker_processes auto表示worker进程数自动匹配CPU核心数这是最省心的设置。worker_connections表示每个worker进程能同时保持的最大连接数1024是保守值压力大的场景可以调高。sendfile on是让Nginx直接通过内核搬运文件加快静态文件响应keepalive_timeout控制长连接的超时时间默认65秒前端资源多的情况下长连接能显著减少握手开销。关于http块include mime.types引入文件类型映射表让Nginx知道.css文件该用什么Content-Type返回、.png用什么。include在Nginx里是高频操作它允许把配置拆成多个小文件比如http块里include conf.d/*.conf每个站点一个文件维护起来非常清爽。这也是我强烈推荐的做法。3.2 高频指令速查与真实含义刚接触Nginx的人看到一堆指令会头晕其实常用指令并不多。我整理了一份基础阶段的速查表先记住这些足够应付大多数场景指令作用示例listen监听的IP和端口listen 80;server_name匹配的域名server_name example.com;root静态文件根目录root /var/www/html;index默认首页文件index index.html;locationURL路径匹配规则location /api/ { ... }proxy_pass反向代理转发地址proxy_pass http://127.0.0.1:8080;proxy_set_header转发时修改请求头proxy_set_header Host $host;upstream定义后端服务器组upstream backend { ... }try_files按顺序尝试文件try_files $uri $uri/ 404;gzip开启压缩传输gzip on; gzip_types text/css;error_page自定义错误页面error_page 404 /404.html;有个容易混淆的点简单提一下listen后面跟的是Nginx本身监听的端口proxy_pass后面跟的是要转发到的后端地址一个是入口一个是出口别搞反。3.3 location匹配规则最容易踩坑的地方location是Nginx配置里出场率最高、也最让新手头疼的指令。写错匹配规则常见的现象就是“我明明配置了某个路由怎么就是不生效”。Nginx的location匹配优先级是这样一个顺序精确匹配具有最高优先级然后是^~前缀匹配一旦匹配上就不再继续检查正则接着是~或~*开头的正则匹配波浪号区分大小写星号波浪号不区分最后是普通前缀匹配按最长的那个来。如果所有规则都没匹配上就落到默认的/。location /logo.png { ... } # 精确匹配/logo.png location ^~ /static/ { ... } # 匹配/static/开头不再检查正则 location ~ \.php$ { ... } # 正则匹配区分大小写 location / { ... } # 兜底匹配这里有个真实踩坑案例。我之前给一套系统配置API代理写成location /api结果访问/api/user时怎么都不命中预期规则。后来查文档才发现前缀匹配不管有没有斜杠都能匹配到/api开头的路径但规则匹配的优先级和长度计算方式会和预期有偏差。所以我的习惯是前后端分离的项目统一用带斜杠的精确前缀比如location /api/然后通过proxy_pass精确控制转发路径避免含糊不清。3.4 静态站点与多项目部署实操静态站点是最简单的场景。新建一个server块指定root和index把文件丢进去就能跑。但实际上我们经常遇到“一台服务器上部署多个Web项目”的需求有三种主流做法。第一种不同端口。每个项目一个server块listen不同端口。好处是简单坏处是端口号难记也不利于HTTPS统一管理。server { listen 8081; server_name project-a.test; root /var/www/project-a; } server { listen 8082; server_name project-b.test; root /var/www/project-b; }第二种不同域名。一台服务器绑定多个域名这是生产环境最常见的做法。你只需要在server_name里写上不同的域名Nginx会根据请求中的Host头自动分流。server { listen 80; server_name www.a.com; root /var/www/a; } server { listen 80; server_name www.b.com; root /var/www/b; }第三种同一域名下不同路径。通过location前缀区分比如example.com/app1/和example.com/app2/。这时候要特别注意root和alias的区别我的经验是除非你非常确定否则子路径部署尽量用alias而不是root。location /app1/ { alias /var/www/project-a/; } location /app2/ { alias /var/www/project-b/; }root会把location前缀拼接到root目录后面。比如root /var/www; location /app1/实际查找路径是/var/www/app1/而alias是直接把请求路径映射到指定目录不会拼接location前缀。很多新手在这个地方写错导致页面一直404或者403。静态站点还有一个高频技巧给SPA应用配置try_files。前端页面是history路由刷新某个子路由时Nginx找不到对应的物理文件会返回404。正确的配置是location / { root /var/www/spa; try_files $uri $uri/ /index.html; }意思是先尝试请求的文件再尝试目录都不存在就返回index.html由前端路由接管。4. 进阶场景实操反向代理/负载均衡/HTTPS/WebSocket4.1 反向代理用一份配置把后端服务藏起来反向代理是Nginx最核心的用途之一。先解释下正向代理和反向代理的区别。正向代理是替客户端访问它够不到的服务比如你通过代理服务器访问某个外部网站服务端不知道你的真实IP。反向代理是替服务器接受客户端请求客户端只知道Nginx的地址不知道后端真实处理服务的地址。实际开发里最常见的做法是把前端静态页面和后端接口通过同一个域名暴露出去。前端请求以/api/开头的路径Nginx把它转发给Java或Node后端其余路径直接返回前端静态文件。这样一个域名全搞定不用处理跨域体系结构也清晰。server { listen 80; server_name example.com; root /var/www/frontend; index index.html; # 前端静态资源 location / { try_files $uri $uri/ /index.html; } # 后端API转发 location /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; proxy_set_header X-Forwarded-Proto $scheme; } }proxy_pass是反向代理的灵魂指令。这里有个细节proxy_pass后面带不带URI行为完全不同。不带URI的写法proxy_pass http://127.0.0.1:8080;会把原始请求的完整路径拼接到后端地址后面也就是说请求/api/user后端收到的是/api/user带URI的写法proxy_pass http://127.0.0.1:8080/;后端的路径会被替换掉api前缀可能就丢了。到底用哪种取决于后端接口要不要这个前缀。几个proxy_set_header字段的作用经常被面试问到这里一次说清楚。Host $host是让后端收到请求时看到的是浏览器里访问的那个域名而不是Nginx的内网地址。X-Real-IP是让后端记录到客户端真实IP。X-Forwarded-For会在原有值后面追加每层代理的IP适合后端通过它获取完整链路。X-Forwarded-Proto用来标记客户端最初使用的是HTTP还是HTTPS否则后端在生成跳转链接时可能把HTTPS误判成HTTP。4.2 负载均衡流量分摊的几种玩法后端服务部署了多台机器Nginx通过upstream定义一组后端服务器再在server块里把请求转发到这一组流量就自动分摊了。upstream backend { ip_hash; server 192.168.1.10 weight2 max_fails3 fail_timeout30s; server 192.168.1.11 weight1 max_fails3 fail_timeout30s; server 192.168.1.12 backup; } server { listen 80; server_name api.example.com; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }上面的配置里包含了几种负载均衡策略。默认就是轮询每个请求按顺序分发给后端节点。weight参数表示权重weight2的机器会分到两倍流量适合配置高的机器。ip_hash根据客户端IP计算哈希值同一IP固定请求到同一台后端适合需要保持会话状态的应用。backup标记的是备用节点只有主节点都挂了才会接入流量。max_fails和fail_timeout组合使用用于故障转移。举个例子max_fails3, fail_timeout30s表示如果某个节点在30秒内失败达到3次Nginx会在接下来的30秒内把这个节点标记为不可用把流量切到其他节点。这个配置对于后端偶发抖动非常有效我建议每个upstream里的节点都加上避免单点故障被客户端反复感知。负载均衡还有个面试高频问题选轮询还是ip_hash我的判断标准很简单后端服务如果是有状态应用比如Session存在本地就用ip_hash如果是无状态应用服务本身不保存状态或者Session放到了Redis里那就用默认轮询让流量分配更均匀。4.3 HTTPS与自签名证书交互式生成一次搞定HTTPS已经是大势所趋。基础篇里生产环境主要用Lets Encrypt免费证书或云厂商提供的证书流程是申请、下载、配置三个步骤测试环境用自签名证书就够了。自签名证书虽然不被浏览器信任但能让你完整走一遍HTTPS配置流程。热词里提到的“交互式生成自签名证书”其实就是用openssl按提示一步步填写信息。先生成私钥openssl genrsa -out example.key 2048然后生成自签名证书openssl req -new -x509 -key example.key -out example.crt -days 3650执行第二条命令时openssl会进入交互模式依次询问国家、省份、城市、组织名、组织单位、通用名和邮箱。最重要的一项Common Name一定要填对它必须是你访问站点时输入的域名比如example.com或者localhost。如果填错了浏览器会报证书名称不匹配。不想交互式输入的话也可以一次性指定某个字段比如加一个-subj /CNlocalhost所有字段都用参数传入适合脚本化生成。拿到证书和私钥后Nginx配置如下server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/ssl/example.crt; ssl_certificate_key /etc/nginx/ssl/example.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; root /var/www/html; index index.html; } server { listen 80; server_name example.com; return 301 https://$host$request_uri; }第一个server块是用443端口跑HTTPS注意listen 443 ssl;是Nginx的标准写法。ssl_certificate指向证书文件ssl_certificate_key指向私钥文件。第二个server块负责把HTTP请求301跳转到HTTPS这样用户访问http://example.com会自动跳到https://example.com。ssl_protocols建议至少TLSv1.2TLSv1和TLSv1.1都属于已知有安全缺陷的旧协议能不开就不开。改完配置执行nginx -t检查语法然后reload。用浏览器访问HTTPS地址会看到“您的连接不是私密连接”的警告这是自签名证书正常现象点“高级”里的“继续前往”就行。4.4 WebSocket代理与FastCGI两个高频场景WebSocket和普通HTTP请求的区别在于它需要先通过HTTP Upgrade机制把连接升级成WebSocket长连接。默认情况下Nginx代理并不传递Upgrade和Connection头所以必须显式配置这些头。map $http_upgrade $connection_upgrade { default upgrade; close; } server { listen 80; server_name ws.example.com; location /ws/ { proxy_pass http://127.0.0.1:8082; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } }map指令的作用是如果客户端请求带了Upgrade头就把Connection设置为upgrade如果没带就设置为close。这是WebSocket代理的标准写法。proxy_http_version必须设为1.1因为HTTP/1.0不支持Upgrade机制。我在实际项目里用这套配置代理过FreeSWITCH的事件Socket连接后端监听8082端口前端通过Nginx建立的WebSocket连接就能稳定保持长连接。遇到这类实时通信需求直接在Nginx层代理而不是让后端再单独开一个公网端口既省事又安全。FastCGI场景是Nginx配合PHP-FPM时的标准流程。PHP-FPM监听9000端口Nginx把PHP请求转过去处理location ~ \.php$ { root /var/www/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }location ~ .php$是正则匹配所有以.php结尾的请求。fastcgi_param SCRIPT_FILENAME是关键参数告诉PHP-FPM要执行哪个文件。如果这个参数写错最常见的结果是页面返回空白或者File not found。Windows上用Nginx跑PHP也是同一套逻辑只要PHP-CGI监听在9000端口即可。5. 常见问题速查报错对照与排查实录5.1 高频报错排查入口我在各种环境里部署Nginx踩过不少坑也帮不少人看过问题。下面这张速查表基本覆盖了基础篇阶段最高频的故障常见问题现象特征排查方向端口被占用启动时提示bind() to 0.0.0.0:80 failedss -lntp | grep :80停掉占用进程或改Nginx监听端口配置语法错误nginx -t报unknown directive或缺少分号按提示定位到具体行重点检查分号和大括号是否匹配502 Bad Gateway请求到了Nginx但后端没响应检查后端服务是否启动、端口是否一致、后端日志403 Forbidden明明配置了root访问还是403检查目录权限、Nginx运行用户是否有读取权限、index文件是否存在404 找不到文件页面路径看起来没错就是404检查root路径拼接是否错误子目录场景优先考虑alias重定向循环浏览器提示重定向次数过多检查HTTP强制跳转HTTPS的规则是否存在死循环静态文件不渲染页面能打开CSS/JS全部404检查include mime.types看响应头Content-Type是否正确排查这类问题我有一个固定的“三板斧”流程。先跑nginx -t排除配置语法问题再看/var/log/nginx/error.log错误日志里通常直接写着原因最后用curl在服务器本地访问接口对比现象。这三步走完八成问题都定位得到。5.2 从一次“nginx inactive”看排查思路热词里有个“nginx inactive”对应的是systemd管理场景下执行systemctl status nginx状态显示inactive (dead)。很多人一看到就慌了其实思路不难。首先要知道inactive表示服务没有在运行原因是多方面的。最直接的排查是从状态信息里找线索如果systemd提示进程退出码非0多半是启动时崩了。这时候用journalctl -u nginx -n 50查看最近的系统日志重点找Jan、Feb日期后面的错误行。接着手动执行nginx -t检查配置文件是否合法。很多inactive的根因是配置里端口冲突或者语法错误Nginx启动失败后systemd就把它标记为dead。还有一种情况比较隐蔽你是用编译方式安装的Nginx但systemd服务文件里写的是旧路径或者不存在的路径服务自然起不来。解决方法是把ExecStart路径改成实际二进制路径然后systemctl daemon-reload重新加载服务定义。现象出现时先别急着“重启大法”把状态、日志、配置逐层看一遍问题往往几分钟就能定位。5.3 ERR_QUIC_PROTOCOL_ERROR是怎么来的另一个高频热词是浏览器里的net::ERR_QUIC_PROTOCOL_ERROR错误码后面通常还带着200 (OK)看起来很矛盾实际上很有信息量。QUIC是HTTP/3的底层传输协议它基于UDP而不是TCP。如果你访问的网站通过Alt-Svc头声明了支持HTTP/3浏览器会优先尝试用QUIC建立连接一旦这个UDP连接握手失败浏览器就会抛出QUIC协议错误即便服务器上TCP连接其实已经成功返回了200。排查思路分两步。客户端这边先强制刷新或者清除该站点的缓存、Cookie和站点数据。Chrome里可以访问chrome://net-internals/#alt-svc把备用服务列表清空重启浏览器再看。服务端这边如果Nginx没有启用HTTP/3模块不太可能自己产生这个错误问题通常出在浏览器缓存了旧的Alt-Svc记录如果Nginx确实开启了HTTP/3相关模块就需要检查UDP 443端口是否被防火墙拦截以及加载的HTTP/3模块是否和当前Nginx版本匹配。偷懒的办法是在确认HTTPS正常的情况下干脆关闭Nginx的HTTP/3支持让浏览器回到TCP连接问题一般就消失了。5.4 一些小习惯能救你于水火最后分享几个我这些年总结出来的操作习惯都不是什么高深技巧但能让你少踩很多坑。改配置前永远先备份。不管你对Nginx多熟一个写错的字符都可能导致服务起不来。最简单的方式改之前执行cp nginx.conf nginx.conf.bak出问题马上回滚。改完配置先nginx -t再reload这套顺序我建议养成肌肉记忆。很多事故都是直接reload、发现配置错误、服务挂了才想起来检查。配置不要全堆在一个文件里。每个站点一个conf文件放到conf.d目录然后在nginx.conf里include conf.d/*.conf。这样找配置、改配置、临时下线某个站点都特别方便而且不容易互相干扰。像多项目部署场景按项目拆配置比在同一个server块里反复嵌套清晰得多。日志是你最好的朋友。Nginx的access.log记录了所有请求error.log记录了所有错误。遇到诡异问题先查日志。很多时候日志里已经写明了原因只是被大家忽略了。还可以按需求调整日志格式比如记录响应时间、请求体大小这些数据对定位性能问题特别有用。我甚至有段时间把Nginx日志接到日志平台里配合Kibana做可视化检索排查问题的效率完全不是一个量级。最后再分享一个小技巧。如果你在配置Nginx时不确定某个指令的行为直接在测试环境写最小配置验证不要跑到生产环境试错。把Nginx当成一个可以通过配置来控制的工具多做小实验用不了多久你就会发现那些看起来复杂的配置底层逻辑其实都是围绕“匹配-转发-返回”这三个动作展开的。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门