【Linux从入门到精通】第32篇:Nginx入门——高性能Web服务器搭建

目录

一、引言:Nginx为什么这么流行?

二、安装与基础管理

[2.1 安装Nginx](#2.1 安装Nginx)

[2.2 启动、停止、重载](#2.2 启动、停止、重载)

[2.3 配置文件结构](#2.3 配置文件结构)

三、虚拟主机:一台服务器跑多个网站

[3.1 什么是虚拟主机?](#3.1 什么是虚拟主机?)

[3.2 实战:配置两个虚拟主机](#3.2 实战:配置两个虚拟主机)

[3.3 server_name的通配符匹配](#3.3 server_name的通配符匹配)

四、反向代理:Nginx的第二重身份

[4.1 什么是反向代理?](#4.1 什么是反向代理?)

[4.2 实战:用Nginx反向代理Node.js应用](#4.2 实战:用Nginx反向代理Node.js应用)

[五、nginx -s reload:平滑重启的秘密](#五、nginx -s reload:平滑重启的秘密)

[5.1 为什么需要平滑重启?](#5.1 为什么需要平滑重启?)

[5.2 reload的完整流程](#5.2 reload的完整流程)

[5.3 reload vs restart vs stop](#5.3 reload vs restart vs stop)

[5.4 可能遇到的问题](#5.4 可能遇到的问题)

六、本篇小结

动手练习

排错小技巧

七、下篇预告


一、引言:Nginx为什么这么流行?

如果你去问后端开发或运维工程师"用什么部署Web应用",答案十有八九是Nginx

它凭什么成为事实标准?几个关键数字可以说明问题:

  • C10k问题的终结者:Nginx采用事件驱动架构,一台服务器就能轻松处理上万个并发连接,而传统Apache在几百个连接时已经吃力

  • 内存占用极低:空闲状态下仅占用几MB内存,即使在高并发场景下也远低于同类产品

  • 功能三合一:既是Web服务器(托管静态文件)、又是反向代理(转发请求到后端)、还是负载均衡器(分发流量到多台服务器)

简单说:一个软件,解决三个问题,而且全部免费开源

二、安装与基础管理

2.1 安装Nginx

Ubuntu/Debian系统默认仓库已经包含Nginx,一条命令即可安装:

bash

复制代码
sudo apt update && sudo apt install nginx -y

CentOS/RHEL需要先启用EPEL仓库:

bash

复制代码
sudo dnf install epel-release -y   # CentOS 8+ / Fedora
sudo dnf install nginx -y

安装完成后验证版本:

bash

复制代码
nginx -v

2.2 启动、停止、重载

Nginx作为systemd服务运行,用我们第15篇学过的systemctl管理:

bash

复制代码
sudo systemctl start nginx       # 启动
sudo systemctl stop nginx        # 停止
sudo systemctl restart nginx     # 重启(会中断服务)
sudo systemctl reload nginx      # 平滑重载(不中断服务)
sudo systemctl status nginx      # 查看状态
sudo systemctl enable nginx      # 开机自启

2.3 配置文件结构

Nginx配置文件的默认位置是/etc/nginx/,核心文件是nginx.conf。现代Nginx采用模块化设计,主配置文件通过include引入子目录中的配置片段:

bash

复制代码
/etc/nginx/
├── nginx.conf              # 主配置文件
├── sites-available/        # 所有可用的站点配置
│   ├── default
│   └── example.com
└── sites-enabled/          # 已启用的站点(软链接到sites-available)
    └── example.com -> ../sites-available/example.com

约定 :把每个站点的配置单独放在sites-available/下,需要启用时创建一个软链接到sites-enabled/。这样需要下线某个站点时,只删除软链接即可,原配置文件保留备用。

每次修改配置后,先测试语法再重载:

bash

复制代码
sudo nginx -t                 # 测试配置语法
sudo systemctl reload nginx   # 确认无误后平滑重载

三、虚拟主机:一台服务器跑多个网站

3.1 什么是虚拟主机?

在Nginx出现之前,一个域名对应一个IP、一台服务器只能跑一个网站。Nginx的虚拟主机(Server Block) 打破了这种绑定:一台服务器可以托管多个域名,每个域名对应不同的网站目录

Nginx通过server_name指令来判断当前请求的域名,然后匹配到对应的server块处理。

3.2 实战:配置两个虚拟主机

假设你有一台服务器,需要托管两个网站:blog.example.com对应博客,shop.example.com对应商城。

第一步:创建网站目录和首页

bash

复制代码
sudo mkdir -p /var/www/blog.example.com
sudo mkdir -p /var/www/shop.example.com

# 创建示例首页
echo '<h1>Welcome to Blog</h1>' | sudo tee /var/www/blog.example.com/index.html
echo '<h1>Welcome to Shop</h1>' | sudo tee /var/www/shop.example.com/index.html

# 设置权限
sudo chown -R www-data:www-data /var/www/blog.example.com
sudo chown -R www-data:www-data /var/www/shop.example.com

第二步:创建虚拟主机配置文件

/etc/nginx/sites-available/blog.example.com

nginx

复制代码
server {
    listen 80;
    server_name blog.example.com;

    root /var/www/blog.example.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

/etc/nginx/sites-available/shop.example.com

nginx

复制代码
server {
    listen 80;
    server_name shop.example.com;

    root /var/www/shop.example.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

关键指令解释

  • listen 80:监听HTTP的默认80端口

  • server_name blog.example.com:这个server块只处理域名匹配的请求

  • root /var/www/blog.example.com:网站文件的根目录

  • index index.html:默认首页文件名

  • try_files $uri $uri/ =404:先尝试匹配请求的文件路径,找不到返回404

第三步:启用站点并重载

bash

复制代码
# 创建软链接启用站点
sudo ln -s /etc/nginx/sites-available/blog.example.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/shop.example.com /etc/nginx/sites-enabled/

# 测试语法
sudo nginx -t

# 平滑重载
sudo systemctl reload nginx

现在访问http://blog.example.comhttp://shop.example.com,会看到不同的网站内容。

3.3 server_name的通配符匹配

server_name支持通配符,这在管理大量子域名时非常方便:

nginx

复制代码
# 匹配所有 example.com 的子域名
server {
    listen 80;
    server_name *.example.com;
    ...
}

# 精确匹配多个域名
server {
    listen 80;
    server_name example.com www.example.com;
    ...
}

匹配优先级 :精确名称 > *开头的通配符 > *结尾的通配符 > 正则表达式。

四、反向代理:Nginx的第二重身份

4.1 什么是反向代理?

先理解正向代理:你的浏览器 → 代理服务器 → 目标网站。你主动找代理,让它帮你访问外界

反向代理正好反过来:用户的请求 → Nginx → 内部应用服务器。用户根本不知道后面还有谁,他只和Nginx对话

反向代理的好处:

  • 隐藏后端:内部应用服务器不需要暴露公网IP

  • 统一入口:多个应用(Node.js/Python/Go)通过同一个80端口对外服务

  • SSL终结:在Nginx处理HTTPS,内部服务器只需处理HTTP

4.2 实战:用Nginx反向代理Node.js应用

假设你有一个Node.js应用运行在本地3000端口,想让外部用户通过app.example.com访问,而用户不知道3000端口的存在。

nginx

复制代码
server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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_pass http://127.0.0.1:3000核心指令------把匹配到的请求全部转发到本机的3000端口

  • proxy_set_header Host $host:把原始请求的域名传给后端(否则后端收到的Host是127.0.0.1)

  • proxy_set_header X-Real-IP $remote_addr:把用户的真实IP传给后端(否则后端只能看到127.0.0.1)

  • proxy_set_header X-Forwarded-For:记录完整的代理链,用户的真实IP会追加到这个头部

  • proxy_set_header X-Forwarded-Proto $scheme:告诉后端原始请求是HTTP还是HTTPS

proxy_pass的斜杠陷阱

proxy_pass中地址末尾有没有斜杠,行为截然不同:

配置 请求 /api/users 转发地址
proxy_pass http://backend/ /api/users http://backend/users
proxy_pass http://backend /api/users http://backend/api/users

加上末尾斜杠,location中匹配到的路径会被移除;不加斜杠,完整URI原样追加。这个细节经常让人踩坑。

五、nginx -s reload:平滑重启的秘密

5.1 为什么需要平滑重启?

传统的systemctl restart nginx会先停止所有worker进程,再启动新的。这会导致一个短暂的"真空期"------此时Nginx无法处理任何请求。

对于生产环境,哪怕中断0.1秒都可能导致部分用户请求失败。nginx -s reload就是为解决这个问题设计的。

5.2 reload的完整流程

nginx -s reload向master进程发送SIGHUP信号,master进程随后执行以下步骤:

第一步:检查配置语法

master进程首先对新配置文件做语法检查。如果检查失败,继续使用旧配置运行,服务不受任何影响。

第二步:打开新的监听端口

如果新配置中增加了之前没有的监听端口(比如新增了443的SSL配置),master进程会打开这些新端口。所有worker进程作为master的子进程,会继承这些端口。

第三步:启动新worker进程

master用新配置 启动一批新的worker进程。注意:此时新老worker同时存在,新连接由新worker处理,老worker继续处理已建立的请求。

第四步:通知老worker优雅退出

master向老worker发送SIGQUIT信号。老worker收到后:

  1. 关闭监听的端口句柄(不再接收新连接)

  2. 处理完当前正在进行的请求

  3. 主动退出

示意图

text

复制代码
reload前:[老worker-1] [老worker-2] [老worker-3] [老worker-4]
                ↓ master收到reload信号 ↓
过渡期: [老worker-1] [老worker-2] [老worker-3] [老worker-4]
         [新worker-1] [新worker-2] [新worker-3] [新worker-4]
                ↓ 老worker处理完已有请求后退出 ↓
reload后:[新worker-1] [新worker-2] [新worker-3] [新worker-4]

5.3 reload vs restart vs stop

命令 底层信号 行为 是否中断服务
nginx -s reload SIGHUP 新配置启动新worker,老worker优雅退出
nginx -s stop SIGTERM 立即停止所有worker
nginx -s quit SIGQUIT 优雅停止:处理完当前请求后退出 只处理完已有请求
systemctl restart 先stop再start 完全停止再启动

日常修改配置后,永远优先使用nginx -s reloadsystemctl reload nginx

5.4 可能遇到的问题

老worker长时间不退出:某些请求可能处理得很慢(如大文件上传),导致老worker一直等待。新版本Nginx提供了worker_shutdown_timeout指令,可以设置最长等待时间,超时后强制退出。

六、本篇小结

安装与管理

bash

复制代码
sudo apt install nginx
sudo nginx -t                    # 测试配置
sudo systemctl reload nginx      # 平滑重载

虚拟主机核心配置

nginx

复制代码
server {
    listen 80;
    server_name example.com;     # 域名匹配[citation:5]
    root /var/www/example.com;   # 网站根目录
    index index.html;            # 默认首页
}

反向代理核心配置

nginx

复制代码
location / {
    proxy_pass http://127.0.0.1:3000;      # 转发目标
    proxy_set_header Host $host;            # 传递域名
    proxy_set_header X-Real-IP $remote_addr; # 传递真实IP
}

平滑重启原理

master进程收到reload信号 → 检查语法 → 开新端口 → 启新worker → 老worker优雅退出 → 全程不中断服务

动手练习

bash

复制代码
# 1. 安装并启动Nginx
sudo apt update && sudo apt install nginx -y
sudo systemctl start nginx

# 2. 查看默认页面(本机访问)
curl http://localhost

# 3. 创建自己的虚拟主机配置
sudo mkdir -p /var/www/test.local
echo "My Test Site" | sudo tee /var/www/test.local/index.html
sudo vim /etc/nginx/sites-available/test.local
# 填入server块配置(listen 80; server_name test.local; root /var/www/test.local)

sudo ln -s /etc/nginx/sites-available/test.local /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

# 4. 本机测试(修改hosts或直接用curl指定Host头)
curl -H "Host: test.local" http://localhost

# 5. 观察worker进程变化
ps aux | grep nginx
# 修改个配置,执行reload,再次查看worker进程(PID应该变化)

排错小技巧

502 Bad Gateway :后端服务挂了或proxy_pass地址写错了,检查后端是否在运行、端口是否匹配。

404 Not Foundroot路径不对或文件不存在,确认网站目录下有首页文件。

403 Forbidden :权限问题,chown -R www-data:www-data改属主。

七、下篇预告

Nginx常常搭配数据库一起工作。下一篇我们将进入数据库MySQL/MariaDB的安装与基础调优 ,学习数据库的安全初始化流程、创建用户和授权、以及my.cnf中几个必须调整的内存参数。这是完整Web应用栈的第二块基石。


延伸思考nginx -s reload为什么比restart更优雅?打个比方:restart相当于饭店关门装修------新客旧客全请出去。reload相当于厨师换菜单------已经在用餐的顾客不受影响,新来的顾客按新菜单点菜。这就是生产环境的"零停机更新"。

相关推荐
ZenosDoron3 小时前
Linux 中,rm -r 和 -f
linux·运维·服务器
Hello.Reader3 小时前
Ubuntu 上正确安装 Kali 虚拟机、Docker 与 kail 工具指南
linux·ubuntu·docker
WarPigs3 小时前
Windows IIS开启和配置服务器
运维·服务器
原来是猿3 小时前
Linux UDP Socket 编程入门:Echo Server/Client实现
linux·运维·udp
中微子3 小时前
突然爆火的Warp 终端,开源1天破 4w Stars
linux·人工智能·开源
半斤八两2113 小时前
个人服务器发送消息至飞书
服务器
pengyi8710153 小时前
共享 IP 池多人使用 分层权限与配额管理方案
运维·服务器·网络
计算机安禾3 小时前
【Linux从入门到精通】第33篇:数据库MySQL/MariaDB安装与基础调优
linux·数据库·mysql
楼兰公子4 小时前
读取rpi摄像头
linux·服务器·算法