Chapter 01

认识 Nginx 与安装

理解 web 服务器的职责,搞清 Nginx 为何用事件驱动打败了 Apache 的进程模型,掌握 master-worker 架构、安装与启停。

1.1 web 服务器到底做什么

当你在浏览器输入一个网址,背后发生的事情是:浏览器与服务器建立 TCP 连接,发出一条 HTTP 请求(比如 GET /index.html),服务器读取请求、找到对应资源、返回一条 HTTP 响应。承担"接收请求、返回响应"这个角色的程序,就是 web 服务器

web 服务器的活儿主要有三类:发静态文件(HTML/CSS/JS/图片)、把动态请求转交给后端应用(PHP/Node/Java 进程)、以及处理网络层的杂事(TLS 加密、压缩、缓存、限流)。Nginx 三样都擅长。

web 服务器(Web Server)
接收 HTTP 请求、返回响应的程序。狭义指发静态文件的服务器(Nginx、Apache),广义也包含应用服务器。
反向代理(Reverse Proxy)
代替后端服务器接收客户端请求,再转发给内网真正处理请求的应用,把响应带回客户端。客户端并不知道背后有几台机器。
正向代理(Forward Proxy)
代替客户端去访问外部服务器(如公司出口代理、科学上网)。方向与反向代理相反:一个代理"客户端",一个代理"服务端"。
C10K 问题
指单台服务器同时处理 1 万(10K)并发连接的挑战。传统"一连接一线程"模型在此规模下因内存和上下文切换而崩溃,催生了 Nginx 的事件驱动设计。
阻塞 I/O(Blocking I/O)
线程发起读写后一直卡住等待结果,期间什么也干不了。连接多时需要大量线程,每个线程都在"傻等"。
事件驱动(Event-driven)
用一个事件循环监听大量连接的"可读/可写"事件,哪个就绪就处理哪个,单线程即可复用成千上万连接,不为每个连接开线程。

1.2 Nginx vs Apache:两种并发哲学

Apache(尤其经典的 prefork/worker MPM)的模型是每个连接分配一个进程或线程。这个模型直观、稳定,但代价高:1 万并发就要 1 万个线程,每个线程占几 MB 栈内存,光内存就是几十 GB,CPU 大量时间耗在线程切换上。

Nginx 的模型是少量 worker 进程 + 事件循环。一个 worker 通过 epoll(Linux)/kqueue(BSD/macOS)同时管理上万连接,只在连接真正"有数据可处理"时才去处理它,其余时间不占用线程。这就是它能用极少内存扛住 C10K 甚至 C1M 的秘密。

维度NginxApache(prefork)
并发模型事件驱动 / 异步非阻塞每连接一进程/线程
高并发内存极低(连接≈几 KB)高(线程≈几 MB)
静态文件性能极强(sendfile 零拷贝)中等
动态内容需反代给 PHP-FPM/应用可内嵌 mod_php
配置方式集中式 nginx.conf.htaccess 分布式 + 主配置
典型角色反代/均衡/静态/TLS 终止传统 LAMP 应用服务器
不是"谁更好",而是"分工不同"

现实中常见组合是 Nginx 在最前面做反向代理、负载均衡、静态资源和 TLS 终止,把动态请求转发给后面的应用服务器(可能就是 Apache + PHP,或 Node、Java 等)。二者并非你死我活。

1.3 master-worker 架构

Nginx 启动后不是一个进程,而是一组:一个 master 进程 + 若干 worker 进程

master 进程
以 root 启动,负责读取配置、绑定端口、管理 worker 生命周期、响应信号(重载/退出)。它不处理任何客户端请求。
worker 进程
真正干活的进程,通常降权到普通用户运行。每个 worker 独立跑一个事件循环,处理连接。数量一般设为 CPU 核心数。
cache manager / cache loader
可选的辅助进程,负责管理磁盘缓存(proxy_cache)的过期清理与启动时加载。
# 看看 Nginx 的进程树
$ ps aux | grep nginx
root      1200  nginx: master process /usr/sbin/nginx
www-data  1201  nginx: worker process
www-data  1202  nginx: worker process
www-data  1203  nginx: worker process
www-data  1204  nginx: worker process

这种设计的好处:master 用 root 权限绑定 80/443 端口后,worker 降权运行更安全;重载配置时 master 可以优雅地启动新 worker、让旧 worker 处理完手头请求再退出,实现零停机重载(第 2 章详解)。

1.4 安装 Nginx

# Ubuntu / Debian
$ sudo apt update
$ sudo apt install nginx

# CentOS / RHEL / Rocky
$ sudo dnf install nginx

# macOS(Homebrew)
$ brew install nginx

# 验证版本与编译参数
$ nginx -v
nginx version: nginx/1.27.0
$ nginx -V   # 大写 V 显示编译时的模块
稳定版 vs 主线版

Nginx 有两条线:stable(偶数小版本,如 1.26.x)只修 bug,适合生产;mainline(奇数,如 1.27.x)含新特性。官方其实推荐大多数场景用 mainline。发行版仓库通常给的是较旧的 stable,需要新特性可加官方源。

1.5 启停与常用命令

# 用 systemd 管理(发行版安装的推荐方式)
$ sudo systemctl start nginx      # 启动
$ sudo systemctl stop nginx       # 停止
$ sudo systemctl restart nginx    # 重启(会短暂中断)
$ sudo systemctl reload nginx     # 平滑重载配置(不中断连接)
$ sudo systemctl enable nginx     # 开机自启
$ sudo systemctl status nginx     # 查看状态

# 用 nginx 命令直接控制
$ sudo nginx                       # 启动
$ sudo nginx -s reload             # 重载配置
$ sudo nginx -s stop               # 立即停止
$ sudo nginx -s quit               # 优雅停止(处理完当前请求)
$ sudo nginx -t                    # 检查配置语法是否正确
改配置后先 nginx -t 再 reload

养成肌肉记忆:任何配置改动后,先跑 nginx -t 验证语法,通过了再 reload。直接 reload 一个语法错误的配置,Nginx 会拒绝加载并沿用旧配置——虽然不会挂,但你的改动没生效还不自知。

1.6 关键目录结构

以 Ubuntu/Debian 为例(不同发行版路径略有差异):

路径作用
/etc/nginx/nginx.conf主配置文件,全局设置入口
/etc/nginx/conf.d/额外配置片段,被主配置 include
/etc/nginx/sites-available/所有可用站点配置(Debian 系约定)
/etc/nginx/sites-enabled/已启用站点,软链到 sites-available
/var/log/nginx/access.log访问日志
/var/log/nginx/error.log错误日志(排障第一站)
/var/www/html/默认静态站点根目录
/usr/share/nginx/默认页面、错误页等

启用/停用一个站点的 Debian 惯用法,就是在 sites-enabled/ 里创建或删除软链接:

$ sudo ln -s /etc/nginx/sites-available/myapp \
       /etc/nginx/sites-enabled/myapp   # 启用
$ sudo rm /etc/nginx/sites-enabled/myapp   # 停用
$ sudo nginx -t && sudo systemctl reload nginx

1.7 第一次验证:默认欢迎页

安装并启动后,访问 http://服务器IP/ 应该看到 "Welcome to nginx!" 页面。若看不到,按顺序排查:

1.8 小结与下一步