ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Nginx实战:从安装配置到反向代理、负载均衡与SSL证书

Nginx实战:从安装配置到反向代理、负载均衡与SSL证书 我用 nginx 少说也有七八年了从最早在服务器上手动编译到后来直接用系统包管理器一把梭再到给线上入口做反向代理、负载均衡、平滑升级踩过的坑确实不少收获也很实在。现在无论接手什么项目我第一件事基本都是把 nginx 部署好把它当成流量进出的大门静态资源由它直接返回动态请求由它转给后端所有端口只对 nginx 开放后端服务全部关在内部网络里。这篇文章就是想把这几年实操里最常用、最容易出错的部分整理出来从下载安装、基础配置、反向代理到 SSL 证书、平滑升级和问题排查按我实际验证过的做法讲一遍不背官方文档适合刚接触 Linux 部署的初学者也适合已经在用但想系统补一遍细节的开发者。1. 为什么我会建议每个项目都用 nginx1.1 三个核心使用场景决定你的学习主线很多人一上来就背 nginx 配置背完就忘原因是没有先想清楚 nginx 到底解决什么问题。我自己的理解是nginx 的日常使用可以压缩成三件事第一托管静态资源比如前端打包出来的 html、css、js、图片nginx 处理这类请求非常快几乎不占什么 CPU第二反向代理把请求转发给后端的 Java、Python、Go 服务同时在转发过程中补上客户端真实 IP、Host 等头信息第三负载均衡当一个后端撑不住流量时用 upstream 模块把请求分摊到多台机器上。绝大多数你在网上搜到的教程、面试题、生产运维操作核心都绕着这三件事展开。想明白这一点你的学习顺序就清晰了先装好 nginx配一个能访问的静态页面然后学着配 server 和 location再去理解 proxy_pass 和 upstream最后补 SSL 证书和缓存压缩这些优化项。这也是我这篇文章的组织顺序按真实工作流推进而不是按官方文档的参数顺序堆砌。1.2 进程模型master 与 worker 是怎么配合的理解了进程模型你以后看日志、做平滑升级、排查“nginx 怎么不生效”这类问题都会轻松很多。nginx 启动后会有两类进程一个是 master 进程也叫主进程它不直接处理请求只负责读取配置、管理 worker 进程、执行平滑升级和日志切割另外还有若干 worker 进程才是真正处理并发请求的干活角色。worker 进程的数量默认等于服务器的 CPU 核心数每个 worker 用事件驱动的方式同时维护成千上万个连接这也是 nginx 能扛住高并发的根本原因。你执行nginx -s reload时实际上就是 master 进程检查新的配置然后把 reload 信号发给老 worker老 worker 处理完手上的请求后优雅退出新 worker 用新配置拉起。整个过程用户请求基本不中断所以“平滑”这两个字不是白叫的。如果你不理解这个机制很容易在改配置后产生“我明明 reload 了为什么没生效”的错觉实际上可能是你改了文件但语法错误master 直接拒绝了加载。1.3 该把 nginx 放在网络架构的哪个位置我的习惯是所有对外 HTTP/HTTPS 流量都必须经过 nginx后端服务一律监听内网地址或者只监听本机回环地址。这样做有几个直接的好处一是端口暴露面大幅缩小不会被扫描器乱打二是可以在入口层统一做 HTTPS 终止、Gzip 压缩、请求限速、访问控制三是后端服务后续扩容时只需要改 nginx 的 upstream不需要动客户端配置。之前接过一个老项目Tomcat 直接监听公网 8080 端口一天能被扫描器打几千次。后来我在前面加了一层 nginx对外只开放 80 和 443Tomcat 改成监听 127.0.0.1:8080配合防火墙规则把外部访问全拦掉服务器立刻安静了。这个教训也让我养成了一个习惯每次部署新服务第一件事是想清楚它在链路里的位置而不是先急着启动进程。2. 安装 nginx从下载到平滑升级一篇学会2.1 官方仓库、源码编译、系统包管理器该选哪种安装 nginx 至少有三种常见方式不同场景选择不同。第一种是直接用系统的包管理器安装比如 Ubuntu 上的apt install nginx、CentOS 上的yum install nginx这是最省事的适合绝大多数开发环境和一般生产环境好处是后续可以用系统的systemctl统一管理也能跟随系统源自动更新。第二种是从 nginx 官网下载编译好的二进制包适合想要最新主线版本、又不想自己编译的场景。第三种是源码编译安装适合需要自定义模块、或者目标服务器断网隔离、必须手动指定依赖的场景。对于刚入门的人我建议直接从包管理器开始先把主流程跑通。对于生产环境如果发行版仓库里的版本太老比如某些 CentOS 默认源里的 nginx 版本已经落后好几个大版本那就考虑用官方提供的 nginx 仓库源来安装。至于源码编译除非你有明确的模块定制需求否则付出的时间成本不太值官方和第三方 Pre-built 包通常够用。2.2 Linux 安装实操Ubuntu 与 CentOS 都覆盖在 Ubuntu 20.04 或 22.04 上安装 nginx 只需要两三条命令sudo apt update sudo apt install -y nginx systemctl status nginx装完之后 Ubuntu 会自动把服务拉起默认监听 80 端口。你可以直接用浏览器访问服务器的 IP看到 Welcome to nginx 页面就说明成功了。配置文件分布在/etc/nginx/目录下主配置是/etc/nginx/nginx.conf站点配置通常放在/etc/nginx/sites-available/和/etc/nginx/sites-enabled/这个设计是为了方便用软链接启用和停用站点和 CentOS 的习惯不太一样。CentOS 7 上稍微有点门槛因为默认源里没有 nginx需要先装 EPEL 源才能用yum install nginxsudo yum install -y epel-release sudo yum install -y nginx sudo systemctl enable nginx sudo systemctl start nginxCentOS 的配置目录是/etc/nginx/conf.d/所有以.conf结尾的文件都会被主配置 include 进来。如果你嫌弃系统源版本太老也可以配置 nginx 官方源再安装但这个操作要小心不同大版本的官方源地址不一样装完一定要执行nginx -v确认版本符合预期。另外提一句离线安装的场景。有些内网服务器或者信创环境比如麒麟系统没法直接访问外网源。我的做法是在一台同版本、同架构的联网机器上用apt download或yumdownloader把 nginx 及其依赖包全部下载下来再拷贝到内网机器上用dpkg -i或rpm -ivh依次安装。这样能绕开在线源的依赖解析问题但是依赖顺序要理清楚装的时候如果报缺依赖就对照错误提示逐个补包。源码编译在这种场景其实也可以但需要提前准备 gcc、make、pcre-devel、zlib-devel、openssl-devel 这些工具链打包搬运的工程量更大我一般只在内网实在找不到对应 rpm 包时才走编译。2.3 Windows 上安装 nginx 的注意事项Windows 上安装 nginx 就简单很多了去官网下载 Windows 版本的 zip 包解压就能用不需要安装程序。解压目录建议别放中文路径也别放带空格的路径否则某些模块处理文件路径时容易出幺蛾子。运行方式是双击nginx.exe或者到解压目录执行cd C:\nginx-1.26.2 start nginx启动后浏览器访问 localhost能看到欢迎页就说明起来了。这里容易踩的坑是 80 端口被 IIS 或其他程序占用如果启动没反应先执行netstat -ano | findstr :80看看端口被谁占了。Windows 版本主要用来本地模拟配置、验证规则不太适合跑重型生产流量因为 Windows 上的 nginx 性能和 Linux 版有明显差距而且不推荐用 Windows 做反向代理服务器。Windows 上重载配置的命令是nginx.exe -s reload停止是nginx.exe -s stop。如果改了配置之后想验证语法用nginx.exe -t它会告诉你配置文件里有没有语法错误这是所有平台都应该养成的习惯。2.4 平滑升级与版本回滚说到平滑升级很多人以为nginx -s reload就叫平滑升级其实不对。reload 只是重载配置文件二进制版本没变。真正的平滑升级是你在不中断服务的前提下把旧的 nginx 二进制换成新的版本。标准流程是这样的先下载新版本源码或二进制编译好之后把旧二进制备份一下再把新二进制替换掉然后给 master 进程发送 USR2 信号让它启动新的 worker等新 worker 正常接管流量后再向旧 master 发送 WINCH 信号让旧 worker 优雅退出。实际生产中我更推荐一种更省心、也更少出错的做法用nginx官方包或发行版仓库直接升级比如 Ubuntu 上apt upgrade nginx升级过程中包管理器本身就会处理好二进制替换和重启流程配合systemctl reload nginx通常能做到秒级平滑。如果升级后发现问题需要回滚最稳妥的方案是提前备份旧版本的二进制和配置文件把备份文件恢复回去再 reload。这个流程在医院、银行等不允许服务中断的场景里经常用到我只能给一个建议升级前一定跑一次nginx -t并且至少保留上一个版本的完整备份目录别嫌麻烦。3. 配置文件才是 nginx 的灵魂3.1 nginx.conf 的主干结构nginx 配置看起来层级很多实际上主干就四个块events块负责全局事件模型配置比如 worker 连接数http块负责 HTTP 相关配置里面可以写serverserver块表示一个虚拟主机匹配域名和端口location块再往下细粒度地匹配 URL 路径。一个最精简的配置长这样events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name example.com; location / { root /var/www/html; index index.html; } } }这里要注意location /里的root和alias的区别这是新手最容易搞混的一组概念。root是拼接式的请求/images/a.png时会去找/var/www/html/images/a.png而alias是替换式的如果写成alias /data/files/请求/images/a.png会找/data/files/a.png。我经常看到有人用root配一个下载目录结果路径多了一层访问全部 404其实就是这里的拼接逻辑没想清楚。3.2 server_name 实战主域名与二级域名一个入口搞定一台服务器上配多个站点是 nginx 最常见的需求比如主域名example.com对应官网二级域名blog.example.com对应博客api.example.com对应后端接口。实现方式就是在同一个 http 块里写多个 server 块nginx 根据请求头里的 Host 字段进行匹配。基本写法如下server { listen 80; server_name example.com www.example.com; root /var/www/site; } server { listen 80; server_name blog.example.com; root /var/www/blog; } server { listen 80; server_name api.example.com; location / { proxy_pass http://127.0.0.1:8080; } }有几件事我是在生产环境里吃了亏之后才明白的。第一DNS 解析必须先把这些域名都指向服务器 IP否则 nginx 配置再对也没用。第二如果有人直接用 IP 访问而你没有给 IP 配 server 块nginx 会默认用第一个 server 块来响应这通常会引发奇怪的问题所以我会习惯性地加一个默认拒掉的 server 块server { listen 80 default_server; server_name _; return 444; }return 444是 nginx 的特色写法服务器直接关闭连接不返回任何响应体很多人在实测之后都喜欢这个方案。第三如果同一域名不同端口、同一端口不同域名需要不同类型处理比如 HTTP 跳 HTTPS、首页重定向到二级目录都用 server 块配合return或rewrite实现别在 location 里写太多重定向逻辑否则排查起来会非常痛苦。3.3 反向代理的核心写法与 proxy_pass 的坑反向代理是 nginx 使用频率最高的功能而且我敢说至少有一半的配置问题是出在proxy_pass后面的路径上。看这个例子server { listen 80; server_name api.example.com; 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_pass结尾带不带斜杠效果完全不同。如果写成proxy_pass http://127.0.0.1:8080;不带斜杠请求/api/user会原样转发给后端后端收到/api/user由后端的路由去处理/api前缀。如果写成proxy_pass http://127.0.0.1:8080/;带斜杠那么 location 里匹配到的/api/前缀会被替换掉请求/api/user转发给后端时变成/user。这个前缀替换逻辑非常容易踩坑特别是前后端约定不一致的时候你可能会看到 404、重定向丢失或者接口路径错误第一反应往往是怀疑后端代码实际上问题出在 nginx 这一层。另外提醒一下反向代理场景中proxy_set_header这几个头字段不要省否则后端拿不到真实的客户端 IP尤其是做日志分析、限流、风控的时候$remote_addr永远只是 nginx 服务器的地址真正的客户端地址要靠X-Forwarded-For来传递。如果你代理的是 WebSocket 或者长连接服务还要额外加Upgrade和Connection头并且把超时时间调大。3.4 upstream 负载均衡参数选择当后端服务有多台实例时就需要把 upstream 块和 proxy_pass 配合使用。upstream 是定义在 http 块里的一个服务组里面列出后端机器的 IP 和端口upstream backend { server 192.168.1.10:8080 weight2; server 192.168.1.11:8080 weight1; keepalive 32; } server { listen 80; location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ; } }默认情况下 nginx 使用轮询算法每个请求按顺序轮流发给后端机器。加上weight参数可以分配权重适合两台机器配置不同、性能不均的场景。还有几种常用策略ip_hash能保证同一个 IP 的请求始终落在同一台后端上适合有 session 但没有做分布式 Session 共享的旧项目least_conn会把请求发给当前连接数最少的那台机器适合请求处理时间差异很大的场景。这里有个隐藏点容易被忽略nginx 默认与后端交互用的是 HTTP/1.0而 HTTP/1.0 不支持连接复用每个请求都要重新建立 TCP 连接在高并发场景下会浪费大量握手开销。所以我在生产环境里都习惯加上keepalive 32和proxy_http_version 1.1让 nginx 与后端之间维持一批长连接实测对 QPS 提升非常明显。3.5 结合 Tomcatnginx 正确地和 Java 应用配合很多人在网上搜“linux 部署 tomcat nginx”核心问题就是nginx 到底能不能跑 JSP答案很明确nginx 本身不支持 JSP 解析它的强项是静态文件、反向代理而 JSP 的解析和执行需要交给 Tomcat 这样的 Servlet 容器。所以标准的架构是nginx 监听外部端口把动态请求转给 Tomcat同时静态资源由 nginx 直接返回。一个典型配置长这样server { listen 80; server_name app.example.com; 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; } location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2)$ { root /opt/tomcat/webapps/ROOT; expires 7d; } }动态请求全部交给proxy_pass静态资源请求走正则 location 直接读文件。这样做的效果是Tomcat 只需要专心处理 Servlet 和 JSP静态资源不占用它的线程池对高并发场景帮助很大。还有一点值得注意Tomcat 在 nginx 后面时很多应用会用到request.getScheme()或request.isSecure()来判断当前请求是 HTTP 还是 HTTPS如果 nginx 做了 SSL 终止Tomcat 收到的是普通 HTTP 请求就可能生成错误的重定向链接。这种问题通常靠proxy_set_header X-Forwarded-Proto $scheme;加上 Tomcat 的 RemoteIpValve 配置解决如果你部署的应用出现“页面访问是 HTTPS、但是里面重定向后变成 HTTP”的怪现象优先往这个方向查。4. 生产环境里一定要会的配置细节4.1 静态资源缓存与 gzip 压缩优化性能最先做的两件事就是缓存和压缩。先说缓存浏览器请求静态资源时nginx 通过expires或Cache-Control告诉浏览器这个文件可以缓存多久。比如图片和 CSS 这类基本不变化的资源缓存一周完全没问题location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2)$ { expires 7d; add_header Cache-Control public, max-age604800; }这里有个搭配技巧如果前端发布时给文件名加了 hash比如app.8f3k2.js缓存时间可以放心放得很长如果没有 hash缓存太久会导致用户更新后还在用旧文件。所以我在实际项目里都建议前端同学在打包时加上 hash 后缀这样 nginx 这里就可以无脑设置长缓存。再说 gzip同样是减少传输体积、提高加载速度的手段。开启方式是在 http 块里加上gzip on; gzip_comp_level 5; gzip_min_length 1k; gzip_types text/plain text/css application/javascript application/json application/xml image/svgxml;gzip_comp_level不是越高越好级别高压缩率提升有限但 CPU 消耗明显增加实测 5 左右是性价比比较高的档位。gzip_min_length 1k表示小于 1KB 的文件不压缩因为压缩这类小文件带来的收益微乎其微反而白白浪费 CPU。还有一个很容易漏的配置是如果走的是反向代理且后端返回的响应头里带Content-Length而不是Transfer-Encoding: chunkednginx 压缩会受影响所以生产环境我会把gzip_http_version 1.1也写上细节不一定马上用得上但踩过一次坑之后就明白为什么要写。4.2 共享文件和下载目录怎么暴露才安全“nginx 共享文件”是网上高频搜索词通常是团队内部需要把某台机器上的目录通过 HTTP 方式共享给同事下载。使用 alias 配置一个纯下载站点一行就能解决server { listen 8088; server_name _; location /download/ { alias /data/share/; autoindex on; autoindex_exact_size off; autoindex_localtime on; } }autoindex on是打开目录列表功能访问时可以看到整个目录的文件列表autoindex_exact_size off让文件大小显示为可读格式autoindex_localtime on让文件时间显示成本地时间。这个配置做内部文件共享确实方便但直接暴露在公网会非常危险容易变成别人抓取数据的免费网盘。所以我通常会在前面加一层访问限制比如最简单的 HTTP Basic 认证或者用allow和deny限制来源 IP。location /download/ { alias /data/share/; autoindex on; auth_basic Restricted; auth_basic_user_file /etc/nginx/.htpasswd; }.htpasswd文件可以用openssl passwd -apr1生成密码散列再手工拼成“用户名:散列值”的格式。虽然这种方式不算最安全但对付内部工具站已经足够了。更重要的一点是共享目录千万别放在 nginx 的 web 根目录下面否则别人可能通过拼接路径访问到目录外的文件alias 的配置一定要注意路径结尾的斜杠对应关系。4.3 mirror 请求复制、超时控制与限速网上搜“nginx mirror 超时时间”通常指向两个方向一是 nginx 的 mirror 模块它能把线上真实流量复制一份到另一个地址常见用途是做流量回放、日志采集、灰度对比二是 nginx 向上游发起请求时的各种超时时间设置。这两个我分开说。mirror 模块的用法是在 location 里指定一个 internal 的内部 locationnginx 收到请求后会同时向 mirror 地址发一份复制流量但不会等待 mirror 的响应主请求仍按原路径正常返回。这个特性很适合做新老系统对比或者录制线上流量用于测试location /api { mirror /mirror; proxy_pass http://backend; } location /mirror { internal; proxy_pass http://mirror-backend; }注意mirror一定要放在主 location 里internal表示这个地址外部访问不到只能被 nginx 内部调用。mirror 毕竟是额外请求如果 mirror 后端响应很慢可能会拖累 worker 进程的资源占用所以网上问 mirror 超时时间怎么办通常不是调快 mirror 本身的返回而是要给 mirror 的 location 单独设proxy_connect_timeout、proxy_send_timeout、proxy_read_timeout让复制请求在超时后及时断开不影响主流程。和超时相关的几个参数在反向代理里也经常调整proxy_connect_timeout默认 60 秒指建立后端连接的超时proxy_read_timeout默认 60 秒指两次读取数据之间的最大间隔proxy_send_timeout默认 60 秒指发送数据给后端的超时。如果你的应用里有长轮询、大文件上传、或者后端接口本身执行时间较长这几个值不调大用户就会遇到莫名的 504而 nginx 错误日志里只显示“upstream timed out”非常容易误判成后端挂掉。4.4 用 VSCode 把 nginx 配置格式化nginx 的配置文件不像代码默认没有很严格的缩进风格多人协作时经常发现每个人写的格式都不一样。我在实际团队里推广过一套方案用 VSCode 来做 nginx 配置的编辑和格式化效果还不错。具体做法是先在 VSCode 里安装一个名为nginx-formatter的插件它基于 nginx 官方提供的格式化工具然后打开任意.conf文件右键选“格式化文档”或者用快捷键ShiftAltF插件会自动把缩进、空格、换行统一成规范格式。还有一个更推荐的做法不依赖 VSCode 插件而是在配置里养成写好分号、不嵌套过深的习惯。再配合nginx -t做语法检查基本就能避免大部分低级错误。另外 VSCode 的 nginx 插件会提供$host、$remote_addr这类变量的自动补全和高亮对新手友好很多不熟悉内置变量的人可以靠提示快速上手。注意插件格式化之后一定要重新跑一遍nginx -t因为格式化不会改变语义但如果有注释位置特殊或者多行参数不同版本插件处理方式可能有细微差异语法检查最终兜底。4.5 SSL 证书申请与配置少走弯路的姿势给站点加 HTTPS 是现代部署的基本要求。证书来源主要有两类一类是付费或免费的 DV 证书很多云厂商提供免费一年证书下载时选择 nginx 类型会得到一个.crt/.pem证书文件和一个.key私钥文件另一类是 Let’s Encrypt 这类免费自动化证书通过 ACME 协议自动申请和续期。下载到的证书放到 nginx 配置里核心写法是server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/certs/example.com.crt; ssl_certificate_key /etc/nginx/certs/example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; }很多人在这一步遇到各种奇怪问题我先说三个最典型的。第一证书文件路径或权限不对nginx 启动时报“cannot load certificate”错误这一般是证书和私钥文件放到了 nginx 用户读不了的目录或者文件格式不对解决方法是确认权限为 600 或 644并用openssl x509 -in 证书文件 -noout -text检查证书内容。第二证书和私钥不匹配nginx 启动时也会报错可以用openssl x509 -noout -modulus -in 证书文件和openssl rsa -noout -modulus -in 私钥文件分别计算 modulus两个输出一致才说明匹配。第三配好 443 之后别忘了把 80 端口的重定向加上最简单的写法是server { listen 80; server_name example.com; return 301 https://$host$request_uri; }有些用户申请的是云厂商提供的免费证书下载时明明选了 nginx 类型只有一个.crt和一个.key但浏览器还是不认这种大概率是证书链不完整。解决办法是把网站证书和中间证书合并成一个.crt文件顺序是网站证书在前、中间证书在后合并之后重新加载 nginxnginx -s reload再测就正常了。5. 常见问题排查与卸载实录5.1 日志会说话先学会怎么看日志遇到 nginx 问题第一件事不是猜而是看日志。nginx 有两个日志access.log 记录每次请求的访问信息error.log 记录启动错误、配置错误和转发错误。Ubuntu 上日志位置通常在/var/log/nginx/CentOS 也一样。我排查问题时的顺序很固定先tail -f /var/log/nginx/error.log看有没有新报错如果访问报 502 或 504去 error.log 里搜 “connect() failed” 或 “upstream timed out”这两个关键字能直接告诉你后端连接失败还是后端超时。access.log 里要重点看的字段有状态码、请求耗时和代理地址。比如日志里有大量 499 状态码说明客户端在 nginx 还没返回结果之前就主动断开连接了这种现象在高并发或慢接口场景下很正常但如果你做的是视频上传类应用499 频繁出现往往意味着超时时间设置不对。养成“报错先看日志”的习惯之后90% 的问题都能在 5 分钟内定位到方向而不是像无头苍蝇一样到处改配置。5.2 “no required ssl certificate was sent” 与其他证书类报错很多人在 nginx 配置双向 TLS 时也就是客户端证书验证场景会看到这么一条错误no required ssl certificate was sent。这个报错直译是“没有发送需要的 SSL 证书”意思是 nginx 要求客户端提供证书但客户端没有传。这通常发生在ssl_verify_client on配置开启了强制客户端证书认证时而浏览器或客户端没有安装对应的客户端证书。处理思路有两个方向如果你确实需要双向认证就要先给客户端签发证书并安装到请求方然后把ssl_client_certificate指向 CA 证书文件如果你本来只是想配单向 HTTPS根本不该加ssl_verify_client这行配置找到并删掉即可。我见过不少人被这个问题困扰很久最后发现是误拷贝了网上某个 “双向认证” 配置模板把不需要的验证开关也抄了进来。排查时先grep -r ssl_verify_client /etc/nginx/检查所有配置确认哪里开启了验证再去判断这个需求是不是真的必要。5.3 卸载 nginx 时的残留清理卸载看似简单但系统里残留的配置、日志、进程会导致你重装 nginx 后遇到“地址已在使用”或端口冲突。Ubuntu 上卸载并清理的完整命令是sudo systemctl stop nginx sudo apt remove --purge nginx nginx-common nginx-full sudo apt autoremove如果之前是源码编译安装的包管理器根本不知道 nginx 存在你需要手动停掉进程然后删除/usr/local/nginx或你当初指定的安装目录以及/etc/nginx和/var/log/nginx等残留目录。判断是否真正清理干净用which nginx和ps -ef | grep nginx两条命令检查一下就行。重装 nginx 时遇到 “bind() to 0.0.0.0:80 failed” 的错误十有八九是端口被旧进程占用。这时候执行ss -tlnp | grep :80找到占用进程的 PID然后根据情况停掉或杀掉再把新装的 nginx 拉起来。这个报错在生产切换时特别常见别急着改配置先在系统层面确认端口确实被释放了。5.4 超时、请求大小、502/504 速查表我把生产环境里遇到频率最高的几个问题集中整理成了一张表比较适合直接收藏现象常见原因排查方向502 Bad Gatewaynginx 无法连接后端检查后端进程是否存活端口是否监听防火墙是否拦截504 Gateway Timeout后端响应太慢触发proxy_read_timeout调大超时同时排查后端慢查询、线程阻塞499 状态码客户端在响应前断开检查接口耗时、前端超时设置或者需要调大 keepalive413 Request Entity Too Large上传文件超过client_max_body_size在 server 或 location 中调大该参数404 Not Foundroot/alias 路径配置错误或后端路由缺失先看日志确认请求实际路径再对比root拼接规则connection refused后端端口未监听或防火墙拦截ss -tlnp检查监听telnet 测试连通性这里重点说一下 502 和 504 的区别502 是连接建立失败后端压根没起来或者端口不通504 是连接建立成功但响应超时后端可能还活着只是处理请求太慢。这两个状态一出来排错方向完全不同的新手最容易混。还有一个容易被忽略的问题如果后端的 worker 线程池被慢请求耗尽新连接排不上队也会表现为 502/504这时候光调 nginx 超时没用必须去后端的线程池、数据库连接池那边找根因。6. 写在最后一些靠时间换来的经验说几条我这些年攒下的实在体会吧。第一每次改 nginx 配置前先备份一份备份文件名带上日期改完后立刻执行nginx -t验证语法再 reload。我见过太多人在生产环境手一抖删错一个分号或者写错一个变量名直接把整个站点搞挂。第二能用include拆分配置的就拆开别把所有 server 块堆在一个 nginx.conf 里我习惯按域名拆成独立的 conf 文件每个文件只负责一个站点或一组服务排查问题时互不干扰谁出的问题看谁的文件。第三systemctl restart nginx和nginx -s reload是有本质区别的restart 会先停再启动连接会断reload 是平滑重载连接基本不受影响。所以平时配置变更尽量用 reload只有改了一些底层参数或者加载新模块时才需要 restart。还有一个小技巧是学会用curl -I来做验证。比如你改了 SSL 证书执行curl -I https://example.com看返回的证书信息和状态码你怀疑路径配置错了执行curl -I http://127.0.0.1:80/xxx直接看响应。很多时候用一条 curl 命令就能确认问题到底在 nginx 还是后端比反复开浏览器 F12 要高效得多。nginx 这东西说难不难说简单也不简单但只要你理解了它的进程模型、location 匹配规则和 proxy_pass 的转发逻辑后面遇到的大多数问题都是配置细节问题靠日志和 curl 就能解决。希望这篇总结能帮你在部署和排错时省点时间。
返回列表