nginx实战指南:从反向代理到负载均衡的配置与排障
2026/9/23 18:05:43 网站建设 项目流程

最近有个朋友问我,他在本地起了好几个服务,前端一个端口、后端一个端口、文件服务又一个端口,联调的时候被跨域折腾得够呛。我告诉他,这种情况别急着改代码,先用 nginx 把流量统一收口,问题能少一半。这就是 nginx 最典型的使用场景:它是一款高性能的 HTTP 服务器和反向代理服务器,入门门槛不高,但覆盖的场景极广——静态资源托管、反向代理、负载均衡、SSL 终止、WebSocket 转发、灰度发布,几乎每个用 Web 的地方都有它的身影。

如果你是刚接触 Linux 服务端、想搞懂 nginx 配置逻辑的开发者或运维新人,这篇内容会比较适合你。我会从"nginx 解决的到底是什么问题"讲起,再逐步拆解安装方式、配置文件结构、反向代理与负载均衡的实战写法,以及我实际踩过的 403、SSL 证书、QUIC 报错等常见坑。文章里不会堆砌抽象术语,所有操作步骤和配置片段都可以直接复制到你的机器上试。

1. 先弄清楚 nginx 到底帮你解决了什么问题

1.1 一张图理解 nginx 在体系中的位置

我习惯把 nginx 理解成"公司前台":所有外部请求先到前台,前台根据访客想去哪个部门(后端服务、静态文件、图片服务),再把他引导到对应的工位。没有前台的时候,访客必须记着每个部门的详细门牌号(IP 加端口),部门之间协调起来非常混乱;有了前台之后,访客只需要知道公司总机(80 或 443 端口),剩下的事情由前台统一调度。

这个"前台"在技术上做的是四层或七层流量转发。四层转发基于 IP 和端口,七层转发则能识别 HTTP 协议细节,比如域名、URL 路径、请求头。nginx 默认工作在七层,这也是大多数入门场景需要的。它不像 LVS 那样只做底层流量分发,而是能真正"看懂" HTTP 请求,然后根据规则决定转发、拒绝、缓存或改写。

1.2 哪些场景最适合用 nginx 入门

根据我接触的项目,入门阶段碰到最多的需求集中在四类:

  1. 静态资源托管:把前端打包后的 dist 目录直接交给 nginx,省去自己写静态文件服务的麻烦。
  2. 反向代理:前端页面通过同源路径访问后端 API,由 nginx 转发到实际的后端服务端口,解决跨域问题。
  3. 负载均衡:同一套后端服务部署多个实例,nginx 按照一定策略分发流量,提升可用性和并发能力。
  4. SSL 终结:在 nginx 这一层统一配置 HTTPS 证书,后端服务不用各自处理 TLS 握手,简化证书管理。

这四个场景基本覆盖了从个人项目到中小型生产环境的绝大多数需求。把这块玩明白了,再去理解网关、服务网格等更复杂的架构概念会顺畅很多。

1.3 nginx 与 Apache、Caddy 的差别

很多人会问,同类产品还有 Apache 和 Caddy,为什么偏偏选 nginx?我个人的使用感受是:

  • Apache配置灵活但语法偏重,模块体系复杂,并发连接较多时内存占用明显。它在老项目里依然常见,但新项目中使用比例在下降。
  • Caddy最大的亮点是自动 HTTPS 和极简配置,几行就能跑起来,但生态成熟度和企业存量部署远不如 nginx。
  • nginx采用事件驱动架构,单进程能支撑大量并发连接,配置语法简单直观,社区资料和海量存量配置决定了它几乎是运维必会技能。

另外,openresty 基于 nginx 扩展了 Lua 脚本能力,Nginx Plus 则是官方商业版,这些都说明 nginx 的底层架构具备很强的延展性。入门学 nginx 等于同时打开了这些上层工具的基础。

2. 安装 nginx 的几条路径:按系统选最省事的方式

2.1 Linux 发行版官方仓库安装

在 Debian/Ubuntu 系列上,最省事的方式是直接通过 apt 安装:

sudo apt update sudo apt install nginx -y

装完后 nginx 会自动注册为 systemd 服务,直接执行:

sudo systemctl start nginx sudo systemctl enable nginx

Ubuntu 上装完默认站点目录在/var/www/html,配置文件在/etc/nginx/,日志在/var/log/nginx/。不同发行版的路径稍有差异,但核心结构一致。

在 AlmaLinux 9 或 CentOS 9 上,流程类似但细节不同:

sudo dnf install nginx -y sudo systemctl start nginx sudo systemctl enable nginx

需要注意,RHEL 系发行版的默认站点根目录通常是/usr/share/nginx/html,配置文件主目录仍是/etc/nginx/。如果你在 AlmaLinux 9 上装完 nginx 后访问 80 端口没反应,先检查一下防火墙:

sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --reload

这个坑我见过太多次——服务明明起来了,访问却不通,最后发现是 firewalld 没放行端口。

2.2 Windows 下的 nginx 安装与注意事项

Windows 上安装 nginx 其实不需要所谓"真正的安装包",官方提供的是绿色解压版。到 nginx.org 下载 Windows 版本的 zip 包,解压到某个目录,比如D:\nginx-1.26.x,目录里直接就有nginx.exe

启动方式是在该目录下执行:

start nginx.exe

注意它不像普通 Windows 服务由 systemd 管理,默认也不会开机自启。关停和重载的命令分别在同一个目录下:

nginx.exe -s stop nginx.exe -s reload

Windows 下最容易踩的坑有两个。第一个是路径分隔符:windows 路径里如果直接写D:\some\path,nginx 会把\s之类的转义成特殊字符,必须写成D:/some/path或使用双反斜杠D:\\some\\path。第二个是端口占用:80 端口经常被 IIS 或其他程序占用,启动时如果看到[emerg] bind() to 0.0.0.0:80 failed,需要先找到占用进程,或者改成其他端口。Windows 上入门学习 nginx 完全够用,但真正跑生产还是建议用 Linux。

2.3 编译安装与离线安装的取舍

生产环境或内网场景里,官方仓库版本满足不了需求时,会选择编译安装。编译安装的核心优势是可以自定义模块,比如把http_v2_modulehttp_ssl_modulehttp_realip_module等编译进去。基本步骤如下:

# 先安装编译工具和依赖库 sudo apt install build-essential libpcre3-dev zlib1g-dev libssl-dev -y # 下载源码并解压 wget https://nginx.org/download/nginx-1.26.2.tar.gz tar -zxvf nginx-1.26.2.tar.gz cd nginx-1.26.2 # 配置编译选项 ./configure --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-stream \ --with-http_realip_module # 编译安装 make -j$(nproc) sudo make install

--prefix指定安装目录,如果之后想卸载,删除这个目录即可。--with-stream是四层代理必需的模块,很多人一开始会漏掉,等配置 stream 块时报错才发现。

离线安装的情况我在 aarch64 纯内网环境下遇到过。思路是准备一台同架构、同系统的机器,在线把 nginx 及其依赖通过apt downloadyumdownloader拉下来,再拷贝到内网机器上离线安装。aarch64 本身的坑是部分官方仓库的二进制包是 x86_64 的,所以纯内网的 aarch64 机器更推荐源码编译安装,编译依赖和源码包一起带进去。

2.4 安装后的第一步验证

安装完成后不要急着改配置,先验证 nginx 是否正常工作。Linux 下执行:

curl -I http://localhost

如果返回HTTP/1.1 200 OK,说明基础服务正常。然后执行:

nginx -t

这个命令是语法检查,任何配置文件改动后都要先跑一次。它会提示配置文件中第几行有语法错误,非常实用。如果配置有问题,改完再跑一次,直到出现syntax is oktest is successful

3. nginx 配置文件的底层逻辑

3.1 nginx.conf 的树形结构

nginx 的配置本质是一棵嵌套的指令树,大部分时间你只需要接触其中的几个关键块。打开/etc/nginx/nginx.conf,典型的简化结构是:

user www-data; worker_processes auto; events { worker_connections 1024; } http { include /etc/nginx/mime.types; include /etc/nginx/conf.d/*.conf; server { listen 80; server_name example.com; location / { root /var/www/html; index index.html; } } }

events块负责全局事件模型,worker_connections决定每个 worker 进程能同时处理的连接数。http块里是 HTTP 服务的全部配置,包括 server 和 location。在生产环境里,我不会把所有 server 块直接堆在主配置文件里,而是通过include /etc/nginx/conf.d/*.conf把每个站点独立成一个文件,方便维护和排查。

在 http 块之外还有一个stream块,专门用于四层 TCP/UDP 转发。如果你要给 FreeSWITCH 的 WebSocket 端口或者数据库端口做代理,就需要配置 stream 块,而不是用普通的 server 块。

3.2 server 块和 location 块匹配规则

server 块可以理解为"虚拟主机"。同一台机器可以配置多个 server 块,通过listen端口和server_name域名区分请求应该落到哪个 server。请求进来后,nginx 会先比对端口和域名,找到对应的 server 块,再进入这个 server 块内部的 location 匹配。

location 的匹配规则是入门阶段最容易懵的地方。它支持多种写法:

# 前缀匹配,最常用 location /api/ { proxy_pass http://backend; } # 精确匹配 location = /healthcheck { return 200 "ok"; } # 正则匹配,~ 表示区分大小写,~* 表示不区分 location ~* \.(png|jpg|css|js)$ { expires 7d; } # 优先前缀匹配 location ^~ /static/ { alias /data/static/; }

匹配顺序的规则是:先做精确匹配=,命中就直接返回;再处理^~前缀匹配,命中后不再继续;然后是正则匹配,按配置顺序逐个测试;最后才是普通前缀匹配,取最长匹配项。这个顺序记牢了基本不会错。

一个容易犯的低级错误是rootalias的区别。root会把完整的 URL 路径拼接到根目录后面,而alias是用 location 中的路径替换掉配置的目录。举例来说:

location /static/ { root /data/www; } # 访问 /static/app.js 时,实际找的是 /data/www/static/app.js location /static/ { alias /data/files/; } # 访问 /static/app.js 时,实际找的是 /data/files/app.js

很多新人在配置静态文件时出现 404,多半就是 root 和 alias 没分清。我的习惯是:如果 location 的路径和实际文件目录不一致,用 alias;如果一致,用 root,逻辑上更清晰。

3.3 配置文件热加载与语法检查

nginx 支持平滑重载配置,不需要重启进程就能让新配置生效。每次修改完配置文件后执行:

nginx -t sudo systemctl reload nginx

nginx -t先做语法检查,检查通过后再 reload。reload 的工作机制是:主进程重新读取配置,并启动一组新的 worker 进程,等旧 worker 处理完当前连接后自动退出。这意味着在重载期间,已建立的连接不会断开,非常优雅。

我见过不少人在这个环节省事,直接执行systemctl restart nginx,虽然也能生效,但会把所有活跃连接全部断开,在线上环境会造成请求失败。习惯上应该用 reload,restart 只保留在不得已的情况下,比如修改了监听端口或升级了二进制文件。

4. 反向代理与负载均衡:入门最核心的实战配置

4.1 反向代理配置与常见参数

反向代理是 nginx 最常见的用途。典型配置是前端访问https://yourdomain.com/api/xxx,由 nginx 转发到后端服务http://127.0.0.1:8080/xxx

server { listen 80; server_name yourdomain.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_set_header X-Forwarded-Proto $scheme; } }

这里最容易被忽略的是proxy_set_header三件套。如果后端要获取客户端真实 IP 或判断原始协议,这三个请求头是必需的。尤其是X-Forwarded-Proto,很多后端框架会根据它来决定生成 http 链接还是 https 链接,不设置的话会出现页面拿到一堆 http 资源地址的诡异问题。

另一个关键点是proxy_pass末尾是否带/,它直接影响 URL 的拼接方式。看这两条配置的区别:

# 不带斜杠:原始 URI 原样传递 # 请求 /api/users -> http://127.0.0.1:8080/api/users proxy_pass http://127.0.0.1:8080; # 带斜杠:location 匹配部分会被替换掉 # 请求 /api/users -> http://127.0.0.1:8080/users proxy_pass http://127.0.0.1:8080/;

这个差异不是靠记背能解决的,最好的方式是动手写两个配置分别测一遍。我记得第一次配置时因为多写了一个斜杠,导致整个 API 路由全部报 404,排查了半天才发现是 URL 被代理解析后多了一层路径。

proxy_pass还支持转发到 upstream 定义的后端集群,这样就和负载均衡绑定在一起了。

4.2 负载均衡的几种策略

负载均衡是反向代理的自然延伸,把请求分发给多个后端实例。先定义一个 upstream 组:

upstream backend_servers { server 192.168.1.10:8080 weight=3; server 192.168.1.11:8080 weight=1; server 192.168.1.12:8080 backup; }

默认策略是轮询,每个请求按顺序依次分发到不同 server。weight参数能让性能更好的机器承担更多流量,例如上面的配置中,无权重时两台机器均分,加了 weight 后会有 3/4 的流量到第一台、1/4 到第二台。backup标记的机器只在主服务器全部不可用时才启用,适合做容灾。

除了默认轮询,还有几个常用的分配策略:

# IP 哈希:同一客户端 IP 固定分发到同一后端,适合需要会话保持的场景 upstream backend_servers { ip_hash; server 192.168.1.10:8080; server 192.168.1.11:8080; } # 最小连接数:动态分配给当前活跃连接数最少的后端 upstream backend_servers { least_conn; server 192.168.1.10:8080; server 192.168.1.11:8080; }

ip_hash常见于有 Session 的服务,但它基于 IPv4 地址做哈希,如果用户通过 NAT 访问,同一台设备的不同请求可能来源 IP 都一样,反而导致负载不均。如果后端服务是无状态的,或者已经引入了 Redis 会话共享,我建议直接使用默认轮询或least_conn,让流量更均衡。

4.3 WebSocket 代理的额外处理

WebSocket 协议在握手阶段是通过 HTTP Upgrade 机制实现的。nginx 默认只转发普通 HTTP 请求,所以代理 WebSocket 时必须显式加上 Upgrade 相关头:

location /ws/ { proxy_pass http://backend_servers; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; }

proxy_http_version 1.1这个点经常被忽略。默认情况下 nginx 与后端通信使用 HTTP/1.0,而 HTTP/1.0 不支持 Upgrade 头,WebSocket 握手会失败。设为 1.1 之后,配合 Upgrade 和 Connection 头,才能完成协议升级。

proxy_read_timeout 3600s也很关键。WebSocket 连接建立后,默认 60 秒内没有数据传输,nginx 就会断开连接。如果要做即时通讯或消息推送,必须把这个超时时间调大。FreeSWITCH 的 WebSocket 端口代理就是一个典型场景——FreeSWITCH 通过 mod_verto 等模块对外提供 WebSocket 接口,通话信令和媒体控制都要走这个长连接,一旦被 nginx 掐断,电话就会异常挂断。代理这类长连接服务时,不仅要设置大的 read timeout,还建议关闭 idle 连接回收,必要时直接在 stream 块里做四层转发,让它处理 TCP 层的数据。这就是热词里"nginx 代理 FreeSWITCH 的 ws 端口"的由来。

长连接的另一个细节是upstream keepalive。默认情况下,nginx 与后端之间的连接在处理完请求后就会关闭,每次都重新建立 TCP 连接,在高并发场景下开销很大。启用 keepalive 可以复用与后端的连接池:

upstream backend_servers { server 192.168.1.10:8080; server 192.168.1.11:8080; keepalive 32; } location /api/ { proxy_pass http://backend_servers; proxy_http_version 1.1; proxy_set_header Connection ""; }

keepalive 32表示每个 worker 进程最多保留 32 个空闲的连接。启用后需要把proxy_http_version设置为 1.1,并且清空Connection头,否则连接的复用逻辑会出错。我曾经在一次压测中看到,加上这组配置后后端服务的 QPS 提升了约 15%,同时 TIME_WAIT 连接数大幅下降,说明这个配置在高并发场景下效果确实明显。

5. 踩坑实录:403、自签名证书、QUIC 等常见问题

5.1 403 的根因定位

403 Forbidden 是我在 nginx 入门里见过最多的错误,也是最容易误判的问题。原因通常有三个方向:

第一,默认 index 文件不存在。访问站点根目录时,nginx 会按index指令找文件,如果/var/www/html下没有index.html,就会返回 403。解决方法是确认文件存在,或者调整index配置:

location / { root /var/www/html; index index.html index.htm; }

第二,文件权限不足。nginx 的 worker 进程以user指令指定的用户运行,默认是www-datanginx。如果网站文件的所有者是 root,且权限为 600,nginx 就没有读取权限。解决方法是调整属主或权限:

sudo chown -R www-data:www-data /var/www/html sudo chmod -R 755 /var/www/html

第三,SELinux 阻止。RHEL 系发行版下,即使文件权限正确,SELinux 也会阻止 nginx 读取某些目录。可以用以下命令临时验证:

sudo setenforce 0

如果关掉 SELinux 后 403 消失,说明确实是策略问题。更优雅的做法是修改文件上下文:

sudo semanage fcontext -a -t httpd_sys_content_t "/path/to/site(/.*)?" sudo restorecon -Rv /path/to/site

排查 403 时,我建议先查看 nginx 错误日志,它比任何猜测都靠谱:

tail -f /var/log/nginx/error.log

日志里会直接写明是权限不足、目录不存在还是被deny规则拒绝,照单抓药即可。

5.2 自签名 SSL 证书的交互式生成

开发环境中,为本地 HTTPS 配置自签名证书是常有的事。很多人一听到"自签名证书"就想到复杂的 OpenSSL 参数,实际上用交互式方式生成很简单:

openssl req -x509 -nodes -newkey rsa:2048 \ -keyout /etc/nginx/ssl/example.key \ -out /etc/nginx/ssl/example.crt \ -days 365

执行后,OpenSSL 会逐个提示你输入国家、省份、城市、组织名和 Common Name。其中 Common Name 必须填你访问用的域名,比如localhostexample.com,否则浏览器会提示域名不匹配。-nodes表示不加密私钥,这样 nginx 启动时不需要手动输入密码;-days 365是证书有效期,自签名证书一般给一年就够了。

生成后在 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 交互式方法",指的就是openssl req -x509的交互问答方式。还有一种更省事的做法,用一行命令配合-subj参数跳过交互:

openssl req -x509 -nodes -newkey rsa:2048 \ -keyout example.key -out example.crt -days 365 \ -subj "/CN=localhost"

这类证书浏览器会提示"不安全",但对于本地开发足够了。如果要做给同事联调用,可以用mkcert工具,它能让本地生成的证书被系统信任,浏览器不再报警告。

5.3 QUIC 与 net::err_quic_protocol_error

HTTP/3 基于 QUIC 协议,nginx 从 1.25 版本开始正式支持 HTTP/3。配置方法是在监听指令上同时监听 UDP 443 和 TCP 443:

listen 443 ssl; listen 443 quic reuseport; http2 on; ssl_certificate /etc/nginx/ssl/example.crt; ssl_certificate_key /etc/nginx/ssl/example.key; add_header Alt-Svc 'h3=":443"; ma=86400' always;

这里reuseport让多个 worker 进程共享同一个 UDP 端口,是 QUIC 高性能的关键。Alt-Svc头告诉浏览器"你可以尝试用 HTTP/3 访问我",浏览器收到后会自动升级。

配置完 HTTP/3 后,Chrome 浏览器有时会出现net::err_quic_protocol_error,表现是页面偶尔打不开,刷新一次又恢复正常。这个问题我在本地压测时遇到过,原因基本上集中在两个方向:一是 UDP 端口被防火墙拦截,QUIC 握手使用了 UDP,如果防火墙没有放行,请求会一直重试直到超时;二是 HTTP/2 与 HTTP/3 的协议协商出问题,尤其是配置了旧版本 nginx 后再升级,配置语法不一致导致 QUIC 和 TCP 监听逻辑冲突。

排查方法是先在浏览器地址栏输入chrome://net-export抓取网络日志,或者在命令行里用 curl 强制指定 HTTP/3 测试:

curl --http3 -I https://example.com

如果 curl 能通但浏览器报错,优先检查防火墙的 UDP 443 端口。如果 curl 也不通,再检查证书链是否完整。QUIC 对证书的完整性和有效期比 HTTP/2 更严格,证书链不完整很容易握手失败。

5.4 "nginx: [emerg] createfile()" 与 Windows 路径问题

Windows 下启动 nginx 时如果报nginx: [emerg] createfile() "D:/phpstudy_pro/www/admin2.com/nginx.htaccess" failed之类的错误,通常是配置里指定的文件路径不存在,或者路径解析出了问题。

这个错误里值得注意两点。一是 nginx.htaccess——这其实是某些集成环境把 Apache 的 .htaccess 习惯带到了 nginx 配置里,但 nginx 根本不认识 .htaccess 文件,也不会自动加载它。如果配置里有类似include D:/web/www/.htaccess;的写法,应该删除或改成真实的 nginx 配置文件。二是 Windows 下的路径用反斜杠还是正斜杠的问题,nginx 在 Windows 上建议统一使用正斜杠,即D:/path/to/file,如果必须用反斜杠则要写成D:\\path\\to\\file,否则\t会被当成制表符,路径自然错了。

遇到[emerg]级别的错误时,nginx 会直接拒绝启动。排查思路是先执行nginx -t检查语法,再根据报错中提到的文件路径逐一确认文件是否存在、nginx 是否有权限读取。在 Windows 上还可能是管理员权限问题——某些目录(比如C:\Program Files)普通权限无法写入,需要用管理员身份运行命令行工具。

5.5 同端口部署多个 Web 系统的正确姿势

热词里有"nginx 同一个端口部署两个 web 系统",这是很常见的需求。在同一台机器的同一个端口上部署多个 Web 系统,本质上是利用server_name做域名区分:

server { listen 80; server_name sys1.example.com; location / { proxy_pass http://127.0.0.1:8081; } } server { listen 80; server_name sys2.example.com; location / { proxy_pass http://127.0.0.1:8082; } }

这样两个系统共用 80 端口,DNS 将不同域名解析到这台机器,nginx 根据Host请求头区分应该转给哪个后端。如果没有两个域名、只有一个 IP 和一个域名,但想跑两个系统,可以按 URL 路径区分:

server { listen 80; server_name example.com; location /sys1/ { proxy_pass http://127.0.0.1:8081/; } location /sys2/ { proxy_pass http://127.0.0.1:8082/; } }

路径区分方案的难点在后端。如果后端系统本身带有绝对路径资源(比如页面里写死了/static/app.js),代理后会出现资源 404。我通常会在后端的部署配置里加上 context-path 配置,或者通过 sub_filter 指令改写响应内容:

location /sys1/ { proxy_pass http://127.0.0.1:8081/; sub_filter '/static/' '/sys1/static/'; sub_filter_once off; }

sub_filter能在返回给用户前替换响应正文,但这只是兜底方案,最好还是后端支持子路径部署。

6. 进阶玩法:autoindex、高并发与常见面试考点

6.1 autoindex 实现在线文件浏览

nginx 的 autoindex 功能可以像 Apache 的 Indexes 一样,直接列出一个目录下的所有文件,方便做临时下载站或文件分享:

location /files/ { alias /data/files/; autoindex on; autoindex_exact_size off; autoindex_localtime on; }
  • autoindex on开启目录列表。
  • autoindex_exact_size off让文件大小显示为可读格式(如 KB、MB),而不是精确字节数。
  • autoindex_localtime on让文件时间显示为本地时区。

请求https://yourdomain.com/files/时,浏览器会看到/data/files/下的全部文件列表,点击即可下载。这个功能在临时交付文件、搭建内网软件源时很实用。

开启 autoindex 时必须注意目录权限。如果alias指向的目录对 nginx 用户没有读权限,页面会返回 403。另外,autoindex 默认不显示隐藏文件,也不会递归展示子目录,它只展示当前目录的直接内容,子目录会作为链接让用户自己点击进去。

6.2 高并发场景下的参数调整

nginx 的并发能力不是装好就能全自动到达的,需要配合内核参数和 nginx 配置一起调整。入门阶段先理解几个核心参数:

worker_processes auto; events { worker_connections 65535; multi_accept on; } http { keepalive_timeout 65; sendfile on; tcp_nopush on; }

worker_processes auto让 nginx 按 CPU 核数启动 worker 进程,每个 worker 都能充分利用一个 CPU 核心。worker_connections是每个 worker 能同时打开的最大连接数,默认 1024,高并发场景建议调到 65535 或更高。理论最大并发连接数约等于worker_processes * worker_connections,但还要受系统文件描述符限制影响。

系统层面需要调整文件描述符上限:

ulimit -n 65535

如果想让这个限制永久生效,需要修改/etc/security/limits.conf,并确认 nginx 的worker_rlimit_nofile设置:

worker_rlimit_nofile 65535;

sendfile on让数据从磁盘文件直接通过网络发送,减少用户态拷贝;tcp_nopush on配合sendfile使用,优化网络包的发送策略。这几个参数组合起来,静态文件的吞吐量会有显著提升。压测时用abwrk能看到比较直观的 QPS 差异:

wrk -t4 -c100 -d30s http://localhost/

6.3 nginx 面试高频考点

热词里包含"nginx 面试题",说明很多人学 nginx 的目的是求职。面试官常问的问题其实就几个方向:

  • nginx 为什么能支撑高并发?核心是事件驱动和非阻塞 I/O。nginx 的 worker 进程通过 epoll 同时监听大量连接,当某个连接可读或可写时再处理,而不是为每个连接分配一个线程。
  • 正向代理和反向代理的区别?正向代理代理的是客户端,代表客户端去访问服务器;反向代理代理的是服务器,代表服务器接收客户端的请求。
  • nginx 的进程模型?一个 master 进程负责管理和监控,多个 worker 进程实际处理请求,worker 之间通过共享内存通信。
  • 如何排查 502、504 错误?502 Bad Gateway 通常是后端服务没有启动或崩溃;504 Gateway Timeout 是后端处理超时,需要调大proxy_read_timeout或检查后端逻辑。
  • location 匹配顺序?这就是 3.2 节讲的优先顺序,精确匹配、前缀匹配、正则匹配的实际逻辑。

面试回答这些问题时,最关键的是能结合自己动手配置过的场景说,比如你曾经用 ip_hash 解决了会话保持,但后来发现 NAT 环境下负载不均衡,就换成了 Redis 共享会话。这种真实案例比背概念有说服力得多。

6.4 从入门到能上线的建议路径

学到这儿,按我自己的经历,你其实已经具备了把 nginx 用起来的能力。剩下的路可以按这样走:

先把本地环境搭起来,用默认配置跑一个静态网站;然后配置反向代理,把两个本地服务通过不同路径或不同域名挂到同一个端口;接下来加一个自签名证书,让站点支持 HTTPS;最后尝试用 upstream 配两个后端实例,体验一下负载均衡的效果。这个流程走完,你能理解 80 以上的常见配置。

再往后,可以考虑用 Docker 部署 nginx,用 nginx proxy manager 做可视化反向代理管理,或者用 Docker 部署的 Harbor 的 nginx 组件研究生产级配置。Harbor 内部的 nginx 负责转发 UI、API 和 registry 流量,它的配置逻辑就是一套完整的 nginx 实战案例。

最后还有几个日常习惯。改配置前先备份,不管多小的修改都先跑nginx -t。观察日志要成为本能,访问日志看流量,错误日志看故障,两者结合能定位大部分问题。线上变更尽量走 reload 而不是 restart,回滚时直接把备份覆盖回去再接 reload。坚持这套操作习惯,nginx 出问题的概率会小很多,出了问题也能很快定位。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询