拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Nginx实战指南:从安装配置到高并发调优与排错

Nginx实战指南:从安装配置到高并发调优与排错

上个月给一台 aarch64 架构的纯内网服务器部署 Nginx,前前后后折腾了两天。中间踩了依赖包缺失、配置文件路径权限、SSL 证书握手失败这些坑,回头一看,每个问题的答案其实都写在 Nginx 的进程模型和配置语义里。于是有了这篇——从一个真实运维视角出发,把 Nginx 从安装、配置、调优到排错完整过一遍。如果你是刚接触它的小白,这篇可以当入门手册;如果你已经用了很久,但一直停留在“改改配置 reload 一下就走”的水平,这篇能帮你把背后的原理补齐。我会尽量把每一步为什么要这么做讲清楚,而不只是丢给你一堆命令。

1. Nginx到底解决了什么问题:从C10K时代说到今天的进程模型

1.1 一个经常被低估的定位

热搜词里出现“nginx详细讲解”“nginx面试题”,说明大多数人都想系统搞懂这个东西,但它在一线项目里的真实身份往往被低估了。Nginx 本质上是一个 Web 服务器,但日常生产里它更多被当作反向代理、负载均衡器、静态资源服务器和 HTTPS 终结节点来用。

用一句话概括我的理解:它是一个用事件驱动模型把高并发扛下来的 HTTP 基础设施。它不是业务服务器,而是流量入口。所有请求先到它这里,再由它决定是直接返回静态文件,还是转发给后面某个 Tomcat、Node.js、PHP-FPM 进程。

很多人以为 Nginx 只是“一个能跑网站的软件”,实际上它是整个后端架构里最靠近客户端的那一层,也是你最应该花时间去理解的一个组件。它的进程模型、配置语法、排错方式,几乎决定了你后面所有服务部署的体验。

1.2 高并发的核心秘密:事件循环与非阻塞IO

传统 Web 服务器处理并发的方式很直接:来一个连接就开一个进程或线程去伺候,连接数一多,内存和上下文切换开销直接爆炸。这也是十几年前困扰整个互联网的 C10K 问题——单机并发一万个连接就顶不住了。

Nginx 的做法完全不同。它启动后只有一个 master 进程负责管理,真正干活的是若干个 worker 进程。每个 worker 内部跑的是一个事件循环,配合非阻塞 I/O,一个 worker 可以同时盯着成千上万个连接。某个连接的请求还没读完,worker 不会干等,而是转头去处理其他已经就绪的事件;等这个连接的 I/O 准备好了,再回来接着处理。

用一个生活化的类比:传统模型就像餐厅里每来一桌客人就派一个专职服务员全程跟着,客流量一大,服务员数量就得跟着爆炸;Nginx 像一个传菜流水线上的服务员,一个人同时盯着几十桌,哪桌菜好了就过去端,没好的就先忙别的。

这就是 Nginx 能在普通服务器上轻松扛住数万并发的原因。理解了这个模型,后面所有 worker 数量、并发连接数的计算你才能看得懂。

1.3 它日常到底在扛哪些活

结合我自己的部署经验,Nginx 在日常项目中承担这些角色:

  • 静态资源服务:图片、HTML、CSS、JS 直接由 Nginx 返回,不经过后端。
  • 反向代理:动态请求转发给 Tomcat、Spring Boot、Node.js 等后端进程。
  • 负载均衡:通过 upstream 把流量分摊到多台后端服务器。
  • HTTPS 终结:统一处理 TLS 证书和加密握手,后端只跑明文 HTTP。
  • 动静分离:静态资源本地响应,动态请求转后端,充分压榨性能。
  • 限流与访问控制:按 IP、按连接数限制请求频率,保护后端。

后面我会按这个脉络,把每个角色的实际配置和坑位讲透。

2. 安装没你想的那么简单:Windows、Linux、纯内网离线三种实战

2.1 Windows:解压即用,但坑在路径和启动方式

Windows 下安装 Nginx 是最让人放松警惕的场景。从官网下载 Windows 版本,得到一个 zip 压缩包,解压完就能跑。但我第一次用 Windows 版时就被坑了一下:解压后直接双击 nginx.exe,窗口一闪而过,我以为启动失败了,实际上它已经在后台运行,只是没有任何界面提示。

正确的操作是打开命令行,切到解压目录,执行start nginx启动,用nginx -s stop停止,nginx -s reload重载配置。启动后浏览器访问 http://localhost,看到“Welcome to nginx!”就说明成功了。

这里有两个必须注意的点。第一,解压路径不要放在带中文或空格的目录下,Nginx 在 Windows 下对路径解析比较脆弱,后面配日志、配 SSL 证书时容易出莫名其妙的问题。第二,Windows 版通常只建议用于本地开发测试,生产环境最好用 Linux。原因很简单:Windows 文件系统、事件模型和 Linux 差异很大,Nginx 的核心性能优势在 Windows 上发挥不出来。

2.2 Linux:包管理器是最快路径,但版本要留个心眼

Linux 下安装 Nginx 的主流方式是包管理器。Ubuntu/Debian 系执行:

sudo apt update sudo apt install nginx

CentOS/RHEL 系执行:

sudo yum install nginx

装完直接systemctl start nginx就能跑。包管理器的好处是依赖自动解决、开机自启、systemd 管理都帮你弄好了。但我建议你立刻执行nginx -V看一下编译参数和版本。很多发行版自带的 Nginx 版本偏旧,官方文档里新出的指令在这个版本上可能根本不存在,比如http2指令的写法在不同版本之间就不一样。

如果公司有内网软件镜像站,或者你习惯用国内软件镜像源,那就在系统 apt/yum 源里把地址换成镜像站。这一步在纯内网环境尤其重要,提前把源配好,后面安装任何软件都省心。

2.3 纯内网、离线、aarch64 架构:真正的硬骨头

如果你和我一样,遇到的是 aarch64 架构加纯内网环境,安装就完全不是一条命令能解决的事了。核心思路只有一条:提前在有外网的机器上,把所有需要的安装包和依赖都下载好,然后想办法拷进内网。

源码编译是这种环境下最稳妥的方案。一个典型的 Nginx 编译依赖通常包括 gcc、make、PCRE 库(支持正则)、zlib 库(支持压缩)、OpenSSL 库(支持 HTTPS)。在 aarch64 的麒麟系统上,我建议先确认系统是 CentOS 系还是 Debian 系,然后找对应架构的依赖包。麒麟系统不同版本差异很大,有的基于 CentOS 生态,有的基于 Ubuntu 生态,认准了再动手。

具体操作时,我会先在有外网的机器上把依赖包装成 deb 或 rpm 文件,拷入内网后用dpkg -i或rpm -ivh按顺序安装。依赖关系比较复杂的时候,用yum localinstall或apt install ./xxx.deb能自动解析已下载的本地包,比手动一个个装省事得多。

离线编译 Nginx 时,可以多用静态编译选项。把 PCRE、zlib、OpenSSL 以静态方式编进去,运行时就不依赖系统的动态库版本,减少了内网机器上“缺这个库缺那个库”的概率。缺点是二进制文件会大一些,但对内网环境来说,稳定压倒一切。

2.4 安装完的第一件事:nginx -t 和进程检查

不管哪种方式装完,我强烈建议你做三件事:

  1. 执行nginx -t,它会检查所有配置文件的语法。看到 “syntax is ok” 和 “test is successful” 才说明配置没写崩。
  2. 执行ps -ef | grep nginx,正常情况下能看到一个 master 进程和多个 worker 进程。
  3. 打开浏览器访问一次,确认 HTTP 服务真正可用了。

很多新手一上来就改配置,改完直接nginx -s reload,结果 reload 失败还把原来的服务弄挂了。我现在的习惯永远是:改任何配置之前先cp nginx.conf nginx.conf.bak,改完之后先nginx -t再 reload。这个习惯帮我避开了至少十次线上事故。

3. 反向代理、负载均衡、虚拟主机:一份配置吃下日常99%请求

3.1 反向代理到底“反”在哪,兼答“nginx支持jsp吗”

很多人听“反向代理”这四个字就犯晕,我的理解方式很简单。正向代理是客户端主动配置一个代理,由代理代表你访问目标服务器,目标服务器只知道代理的存在,不知道真实客户端。反向代理则相反,它站在服务器前面,客户端访问它时,它把请求转发给后面的某台真实服务器,客户端根本不知道后端的拓扑。

Nginx 最常见的业务形态就是反向代理。这时候你自然会遇到一个问题:Nginx 本身支持 JSP 吗?答案是不直接支持。JSP 需要 Tomcat 这类 Servlet 容器才能解析,Nginx 不内置这些。但通过反向代理,Nginx 可以把所有.jsp请求或者某个路径前缀下的请求转发给 Tomcat,由 Tomcat 处理完再交回 Nginx。用户无感知,业务却完整跑起来了。

后端部署时,运维需要你提供的信息其实很固定:域名是什么、监听哪个端口、后端服务地址是多少(IP 加端口)、哪些路径要转后端、是否需要支持 WebSocket、HTTPS 证书是否已经准备好。把这些信息列清楚,Nginx 配置基本就完成一半了。

3.2 配置server块:主域名、二级域名与匹配规则

一个 Nginx 配置里,server块就是一台“虚拟主机”。每个server块绑定一个或多个域名,对应一组监听配置。热搜词里“nginx 配置主域名和二级域名”是高频问题,核心就在server_name上。

匹配优先级是这样的:精确匹配大于通配符匹配,通配符匹配大于正则匹配。也就是说,同时配置了www.example.com和*.example.com时,请求www.example.com一定走精确匹配的那个块。

我常用的主域名加二级域名配置长这样:

server { listen 80; server_name example.com www.example.com; # 主站相关配置 } server { listen 80; server_name blog.example.com; # 二级域名,转发到另一套后端或另一个静态目录 location / { proxy_pass http://blog_backend; } }

这里最容易踩的坑其实不在 Nginx,而在 DNS。很多人配好server_name后访问二级域名还是 502 或 404,最后发现是 DNS 解析没把blog.example.com指向这台服务器。测试阶段最简单的办法是改本机 hosts 文件,把域名临时解析到服务器 IP,确认 Nginx 配置没问题后再去改正式 DNS。

3.3 upstream负载均衡:让流量分摊到多台后端

当后端服务不止一台时,upstream就该登场了。它定义一个后端服务器组,location里通过proxy_pass指向这个组,Nginx 会在组内做负载均衡。

upstream backend_pool { server 192.168.1.10:8080 weight=2; server 192.168.1.11:8080 weight=1; server 192.168.1.12:8080 backup; } location /api/ { proxy_pass http://backend_pool; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }

默认策略是轮询,每台服务器轮流接请求。weight参数能加大某台机器的权重,适合性能不均衡的集群。ip_hash策略会让同一个 IP 的请求始终落到同一台后端,适合需要会话保持的场景。least_conn会把新请求分给当前活跃连接最少的后端,适合长请求占比较高的业务。

健康检查方面,Nginx 自带的被动检查通过max_fails和fail_timeout控制:请求连续失败几次,就把这台机器暂时踢出组,过一段时间再重新尝试。对大部分中小业务来说,这套配置已经够用。

我实测下来,proxy_set_header Host $host这行非常关键。不加它,后端收到的 Host 会是 upstream 的 IP,导致很多基于域名的后端服务直接返回 404。

3.4 动静分离与root/alias的经典区别

静态资源由 Nginx 直接返回、动态请求转发后端的动静分离,是 Nginx 性能优势的最大体现。配置上要注意root和alias的区别,这是我见过面试被问、实战中同事也经常搞混的一组指令。

root会把整个 location 的完整路径拼到根目录后面。比如:

location /static/ { root /data/www; }

请求/static/a.png时,Nginx 找的是/data/www/static/a.png。注意,location 里的/static/被保留了下来。

alias则不同,它会把 location 匹配到的部分整体替换掉。比如:

location /static/ { alias /data/files/; }

请求/static/a.png时,Nginx 找的是/data/files/a.png,/static/被替换成了/data/files/。如果配置成alias /data/files少一个结尾斜杠,路径拼接很可能出错。

动静分离配置的一个典型形态是:location /static/走本地目录并设置强缓存,其他所有请求proxy_pass给后端。这样图片、CSS、JS 完全不经后端,后端压力能降一大截。

4. HTTPS证书配置,以及那个让我排了一夜的SSL报错

4.1 拿到证书后,Nginx里到底要配什么

在 Godaddy、win-acem 这类证书服务平台申请的证书,下载时一般有 Nginx 类型选项。所谓 Nginx 类型,本质上就是 PEM 格式的证书文件和 Key 私钥文件。拿到两个文件后,在 Nginx 里的配置其实很固定:

server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/example.com/example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; }

最容易出问题的不是ssl_certificate,而是证书链不完整。一张正规的证书通常由站点证书、中间证书、根证书组成。浏览器要验证站点证书的信任链,就必须拿到中间证书。很多平台下载的文件里包含了完整链(fullchain),如果你的证书文件只有站点证书那一段,就必须把中间证书手动拼接进去,否则浏览器会报警告,部分客户端甚至直接拒绝连接。

拼接的方式很简单,用编辑器把站点证书内容和中间证书内容按顺序放到同一个文本文件里,站点证书在前,中间证书在后,然后让ssl_certificate指向这个合并后的文件即可。

4.2 排错记录:no required ssl certificate was sent

有一次配置双向 TLS 时,我连续排了一夜,最后定位到一个把我绕晕很久的报错:“400 No required SSL certificate was sent”。

先说明白,这个报错和服务器证书缺失完全是两回事。它出现在你配置了双向 TLS 的情况下——也就是 Nginx 要求客户端必须出示客户端证书进行身份验证。如果客户端没有安装或没有正确携带客户端证书,Nginx 在握手阶段就会直接返回 400。

配置里触发这个行为的是这两个指令:

ssl_verify_client on; ssl_client_certificate /etc/nginx/ssl/ca.crt;

排查链路建议这样走:

  1. 先看错误日志,确认报错发生在 TLS 握手阶段还是 HTTP 请求阶段。
  2. 打开配置文件,搜索ssl_verify_client,确认是否开启了双向认证。
  3. 如果业务根本不需要双向认证,把ssl_verify_client on改成off或者直接删掉,问题立刻解决。
  4. 如果确实需要双向认证,那就去检查客户端证书是否已正确安装到发起请求的机器上,以及该证书是否由ssl_client_certificate指定的 CA 签发。

还有一个容易踩的隐蔽点:很多自动化监控工具、健康检查探针不会携带客户端证书,一旦你的服务开启双向认证,探针请求就会返回 400,导致监控误报服务宕机。我当时就因为这个被半夜叫起来过。解决方法是给探针单独开一个不需要客户端证书的 server 块,或者给探针配上证书再访问。

用openssl s_client -connect 域名:443可以手动查看握手过程中的证书发送情况,输出里会明确显示是否发送了客户端证书,这是定位这类问题最直接的武器。

4.3 证书续期、多域名证书和会话复用

证书到期引发的故障我见过太多,基本都是没有提前配置续期。使用 certbot 的话,可以加一条定时任务自动续期:

certbot renew --nginx --quiet

如果证书是从服务商平台手动下载的,那就得记得在到期前重新申请、替换文件、reload。多域名场景建议直接申请 SAN 证书或者泛域名证书(*.example.com),一张证书覆盖主域名和所有二级域名,省去后期为每个子域单独维护证书的麻烦。

最后提醒一句,TLS 握手本身开销不小,高并发场景下一定要开会话缓存。ssl_session_cache shared:SSL:10m配好后,同一个客户端在一定时间内重连可以复用会话,避免重新走完整的签名验证流程。这个配置在性能测试里实测能明显降低 CPU 消耗。

5. 平滑升级与进程管理:换版本不用停业务

5.1 先搞懂master和worker各干什么

Nginx 启动后,进程模型是清晰的两层。master 进程负责全局管理:读取配置、fork worker、监听信号、平滑升级。worker 进程负责实际干活:每个 worker 运行一个事件循环,处理连接和请求。

为什么不让一个 master 直接处理请求?因为如果 worker 崩溃直接导致整个 Nginx 挂掉,太脆弱。分进程之后,某个 worker 出了严重问题,master 还能把它重启;而且多 worker 可以充分利用多核 CPU,每个 worker 绑定一个或多个核心,并行处理事件。

你在系统里执行ps -ef | grep nginx时会看到,master 的进程号往往很小,worker 的进程号是后来 fork 出来的。理解了这个结构,才能理解下面这些信号为什么能实现平滑升级。

5.2 信号、reload与restart的区别

Nginx 的运行控制本质上是向 master 进程发信号:

  • TERM、INT:立即停止,相当于强杀。
  • QUIT:优雅停止,处理完当前请求再退出。
  • HUP:重载配置,不停机。nginx -s reload发送的就是这个信号。
  • USR2:启动新的 master,用于平滑升级。
  • WINCH:让旧 worker 优雅退出。

生产环境里最常用的操作是 reload,但很多人分不清 reload 和 restart 的差别。systemctl restart nginx是完整地停掉进程再重新启动,期间会有一段服务不可用时间,所有正在处理的请求都会被中断。reload 则是让 master 重新读取配置文件、fork 新 worker、优雅退掉旧 worker,旧连接还能继续处理完。

不过 reload 也不是绝对零影响。如果一个长连接一直不断开,旧 worker 可能永远等不完,HUP 就无法完成最后的回收。新版本 Nginx 提供了worker_shutdown_timeout指令,超过指定时间强制关闭旧连接,业务能接受短暂断连的话可以配一个合理值。

我的建议是:改配置用 reload,升级二进制才用 restart 或平滑升级流程。

5.3 平滑升级新版本的具体操作

平滑升级的目标是替换 Nginx 二进制文件但不重启服务。完整流程如下:

  1. 准备好新版本 Nginx 的二进制文件,编译完先nginx -V确认版本和模块。
  2. 备份当前正在运行的二进制:cp /usr/sbin/nginx /usr/sbin/nginx.old。
  3. 用新二进制替换旧文件。
  4. 向当前 master 发送 USR2 信号:kill -USR2 $(cat /var/run/nginx.pid)。这时 Nginx 会启动一个新的 master,新旧两个 master 同时存在。
  5. 向旧 master 发送 WINCH 信号:kill -WINCH $(cat /var/run/nginx.pid.oldbin)。旧 worker 开始优雅退出,新 worker 接管新连接。
  6. 确认新 master 运行正常后,向旧 master 发送 QUIT,把旧进程彻底关闭。

这套流程我实测过多次,能在完全不中断业务的情况下完成版本升级。但要注意几点:新旧版本配置文件必须完全兼容,否则新 master 可能启动失败;升级前一定要把旧的二进制文件备份好,万一新版本有问题,还能用旧文件回滚。

很多新手升级失败是因为直接systemctl restart nginx,然后新版本启动报错,服务直接断开。走平滑升级流程的话,新旧并存期间如果发现新版本异常,还能及时回滚,这种安全感是 restart 给不了的。

6. 高并发调优和createfile()报错的完整排查链路

6.1 worker数、连接数、文件描述符:高并发三件套

真正压榨 Nginx 高并发性能,先看这三个参数:

worker_processes auto; worker_connections 10240; worker_rlimit_nofile 65535;

worker_processes设为 auto 会按照 CPU 核心数自动生成 worker 数量,这是最简单也最合理的选择。worker_connections表示每个 worker 最多同时维护多少连接。Nginx 官方文档计算最大并发数的公式是worker_processes × worker_connections,但如果你在做反向代理,实际并发能力还要再除以 2,因为一个客户端请求会占用一个前端连接和一个后端连接,一个请求消耗两个连接额度。

系统层面的限制同样不能忽略。查看当前进程能打开的文件描述符数量用ulimit -n,如果这个值太小,Nginx 连接数再多也白搭,底层too many open files会直接限制你。修改/etc/security/limits.conf,把 nofile 提高,同时配上worker_rlimit_nofile,让 worker 进程突破默认限制。

内核参数方面,我一般会调net.ipv4.ip_local_port_range扩大本地可用端口范围,以及net.core.somaxconn提高 accept 队列长度。至于net.ipv4.tcp_tw_reuse,不同内核版本默认策略不一样,有些新内核默认就是开启相关处理逻辑的,改之前先确认内核版本,别拿着老教程盲目设置。

6.2 那个让人头疼的[emerg] createfile()报错,到底怎么查

Windows 环境下最经典的启动失败就是类似这种报错:

nginx: [emerg] createfile() "d:/phpstudy_pro/www/admin2.com/nginx.htaccess" failed (2: The system cannot find the file specified)

第一次遇到时我也很懵:createfile 是什么?为什么 Nginx 会去创建一个nginx.htaccess文件?其实根源很简单——某个配置指令要求 Nginx 打开或创建一个文件,但这个文件的路径不存在,或者目录没有写权限。在 Windows 下,Nginx 底层用的是 CreateFile 系统调用,所以报错就表现为 createfile()。

这条报错的路径是d:/phpstudy_pro/www/admin2.com/nginx.htaccess,典型的 phpStudy 集成环境域名目录。我排查后发现,是有个配置文件把error_log或access_log的路径写到了这个不存在的文件上。Nginx 启动时要按配置创建日志文件,结果找不到对应目录,直接启动失败。

完整排查链路建议这样走:

  1. 完整阅读报错,PS 后面的提示是(2: No such file or directory)还是(13: Permission denied)。前者是路径不存在,后者是权限不够,两个修法不一样。
  2. 全局搜索报错里出现的文件名或路径,看是哪个指令引用了它。
  3. 检查该路径的父目录是否存在。如果目录不存在,先创建目录;如果目录存在但权限不足,给 Nginx 进程授权。
  4. 看是否把日志文件路径误配到了网站根目录下一个并不存在的文件名上。如果是,改成 Nginx 默认的日志位置最省事:
error_log logs/error.log; access_log logs/access.log;
  1. 改完先nginx -t验证,再启动服务。

这条经验也提醒我,Windows 下配 Nginx,路径书写一定要保守:尽量用相对路径,避免盘符加反斜杠混用,避免中文目录,避免在网站目录里创建 Nginx 自身要用的文件。

6.3 用VSCode把Nginx配置规整起来,少踩低级语法坑

Nginx 配置语法有一个特点:块结构靠花括号,指令以分号结尾,缩进纯粹为了好看,语法检查只看括号和分号。但正因为如此,配置一长就很容易出现花括号不匹配、分号丢失这类低级错误。

我现在的习惯是用 VSCode 加 nginx-formatter 插件,写完配置直接格式化,缩进统一、层级清晰,花括号配没配对一目了然。插件安装后选中配置内容,右键选择格式化即可。

更重要的是配置文件的组织方式。主配置nginx.conf只放全局配置和基本的 server 块,其他业务配置全部拆到conf.d/目录下,每个域名一个文件,用include conf.d/*.conf;加载。这样排查问题时,直接按域名找文件,不用在一大坨配置里翻半天。

维护规范方面,我给自己定了几条死规矩:每次改动前备份;每次改完必须nginx -t;reload 必须在低峰期执行;配置文件里永远写上注释标明这段配置是哪个业务的、负责人是谁。这些规矩看起来琐碎,长期维护下来能省下的时间远超投入。

6.4 把调优和排错经验变成面试里的加分项

Nginx 是后端和运维面试的常客,热搜词里就有“nginx面试题”。我梳理了几个高频问题,结合前面的实战说下回答思路:

  • Nginx 和 Apache 的差异:核心是进程模型,Nginx 的事件驱动非阻塞模型在高并发下内存占用更低。
  • 反向代理和负载均衡的原理:讲清客户端、Nginx、后端三者的关系,以及 upstream 的几种策略。
  • 502、504、499 分别怎么排查:502 是后端无响应或响应错误,先看后端进程;504 是后端处理超时,调 proxy_read_timeout;499 是客户端在等待期间主动断开,重点看后端处理耗时和客户端行为。
  • 高并发参数怎么调:把 worker_processes、worker_connections、文件描述符、内核参数这条链路讲完整。

面试官最想听到的不是你背出的配置项,而是解决过的真实问题。把你调优时算并发数的过程、排查 createfile 报错的链路、处理双向 TLS 误报的经过讲出来,比列出二十个指令更有说服力。

最后分享一个我个人的实战习惯:每次接到一个 Nginx 相关的排障任务,第一件事不是看业务代码,而是先执行nginx -V确认版本和编译模块,再查看错误日志最后一百行。版本决定哪些指令可用,日志决定问题方向,这两样对齐了,百分之八十的问题已经能定位。Nginx 这个软件看起来简单,真正用好的关键是把进程模型、配置语义和排错思路串成一条线。希望这篇能帮你少走一些弯路。

返回列表