ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

从零掌握Nginx:反向代理、负载均衡与HTTPS配置实战

2026/9/23 19:43:22 拓冰建站 浏览量
从零掌握Nginx:反向代理、负载均衡与HTTPS配置实战 nginx 这个词在很长一段时间里几乎成了 Web 服务端和反向代理的默认答案。我这些年带团队、做项目几乎每个服务上线前都会先把 nginx 这一层搭好静态资源、接口转发、负载均衡、SSL 证书全都由它统一收口。新手搜“nginx”的时候看到的东西特别杂有讲安装的、有讲配置的、有讲面试题的反而容易看懵。这篇我不打算写成文档式教程而是按我自己从零搭一套服务的过程来走先搞清楚 nginx 到底在干什么再把安装、配置、代理、HTTPS、排错一次捋完。你照着做能解决 80% 的入门问题也能理解后面再看高层级资料时那些概念到底在说什么。1. 先搞明白nginx 到底是干什么的1.1 Web 服务器的核心职责很多初学者把 nginx 和 Tomcat 当成一类东西其实定位不一样。nginx 最擅长的三件事一是静态文件服务比如直接返回图片、CSS、JS 这些文件速度快、开销小二是反向代理它站在后端服务前面把客户端请求按规则转发给后端的应用服务器接住流量也隐藏后端细节三就是负载均衡当一个后端服务扛不住的时候把请求分发到多台机器、多个实例上。生活里类比一下nginx 就像一个前台接待员。访问者不直接找后面办公的每个人后端应用而是先到前台nginx前台按照你贴的指引把访客带到对应工位。这个“指引”就是 nginx 的配置规则。我见过很多人项目里其实已经用着 nginx 了但对这几个角色没概念出了问题只能瞎猜。比如访问首页正常、访问某个接口 502很可能就是 location 匹配规则把请求转发到了不对的后端端口。这一类问题本质上是没理解 nginx 的请求处理流程接收请求、按 server 匹配主机名、按 location 匹配路径、执行对应处理返回文件或转发。1.2 为什么选 nginx 而不是 Apache、Tomcat、Caddy这个话题有意思面试也爱考。nginx 用的是事件驱动模型一个进程能同时处理大量连接对付高并发场景资源占用很低。Apache 经典的 prefork 模型是每个请求一个进程稳定但耗资源Tomcat 本身更适合跑动态 Java 应用而不是直接暴露在公网。Caddy 配置简洁、自带 HTTPS但生态和灵活度没有 nginx 成熟。我自己的选择经历可以供你参考早年接过一个小项目Tomcat 直接监听 80 端口暴露出去最开始流量小没事某一波活动流量上来后连接数瞬间暴涨Tomcat 线程池被打爆服务直接假死。后来在前面架了一层 nginx 做动静分离和限流同样的 Tomcat 扛住了原先几倍的请求量。所以如果你还没有明确的技术偏好从 nginx 入手是性价比最高的选择。2. 环境准备4 种常见方式安装并验证 nginx2.1 Windows 下的快速体验如果你只是第一次接触 nginx想在本地先跑起来看看效果Windows 是最快的路子。到官网下载 Windows 版 zip 压缩包nginx.org 直接能搜到解压到一个路径不含中文、不含空格的目录双击 nginx.exe或者在命令行进入目录执行start nginx然后在浏览器访问http://127.0.0.1看到 Welcome to nginx 的页面就说明启动成功了。Windows 版的坑主要有两个。一个是配置改了之后很多人直接杀进程重开其实推荐用nginx -s reload优雅重载不中断已建立的连接。另一个是某些杀毒软件会把 nginx 当可疑进程导致启动失败这时候先看logs/error.log不要盲目重装。我自己测试环境偶尔会在 Windows 上跑 nginx但生产环境不推荐毕竟 nginx 的核心优势在 Linux 上才能完全发挥。2.2 Ubuntu / Debian 系安装Linux 下安装最省心的方式是用系统包管理器。在 Ubuntu 或者 Debian 上sudo apt update sudo apt install nginx -y sudo systemctl enable --now nginx装完同样访问http://你的服务器IP验证。Ubuntu 的 nginx 包会自己处理好 systemd 服务、默认配置目录主配置在/etc/nginx/nginx.conf站点配置习惯放在/etc/nginx/sites-available/再软链到sites-enabled/。这种组织方式对于多站点管理特别友好。2.3 AlmaLinux / RHEL 系安装如果是 AlmaLinux 9 或者 CentOS Stream 这类系统sudo dnf install nginx -y sudo systemctl enable --now nginx sudo firewall-cmd --add-servicehttp --permanent sudo firewall-cmd --reload注意 Rocky/AlmaLinux 默认的文档根目录是/usr/share/nginx/html配置目录是/etc/nginx/conf.d/。很多新手在 Ubuntu 上学了一套路径换到 RHEL 系就找不到配置了其实只需要记住发行版包管理器装的 nginx主配置基本都是/etc/nginx/nginx.conf它里面通过include指令把conf.d/*.conf或者sites-enabled/*加载进来。理解了这条 include 链换任何发行版都不会迷路。2.4 源码编译安装与离线内网部署有些场景必须编译安装。比如aarch64架构、纯内网环境或者需要某些发行版包没带的模块比如 HTTP/3、stream 四层代理。编译安装的流程是这样的# 先装依赖 sudo dnf install gcc pcre-devel zlib-devel openssl-devel -y # 或者 Ubuntu: sudo apt install build-essential libpcre3-dev zlib1g-dev libssl-dev wget https://nginx.org/download/nginx-1.26.2.tar.gz tar zxf 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-http_stub_status_module make -j$(nproc) make install编译安装的核心就是把需要的模块在 configure 阶段选好比如要配置 HTTPS 就得带--with-http_ssl_module这个模块在实际配置 SSL 证书时是硬依赖缺了它listen 443 ssl;直接报错。离线环境的准备思路是在一台相同 CPU 架构、能联网的机器上把源码包和所有依赖 rpm/deb 包下载好拷进内网后离线安装configure 和 make 不需要访问外网。编译安装完启动/usr/local/nginx/sbin/nginx然后用curl -I http://127.0.0.1看到 HTTP/1.1 200 就说明一切正常。如果你用的是容器化部署方式比如docmost这类应用要配 nginx 代理或者想把harbor里内置的 nginx 升级原理也一样只是把配置入口从文件换成了容器挂载目录或者面板界面底层逻辑不变。3. 读懂 nginx.conf配置文件的结构和关键参数3.1 一棵树的思维main、events、http、server、locationnginx 配置文件是一个嵌套结构很多时候看不懂是因为没把它当成树。最外层是 main全局配置下面挂 events 和 httphttp 下面挂 serverserver 下面挂 location。一个 server 表示一个虚拟主机一个 location 表示一类路径规则。打开 nginx.conf你能看到的常见结构就是这样user nginx; worker_processes auto; # main error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; # events } http { include /etc/nginx/mime.types; default_type application/octet-stream; server { listen 80; # server server_name example.com; location / { # location root /usr/share/nginx/html; index index.html; } } }新手最容易混淆的是root和alias。root 表示把请求路径直接拼到目录后面比如root /data/www;时访问/images/a.png实际找的是/data/www/images/a.png。alias 则是替换前缀比如location /images/ { alias /data/pics/; }访问/images/a.png实际找的是/data/pics/a.png。这个区别在配置在线文件浏览这类功能时特别容易踩坑。3.2 全局与 events并发能力的第一道闸门在全局设置里最核心的是worker_processes。一般设成auto让 nginx 按 CPU 核数自动创建同等数量的 worker 进程。events块里的worker_connections表示每个 worker 能同时保持的最大连接数。nginx 的并发能力大致可以用一个公式估算最大并发连接数 ≈worker_processes×worker_connections。如果你的机器是 4 核、每 worker 连接数 1024理论上能扛住约 4000 左右的并发连接实际还要考虑系统文件描述符限制所以通常还会把worker_rlimit_nofile调到 65535 甚至更高。这里有个非常实的建议改完配置一定要执行nginx -t做语法检查。这个命令会告诉你配置文件第几行有什么问题比如少了分号、括号没闭合。直接 reload 一个写错的配置后果是 nginx 直接拒绝重载线上服务保持旧配置继续运行——听起来还好但如果你的配置文件本身是改残了的就容易出现“我明明改了配置为什么没生效”的困惑。所以规范做法是每次改完nginx -t通过后再nginx -s reload。3.3 server 与 location请求是怎么被路由的server块定义监听端口和主机名location块定义 URL 路径的处理方式。location 的匹配规则有好几种优先级从高到低大致是精确匹配最高然后是前缀匹配^~再是正则匹配~或~*最后是普通前缀匹配。我用一个实际场景解释你有两个 Web 系统要跑在同一台服务器的 80 端口一个是前后端分离的管理后台一个是面向用户的官网。方案一是根据域名区分server { listen 80; server_name admin.example.com; location / { proxy_pass http://127.0.0.1:8081; } } server { listen 80; server_name www.example.com; location / { proxy_pass http://127.0.0.1:8082; } }方案二是同一个域名用路径区分server { listen 80; server_name example.com; location /admin/ { proxy_pass http://127.0.0.1:8081/; 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 /www/ { proxy_pass http://127.0.0.1:8082/; proxy_set_header Host $host; } }这里有个特别关键、也特别多新手吃亏的细节proxy_pass后面到底带不带末尾斜杠行为完全不同。带/表示把 location 匹配到的前缀剥掉再转发比如访问/admin/login后端收到的是/login不带/则表示原样转发后端收到/admin/login。如果你的后端应用路由里没有/admin这个前缀就必须带斜杠如果后端本身就用/admin作为上下文路径就不能带。这个“斜杠决定路由前缀去留”的规则值 100 次 debug 经验。3.4 小功能也能解决大问题autoindex 在线文件浏览顺手提一个高频需求用 nginx 做一个简单的文件下载/浏览站。在 location 里开启 autoindex 即可location /files/ { alias /data/share/; autoindex on; autoindex_exact_size off; autoindex_localtime on; }autoindex_exact_size off会让文件大小显示为人类可读的 KB/MB 格式而不是精确字节数autoindex_localtime on让文件时间显示为服务器本地时间。这个配置在内网传文件、分发安装包时特别实用我经常临时用一条 location 就搞定分享需求完全不用再部署什么网盘系统。4. 实战反向代理、负载均衡和会话保持4.1 反向代理背后的逻辑反向代理是 nginx 最核心的用法。上一节的配置已经展示了最基本的proxy_pass。除了转发路径还有三个 header 建议带上Host、X-Real-IP、X-Forwarded-For。为什么要带它们因为后端应用需要知道客户端真实 IP以及原始请求的 Host做日志分析、限流、权限判断都靠这个。不加的话后端看到的 IP 全是你 nginx 服务器的地址等于把所有访问者的身份都隐藏了业务上很多功能都会出问题。nginx 还有一个proxy_redirect指令专门处理后端返回的重定向 Location 头。比如后端 HTTP 请求被转发到另外一个路径返回的 302 Location 可能是内网地址客户端直接访问就失败了。这种“nginx follow 302”的场景我通常在配置里显式处理proxy_redirect http://backend http://$host;来修正重定向地址。新手不用一次全记住但要知道有这种坑代理模式下任何“地址不对”“页面跳转 404”的问题先检查 Location 头被 nginx 改成了什么。4.2 upstream一行行看懂负载均衡负载均衡的本质是把请求分给多台后端。nginx 用upstream定义一组后端服务器upstream backend_servers { server 192.168.1.11:8080 weight2; server 192.168.1.12:8080 weight1; server 192.168.1.13:8080 backup; } server { listen 80; server_name api.example.com; location / { proxy_pass http://backend_servers; proxy_set_header Host $host; keepalive_timeout 65; } }weight表示权重weight2的机器收到两倍于weight1的请求。backup表示备用节点平时不参与服务只有其他节点都不可用时才顶上。nginx 默认是轮询如果你需要同一个客户端的请求始终打到同一台后端可以用ip_hash如果后端机器配置差异大可以用least_conn让 nginx 把请求分给当前连接数最少的节点。4.3 keepalive并发升高时的性能开关热搜里频繁出现upstream keepalive、proxy_pass keepalive说明这是大家遇到性能瓶颈时都在查的点。nginx 默认跟后端建立的连接是短连接每次请求都要重新建立 TCP 连接三次握手在高并发下开销非常明显。打开连接复用的配置其实就三行upstream backend_servers { server 127.0.0.1:8080; keepalive 32; } server { location / { proxy_pass http://backend_servers; proxy_http_version 1.1; proxy_set_header Connection ; } }keepalive 32表示每个 worker 进程缓存 32 个空闲的 upstream 连接proxy_http_version 1.1和proxy_set_header Connection 是配合 HTTP/1.1 长连接的必要项。加上之后同样的压测流量nginx 到后端的连接数会显著下降QPS 和延迟都能改善。这个配置是我在高并发调优时“性价比最高”的操作之一。4.4 高并发与 HTTP/3 方向提到nginx quic 压测和net::ERR_QUIC_PROTOCOL_ERROR 200 (OK)这是很多人在试用 HTTP/3 时遇到的。nginx 官方从 1.25 版本开始提供了 HTTP/3 支持的实验性模块编译时需要加--with-http_v3_module配置上用listen 443 quic reuseport;这类指令。要做 QUIC 压测传统的 ab、wrk 是不行的得用支持 HTTP/3 的客户端比如新版的 curl带 http3 支持或者 quiche 的客户端工具。如果浏览器访问 HTTPS 站点时报net::ERR_QUIC_PROTOCOL_ERROR且状态码 200 后立刻断开通常是 HTTP/3 的 UDP 443 端口被防火墙拦了或者 nginx 的 QUIC 模块与当前浏览器不兼容。排错顺序一般是先确保 UDP 443 放行再确认 HTTP/3 模块编译正确最后清掉浏览器缓存重试。这个方向对入门者来说偏深知道排查路径就够了不必一上来就折腾。5. 给站点加 HTTPS自签名证书的交互式生成和配置5.1 为什么需要自签名证书正式线上环境一般用 Lets Encrypt 这类免费证书但内网测试、开发环境、或者临时演示往往拿不到公网域名这时候自签名证书就派上用场了。它的作用是让 nginx 能启动 443 端口的 HTTPS 服务虽然浏览器会提示“不安全”但你需要的只是加密通道本身这在不少企业内部场景里完全够用。5.2 交互式生成自签名证书最顺手的生成方式是 openssl 的交互式命令openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365这条命令会让你交互式输入国家CN、省份、城市、组织名、通用名等一堆信息可以直接一路回车但 Common Name 建议填你的服务器 IP 或域名否则浏览器报错信息会更让人困惑。执行完会得到两个文件私钥server.key和证书server.crt。注意server.key是私钥文件千万不能泄露也不能提交到 Git 仓库。5.3 配置 HTTPS 并让 HTTP 自动跳转把证书放到一个固定目录比如/etc/nginx/certs/然后配置server { listen 443 ssl; http2 on; server_name example.com; ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/server.key; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } server { listen 80; server_name example.com; return 301 https://$host$request_uri; }http2 on开启 HTTP/2多路复用能让页面加载明显变快。return 301 https://$host$request_uri;是常见的把 HTTP 流量全部迁到 HTTPS 的做法。配置好之后记得nginx -t再 reload然后可以用openssl s_client -connect 127.0.0.1:443 -brief快速验证证书是否生效、链路是否正常。如果你用的是 Docker、Nginx Proxy Manager 这类容器化面板配置入口虽然变成界面操作了但背后原理一样熟悉这套文件配置后到面板上也是同样的心智模型。6. 日常运维排错常见报错的定位与解决6.1 高频错误速查表把我在实际运维和帮人排查时遇到最多的几类问题整理成一张表可以当手册用现象大概率原因解决办法浏览器 403 Forbidden目录权限不足或目标目录下没有 index 文件检查目录执行权限确认 index 指令或者 autoindex 是否开启RHEL 系还要看 SELinux502 Bad Gateway后端服务没起来或 nginx 连不上后端的 host:portcurl 测试后端端口确认 upstream 里的地址端口正确看后端进程是否存活重定向循环或 404proxy_pass 的斜杠问题或 proxy_redirect 没处理检查 location 与 proxy_pass 末尾是否有 /查看 Location 响应头[emerg] createfile() d:/...Windows 下路径不存在、权限不足或目录被占用确认路径存在且可写用绝对路径检查是否杀毒进程占用nginx 进程显示 inactivesystemd 服务已停止或 enable 没设systemctl status nginxsystemctl enable --now nginxERR_QUIC_PROTOCOL_ERRORUDP 443 被拦或 QUIC 模块/浏览器兼容问题放行 UDP 443清缓存确认 HTTP/3 模块编译参数连接数一高就拒绝服务文件描述符限制过小调高 worker_rlimit_nofile 和系统 ulimit这里想特别展开说的是nginx: [emerg] createfile() d:/phpstudy_pro/www/admin2.com/nginx.htaccess这类 Windows 报错。它其实很容易定位报错信息已经把路径写出来了问题要么是这个路径不存在/没有写入权限要么是某个进程锁住了文件。我看到很多新手一遇到 emerg 就慌其实[emerg]代表致命错误nginx 确实启动不了但你只要冷静看第一行路径然后逐个检查路径、权限、占用往往五分钟解决。6.2 排错三板斧分享一套我自己的排错流程不管问题是 403、502 还是配置起不来都能用执行nginx -t确认语法层面没问题它能最快速地排除因手误导致的配置错误。看日志。错误日志默认在/var/log/nginx/error.log或者编译安装目录下的logs/error.log访问日志在/var/log/nginx/access.log用tail -f实时盯。nginx 的日志写得相当直白大部分问题一眼就能看到根因。用curl -v直接模拟请求看 HTTP 状态码、响应头、转发链路的每一跳。比如curl -v http://127.0.0.1/admin你就知道请求到了 nginx 之后到底发生了什么事。6.3 从一次故障看排查思路最后讲一个我印象很深的真实案例。有次一个项目的内网文件下载链接突然全部 403我当时第一反应是磁盘权限被改了。检查目录权限没问题应用也有读权限最后发现是 SELinux 开启了强制模式nginx 访问非标准目录时被拦截。解决办法很简单sudo setsebool -P httpd_can_network_connect 1或者给对应目录加上正确的 SELinux 上下文问题就消失了。这类问题在 CentOS/RHEL 系特别常见如果你用的是这类系统遇到权限相关报错不要光盯着 chmod也查一下 SELinux。写到这nginx 入门的全流程基本过完了一遍。我个人在实际操作中最深的一个体会是nginx 的配置知识不是靠背出来的而是靠一次次真实故障喂出来的。你只要亲手装过一次、配过一次反代、排过一次 403后面看任何 nginx 资料都会快很多。最后再分享一个小技巧每次准备改动线上 nginx 配置前先把当前能正常运行的配置完整备份一份到带时间戳的文件里比如nginx.conf.bak.20250601。哪怕你只改了一行也建议备份。这个习惯在关键时刻帮你省下的时间远比备份动作本身多得多。当你把配置文件当成一棵树去理解把排错流程当成固定套路去执行nginx 就不再是一个让人望而却步的黑盒了。