Nginx 教程

高性能的 HTTP 和反向代理服务器详解

目录

1. Nginx 简介

学习前思考

  1. 您对Web服务器的工作原理有哪些了解?Web服务器在网络架构中起什么作用?
  2. 传统的Web服务器(如Apache)可能面临哪些性能挑战?
  3. 您认为一个理想的Web服务器应该具备哪些特性?
  4. 反向代理和负载均衡对于Web应用有什么重要性?
  5. 您了解Nginx与其他Web服务器的主要区别吗?

在学习本章内容前,请先思考以上问题。带着问题学习,能够帮助您更好地理解和掌握知识点。

Nginx(发音为"engine x")是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。本章将介绍Nginx的基本概念、特点和应用场景。

1.1 什么是 Nginx

Nginx 是一个开源的 Web 服务器,以其高性能、稳定性、丰富的功能集、简单的配置和低资源消耗而闻名。它可以用作 Web 服务器、反向代理服务器、负载均衡器、邮件代理和 HTTP 缓存。

1.2 Nginx 的历史与发展

Nginx 的发展历程:

1.3 为什么选择 Nginx

Nginx 相比其他 Web 服务器有以下优势:

1.4 Nginx 的主要应用场景

小知识:Nginx 的名称来源于"引擎 X"(Engine X),象征其强大的引擎特性。而 Apache HTTP Server 更侧重于功能的全面性,Nginx 则专注于核心功能的高性能实现。

1.5 Nginx 与其他 Web 服务器的比较

特性 Nginx Apache HTTP Server IIS
处理模型 异步非阻塞事件驱动 多进程/多线程 多线程
资源消耗 中到高 中到高
高并发处理 优秀 一般 一般
配置复杂度 简单 中等 图形界面,较简单
操作系统 跨平台 跨平台 仅 Windows
动态内容 需要通过代理 内置支持 (mod_php 等) 内置支持 (ASP.NET)

2. 安装与基本配置

学习前思考

  1. 您在选择软件安装方式时通常考虑哪些因素(包管理器vs.源码编译)?
  2. 在生产环境中安装服务器软件时,应该注意哪些安全和稳定性问题?
  3. 配置文件的组织结构对于系统维护有什么重要性?
  4. 如何判断一个服务器配置是否合理且安全?
  5. 您如何计划对服务器软件进行版本升级和维护?

在学习本章内容前,请先思考以上问题。带着问题学习,能够帮助您更好地理解和掌握知识点。

本章将介绍如何在不同操作系统上安装 Nginx,并了解其基本配置文件结构和常用命令。

2.1 安装方法

2.1.1 在 Linux 上安装

大多数 Linux 发行版都在其官方软件仓库中提供 Nginx 包。

Ubuntu/Debian:

sudo apt update
sudo apt install nginx

CentOS/RHEL:

sudo yum install epel-release
sudo yum install nginx

使用官方仓库安装最新版本(推荐):

# Ubuntu/Debian
sudo apt install curl gnupg2 ca-certificates lsb-release
echo "deb https://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
sudo apt update
sudo apt install nginx

# CentOS/RHEL
sudo yum install yum-utils
sudo tee /etc/yum.repos.d/nginx.repo << EOF
[nginx]
name=nginx repo
baseurl=https://nginx.org/packages/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
EOF
sudo yum install nginx

2.1.2 在 Windows 上安装

Nginx 提供 Windows 版本的二进制文件:

  1. nginx.org 下载 Windows 版本的 zip 文件
  2. 解压到任意目录,如 C:\nginx
  3. 打开命令提示符,进入 Nginx 目录
  4. 运行 start nginx 启动服务器

2.1.3 在 macOS 上安装

使用 Homebrew 安装 Nginx:

brew install nginx

2.1.4 从源码编译安装

如果需要自定义编译选项或使用特定模块,可以从源码编译:

wget https://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0

./configure --prefix=/usr/local/nginx \
            --with-http_ssl_module \
            --with-http_v2_module \
            --with-http_realip_module \
            --with-http_stub_status_module

make
sudo make install

提示:使用包管理器安装 Nginx 通常会自动配置系统服务,而手动安装则需要额外步骤来配置自启动服务。

2.2 基本配置文件结构

Nginx 的配置文件通常位于 /etc/nginx/ 目录(Linux)或安装目录下的 conf 文件夹(Windows)。主配置文件是 nginx.conf,它包含其他配置文件的引用。

2.2.1 配置文件层次结构

2.2.2 nginx.conf 的基本结构

user nginx;              # 运行 Nginx 的用户
worker_processes auto;   # 工作进程数,通常设置为 CPU 核心数
error_log /var/log/nginx/error.log warn;  # 错误日志
pid /var/run/nginx.pid;  # 存储主进程 PID 的文件

events {
    worker_connections 1024;  # 每个工作进程的最大连接数
}

http {
    include /etc/nginx/mime.types;  # 包含 MIME 类型定义
    default_type application/octet-stream;  # 默认 MIME 类型
    
    # 日志格式定义
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log /var/log/nginx/access.log main;  # 访问日志
    
    sendfile on;  # 启用 sendfile 系统调用
    tcp_nopush on;  # 优化网络包传输
    tcp_nodelay on;  # 禁用 Nagle 算法
    keepalive_timeout 65;  # 保持连接超时时间
    
    # 包含其他配置文件
    include /etc/nginx/conf.d/*.conf;
}

2.2.3 基本的 server 块

/etc/nginx/conf.d/default.conf 中:

server {
    listen 80;  # 监听端口
    server_name example.com www.example.com;  # 服务器名称
    
    location / {
        root /usr/share/nginx/html;  # 根目录
        index index.html index.htm;  # 默认文件
    }
    
    # 错误页面
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

2.3 常用命令

Nginx 提供了多种命令来控制服务器操作:

2.3.1 基本控制命令

命令 描述
nginxsystemctl start nginx 启动 Nginx
nginx -s stopsystemctl stop nginx 快速停止 Nginx
nginx -s quitsystemctl quit nginx 优雅停止 Nginx(等待工作进程处理完现有请求)
nginx -s reloadsystemctl reload nginx 重新加载配置文件
nginx -s reopen 重新打开日志文件
nginx -t 测试配置文件是否有语法错误
nginx -v 显示 Nginx 版本
nginx -V 显示 Nginx 版本、编译参数和配置参数

2.3.2 在 Linux 中使用 systemd 管理 Nginx

sudo systemctl start nginx    # 启动 Nginx
sudo systemctl stop nginx     # 停止 Nginx
sudo systemctl restart nginx  # 重启 Nginx
sudo systemctl reload nginx   # 重新加载配置
sudo systemctl status nginx   # 查看 Nginx 状态
sudo systemctl enable nginx   # 设置开机自启动
sudo systemctl disable nginx  # 禁用开机自启动

2.3.3 Windows 下的命令

在 Windows 命令提示符中:

cd C:\nginx
start nginx           # 启动 Nginx
nginx -s stop         # 停止 Nginx
nginx -s quit         # 优雅停止
nginx -s reload       # 重新加载配置
nginx -s reopen       # 重新打开日志

实例:配置验证最佳实践

在更改配置后,始终进行验证并使用 reload 命令:

sudo nginx -t && sudo systemctl reload nginx

这样可以确保只有在配置正确的情况下才会重新加载 Nginx。

3. 核心概念

学习前思考

  1. 服务器软件的架构设计如何影响其性能和可扩展性?
  2. 为什么理解主-工作进程模型对于配置和调优Nginx很重要?
  3. 配置文件的结构和语法规则如何影响服务器管理的难易程度?
  4. 在设计服务器路由规则时,应该考虑哪些因素?
  5. 变量在Web服务器配置中有哪些用途?它们如何增强服务器的灵活性?

在学习本章内容前,请先思考以上问题。带着问题学习,能够帮助您更好地理解和掌握知识点。

要熟练使用 Nginx,需要了解其核心概念和架构设计。本章将深入探讨 Nginx 的工作原理以及关键配置元素。

3.1 Nginx 架构

Nginx 采用主从架构,由一个 master 进程和多个 worker 进程组成:

Master Process
读取配置、管理工作进程
Worker Process 1
Worker Process 2
Worker Process n
Client 请求
Client 请求
Client 请求

3.1.1 Master 进程

3.1.2 Worker 进程

3.1.3 事件驱动模型

Nginx 使用异步非阻塞 I/O 模型处理请求:

小知识:一个 Nginx worker 进程可以处理 10,000+ 并发连接,而传统的多线程服务器每个线程通常只能处理一个连接。

3.2 配置结构与语法

Nginx 配置文件使用简单直观的语法,基于块和指令组织:

3.2.1 指令和块

3.2.2 主要配置上下文

3.2.3 指令继承与覆盖

大多数指令都遵循自上而下的继承规则:

3.2.4 配置文件结构示例

# 全局配置 (main 上下文)
user nginx;
worker_processes 4;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

# 事件配置 (events 上下文)
events {
    worker_connections 1024;
}

# HTTP 配置 (http 上下文)
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # 日志配置
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;
    
    # 全局 HTTP 选项
    sendfile on;
    keepalive_timeout 65;
    
    # 虚拟主机配置 (server 上下文)
    server {
        listen 80;
        server_name example.com;
        
        # URI 匹配配置 (location 上下文)
        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
        
        location /api/ {
            proxy_pass http://backend_servers;
        }
    }
    
    # 另一个虚拟主机
    server {
        listen 80;
        server_name sub.example.com;
        
        location / {
            root /var/www/sub;
            index index.html;
        }
    }
}

3.3 Server 块

Server 块定义了虚拟服务器,允许 Nginx 在单个 IP 地址上处理多个域名。每个 server 块需要包含 listen 指令(指定端口)和 server_name 指令(指定域名)。

3.3.1 基本 server 块配置

server {
    listen 80;                  # 监听端口
    server_name example.com;    # 服务器名称
    
    # 其他配置...
}

3.3.2 server_name 指令

server_name 指令用于区分请求应该由哪个 server 块处理,支持多种匹配模式:

3.3.3 匹配优先级

当一个请求匹配多个 server 块时,Nginx 按以下优先级选择:

  1. 精确匹配的 server_name
  2. 以 * 开头的最长通配符名称(如:*.example.com)
  3. 以 * 结尾的最长通配符名称(如:mail.*)
  4. 第一个匹配的正则表达式
  5. 默认 server 块(使用 listen 80 default_server; 指定)

3.3.4 默认 server 块

当请求的 Host 头不匹配任何 server_name 时,Nginx 使用默认 server 块:

server {
    listen 80 default_server;
    server_name _;
    
    return 404 "No server is configured for this host.";
}

实例:多域名配置

server {
    listen 80;
    server_name example.com www.example.com;
    
    root /var/www/example;
    index index.html;
}

server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://localhost:8080;
    }
}

server {
    listen 80 default_server;
    server_name _;
    
    return 444;  # 关闭连接,不返回任何内容
}

3.4 Location 块

Location 块用于根据请求的 URI 处理不同的内容或逻辑,是 Nginx 配置中最灵活的部分。

3.4.1 Location 匹配类型

3.4.2 Location 匹配优先级

Nginx 按以下顺序选择匹配的 location 块:

  1. 精确匹配(=
  2. 优先前缀匹配(^~
  3. 正则表达式匹配(~~*),按照它们在配置文件中的出现顺序
  4. 前缀匹配,选择最长匹配

3.4.3 常用 location 配置

# 精确匹配首页
location = / {
    root /var/www/html;
    index index.html;
}

# 处理静态文件
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    root /var/www/static;
    expires 30d;  # 设置缓存时间
}

# API 请求代理到后端
location /api/ {
    proxy_pass http://backend_servers;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

# 禁止访问隐藏文件
location ~ /\. {
    deny all;
    return 404;
}

# 命名 location 用于错误处理
error_page 404 @notfound;
location @notfound {
    return 301 /404.html;
}

3.4.4 location 中的常用指令

提示:了解 rootalias 的区别非常重要。使用 root 时,完整路径是 root + URI;使用 alias 时,location 匹配的部分会被 alias 替换。

3.5 Nginx 变量

Nginx 提供了许多内置变量,可以在配置中使用:

3.5.1 常用 HTTP 请求变量

3.5.2 HTTP 头部变量

3.5.3 响应相关变量

3.5.4 在配置中使用变量

# 日志格式中使用变量
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                 '$status $body_bytes_sent "$http_referer" '
                 '"$http_user_agent"';

# 重写规则中使用变量
if ($http_user_agent ~* "Googlebot") {
    rewrite ^/(.*)$ /google-bot/$1 last;
}

# proxy_pass 中使用变量
set $backend_server "backend.example.com";
location /api/ {
    proxy_pass http://$backend_server;
}

# 根据语言变量提供不同内容
location / {
    if ($http_accept_language ~* ^zh) {
        root /var/www/html/zh;
    }
    if ($http_accept_language ~* ^en) {
        root /var/www/html/en;
    }
    index index.html;
}

4. 虚拟主机配置

Nginx 允许在单个 IP 地址上配置多个虚拟主机,每个虚拟主机可以处理不同的域名和端口。本章将介绍如何配置虚拟主机。

4.1 server 块基础

每个 server 块需要包含 listen 指令(指定端口)和 server_name 指令(指定域名)。

4.1.1 基本 server 块配置

server {
    listen 80;                  # 监听端口
    server_name example.com;    # 服务器名称
    
    # 其他配置...
}

4.1.2 server_name 指令

server_name 指令用于区分请求应该由哪个 server 块处理,支持多种匹配模式:

4.1.3 匹配优先级

当一个请求匹配多个 server 块时,Nginx 按以下优先级选择:

  1. 精确匹配的 server_name
  2. 以 * 开头的最长通配符名称(如:*.example.com)
  3. 以 * 结尾的最长通配符名称(如:mail.*)
  4. 第一个匹配的正则表达式
  5. 默认 server 块(使用 listen 80 default_server; 指定)

4.1.4 默认 server 块

当请求的 Host 头不匹配任何 server_name 时,Nginx 使用默认 server 块:

server {
    listen 80 default_server;
    server_name _;
    
    return 404 "No server is configured for this host.";
}

实例:多域名配置

server {
    listen 80;
    server_name example.com www.example.com;
    
    root /var/www/example;
    index index.html;
}

server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://localhost:8080;
    }
}

server {
    listen 80 default_server;
    server_name _;
    
    return 444;  # 关闭连接,不返回任何内容
}

5. 路由与位置匹配

Nginx 使用 location 块来匹配请求的 URI,并根据匹配结果处理不同的内容或逻辑。本章将介绍 location 块的语法和使用方法。

5.1 location 语法

location 块的语法如下:

location [ = | ~ | ~* | ^~ ] uri {
    # 配置指令
}

5.1.1 匹配类型

5.1.2 匹配优先级

Nginx 按以下顺序选择匹配的 location 块:

  1. 精确匹配(=
  2. 优先前缀匹配(^~
  3. 正则表达式匹配(~~*),按照它们在配置文件中的出现顺序
  4. 前缀匹配,选择最长匹配

5.2 匹配优先级

Nginx 按以下顺序选择匹配的 location 块:

  1. 精确匹配(=
  2. 优先前缀匹配(^~
  3. 正则表达式匹配(~~*),按照它们在配置文件中的出现顺序
  4. 前缀匹配,选择最长匹配

5.3 try_files 指令

try_files 指令用于按顺序尝试文件,并根据尝试结果处理请求。

5.3.1 基本语法

try_files file1 file2 ... fileN = code;

5.3.2 使用示例

try_files $uri $uri/index.html $uri/index.htm =404;

5.3.3 与 alias 指令结合使用

try_files $uri $uri/index.html $uri/index.htm =404;
alias /path/to/files;

5.3.4 与 return 指令结合使用

try_files $uri $uri/index.html $uri/index.htm =404;
return 404;

6. 静态文件服务

Nginx 可以高效地提供静态文件服务,包括 HTML、CSS、JavaScript、图片等。本章将介绍如何配置静态文件服务。

6.1 配置静态文件服务器

要配置静态文件服务器,需要使用 root 指令指定文件的根目录,并使用 index 指令指定默认文件。

6.1.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    root /var/www/example;
    index index.html;
}

6.1.2 处理多个默认文件

server {
    listen 80;
    server_name example.com;
    
    root /var/www/example;
    index index.html index.htm;
}

6.1.3 处理静态文件

server {
    listen 80;
    server_name example.com;
    
    root /var/www/example;
    index index.html;
}

6.2 配置缓存

Nginx 可以使用 expires 指令来配置缓存策略,以减少对后端服务器的负载。

6.2.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    root /var/www/example;
    index index.html;
    
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 30d;
    }
}

6.2.2 配置多个缓存策略

server {
    listen 80;
    server_name example.com;
    
    root /var/www/example;
    index index.html;
    
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 30d;
    }
    
    location ~* \.(html|htm)$ {
        expires 1h;
    }
}

7. 反向代理

Nginx 可以用作反向代理服务器,接收客户端请求并转发到后端服务器。本章将介绍如何配置反向代理。

7.1 配置反向代理

要配置反向代理,需要使用 proxy_pass 指令将请求代理到后端服务器。

7.1.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

7.1.2 配置多个后端服务器

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

7.2 配置负载均衡

Nginx 可以使用 upstream 指令来配置负载均衡,将请求分发到多个后端服务器。

7.2.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

7.2.2 配置多个后端服务器

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

8. 负载均衡

Nginx 可以使用多种方式进行负载均衡,包括轮询、加权轮询、最少连接和 IP 哈希等。本章将介绍如何配置负载均衡。

8.1 配置轮询负载均衡

Nginx 可以使用 upstream 指令来配置轮询负载均衡。

8.1.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

8.1.2 配置加权轮询

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

8.2 配置最少连接负载均衡

Nginx 可以使用 least_conn 指令来配置最少连接负载均衡。

8.2.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

8.2.2 配置 IP 哈希负载均衡

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

9. HTTPS 配置

Nginx 可以配置 HTTPS 服务器,处理 HTTPS 请求。本章将介绍如何配置 HTTPS 服务器。

9.1 配置 SSL

要配置 SSL,需要使用 ssl 指令和相关配置。

9.1.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    ssl on;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
}

9.1.2 配置多个 SSL 证书

server {
    listen 80;
    server_name example.com;
    
    ssl on;
    ssl_certificate /path/to/cert1.pem;
    ssl_certificate_key /path/to/key1.pem;
    
    ssl_certificate /path/to/cert2.pem;
    ssl_certificate_key /path/to/key2.pem;
}

9.2 配置 SSL 会话缓存

Nginx 可以使用 ssl_session_cache 指令来配置 SSL 会话缓存。

9.2.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    ssl on;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    ssl_session_cache shared:SSL:10m;
}

9.2.2 配置 SSL 会话缓存大小

server {
    listen 80;
    server_name example.com;
    
    ssl on;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    ssl_session_cache shared:SSL:10m;
}

10. 性能优化

Nginx 提供了多种配置选项来优化性能,包括调整工作进程数、缓存配置和连接超时等。本章将介绍如何优化 Nginx 性能。

10.1 调整工作进程数

Nginx 可以使用 worker_processes 指令来调整工作进程数。

10.1.1 基本配置

worker_processes auto;   # 工作进程数,通常设置为 CPU 核心数

10.1.2 配置多个工作进程

worker_processes 4;   # 配置多个工作进程

10.2 配置缓存

Nginx 可以使用 proxy_cache 指令来配置缓存。

10.2.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

10.2.2 配置缓存大小

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

10.3 配置连接超时

Nginx 可以使用 keepalive_timeout 指令来配置连接超时。

10.3.1 基本配置

keepalive_timeout 65;   # 保持连接超时时间

10.3.2 配置多个连接超时

keepalive_timeout 65;   # 保持连接超时时间

11. 安全最佳实践

Nginx 提供了多种安全配置选项,包括限制访问、配置访问控制和启用安全功能等。本章将介绍如何配置 Nginx 以提高安全性。

11.1 限制访问

Nginx 可以使用 allowdeny 指令来限制访问。

11.1.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

11.1.2 配置访问控制

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

11.2 配置访问控制

Nginx 可以使用 allowdeny 指令来限制访问。

11.2.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

11.2.2 配置访问控制

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

11.3 启用安全功能

Nginx 可以使用 ssl 指令和相关配置来启用安全功能。

11.3.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    ssl on;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
}

11.3.2 配置 SSL

server {
    listen 80;
    server_name example.com;
    
    ssl on;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
}

12. 常见应用场景

Nginx 可以用于多种应用场景,包括 Web 服务器、反向代理、负载均衡和 API 网关等。本章将介绍如何配置这些应用场景。

12.1 配置 Web 服务器

要配置 Web 服务器,需要使用 root 指令指定文件的根目录,并使用 index 指令指定默认文件。

12.1.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    root /var/www/example;
    index index.html;
}

12.1.2 处理多个默认文件

server {
    listen 80;
    server_name example.com;
    
    root /var/www/example;
    index index.html index.htm;
}

12.2 配置反向代理

要配置反向代理,需要使用 proxy_pass 指令将请求代理到后端服务器。

12.2.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

12.2.2 配置多个后端服务器

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

12.3 配置负载均衡

Nginx 可以使用 upstream 指令来配置负载均衡,将请求分发到多个后端服务器。

12.3.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

12.3.2 配置轮询负载均衡

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

12.4 配置 API 网关

Nginx 可以用作 API 网关,将请求路由到相应的服务。

12.4.1 基本配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

12.4.2 配置多个后端服务器

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_servers;
    }
}

4. 基本用法

掌握了 Nginx 的核心概念后,接下来我们将学习如何配置和使用 Nginx 来完成常见任务。

4.1 静态内容服务

Nginx 作为静态文件服务器非常高效,可以轻松处理 HTML、CSS、JavaScript、图片等文件:

4.1.1 基本静态文件配置

server {
    listen 80;
    server_name example.com;
    
    # 网站根目录
    root /var/www/example;
    
    # 默认索引文件
    index index.html index.htm;
    
    # 静态文件缓存设置
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}

4.1.2 try_files 指令

try_files 指令按顺序检查文件是否存在,并使用第一个找到的文件进行请求处理:

location / {
    try_files $uri $uri/ /index.html;
}

这个配置会:

  1. 尝试提供与 URI 匹配的文件
  2. 如果找不到,则尝试将 URI 作为目录并寻找索引文件
  3. 如果仍找不到,则回退到 /index.html(适用于单页应用)

4.1.3 目录列表

可以启用目录列表功能,当访问一个没有索引文件的目录时显示文件列表:

location /downloads/ {
    root /var/www/example;
    autoindex on;
    autoindex_exact_size off;  # 以可读格式显示文件大小
    autoindex_localtime on;    # 显示本地时间
}

4.1.4 文件访问权限控制

可以限制对某些文件或目录的访问:

# 禁止访问隐藏文件
location ~ /\. {
    deny all;
    return 404;
}

# 保护敏感文件
location ~* \.(htaccess|htpasswd|ini|conf|txt)$ {
    deny all;
    return 404;
}

# 基于 IP 限制访问
location /admin/ {
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
}

4.2 反向代理

Nginx 作为反向代理可以将请求转发到后端服务器,是其最常见的应用场景之一。

4.2.1 基本代理配置

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://localhost: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_pass 中,如果 URL 包含路径(如 http://localhost:8080/app/),则 location 匹配的部分会被替换成该路径。如果不含路径,则完整的原始 URI 会被追加。

4.2.2 重要的代理头部

4.2.3 代理超时设置

location /api/ {
    proxy_pass http://backend_api;
    
    # 超时设置
    proxy_connect_timeout 5s;     # 连接超时
    proxy_send_timeout 60s;       # 发送超时
    proxy_read_timeout 60s;       # 读取超时
    
    # 缓冲设置
    proxy_buffering on;
    proxy_buffer_size 8k;
    proxy_buffers 8 8k;
}

4.2.4 WebSocket 代理

Nginx 可以代理 WebSocket 连接,需要设置特殊的头部和超时:

location /ws/ {
    proxy_pass http://websocket_backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    # WebSocket 连接可能长时间保持,增加超时
    proxy_read_timeout 3600s;
}

4.3 负载均衡

Nginx 可以在多个后端服务器之间分配请求,提供高可用和扩展性。

4.3.1 定义上游服务器组

http {
    # 定义上游服务器组
    upstream backend_servers {
        server 192.168.1.10:8080;
        server 192.168.1.11:8080;
        server 192.168.1.12:8080;
    }
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            proxy_pass http://backend_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

4.3.2 负载均衡方法

Nginx 支持多种负载均衡算法:

# 轮询(默认)
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 加权轮询
upstream backend {
    server 192.168.1.10:8080 weight=3;  # 该服务器接收 3/4 的请求
    server 192.168.1.11:8080 weight=1;  # 该服务器接收 1/4 的请求
}

# IP 哈希(会话持久性)
upstream backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 最少连接
upstream backend {
    least_conn;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 通用哈希
upstream backend {
    hash $request_uri consistent;  # 基于 URI 的一致性哈希
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

4.3.3 健康检查和服务器参数

upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 backup;  # 备用服务器
    server 192.168.1.13:8080 down;    # 标记为不可用
}

参数说明:

小知识:Nginx 开源版只支持被动健康检查(通过 max_fails 和 fail_timeout)。主动健康检查(定期探测后端服务器状态)需要 Nginx Plus 商业版。

4.4 URL 重写与重定向

Nginx 提供了强大的 URL 重写功能,可以修改请求 URI 或将客户端重定向到不同的 URL。

4.4.1 rewrite 指令

server {
    listen 80;
    server_name example.com;
    
    # 基本重写:将请求从旧路径重写到新路径
    rewrite ^/old-page\.html$ /new-page.html permanent;
    
    # 使用捕获组保留 URI 的一部分
    rewrite ^/products/(\d+)$ /items/$1 last;
    
    # 处理尾部斜杠
    rewrite ^/(.+)/$ /$1 permanent;
    
    # 多个重写规则
    location /old-site/ {
        rewrite ^/old-site/(.*)$ /new-site/$1 permanent;
    }
}

4.4.2 rewrite 标志

4.4.3 使用 return 指令

对于简单重定向,return 指令比 rewrite 更高效:

# 永久重定向
location /old-url {
    return 301 https://example.com/new-url;
}

# 临时重定向
location /temp-url {
    return 302 https://example.com/temporary;
}

# 返回自定义状态和消息
location /forbidden {
    return 403 "Access Forbidden";
}

# 对整个站点强制使用 HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

4.4.4 if 条件判断

Nginx 支持在 server 和 location 块中使用 if 条件:

server {
    listen 80;
    server_name example.com;
    
    # 基于查询参数重定向
    if ($args ~* utm_source=newsletter) {
        return 302 /landing-page;
    }
    
    # 检查文件是否存在
    if (!-f $request_filename) {
        rewrite ^/(.*)$ /index.php?q=$1 last;
    }
    
    # 基于 User-Agent 重写
    if ($http_user_agent ~* "Googlebot") {
        rewrite ^/(.*)$ /for-bots/$1 last;
    }
}

注意:Nginx 开发者不建议过度使用 if 指令,因为它在某些情况下可能导致不可预期的行为。尽可能使用 location 块或 try_files 指令代替。

4.4.5 常见重写场景

4.4.6 实际示例

# 单页应用配置
location / {
    try_files $uri $uri/ /index.html;
}

# WordPress 漂亮链接
location / {
    try_files $uri $uri/ /index.php?$args;
}

# Laravel 应用
location / {
    try_files $uri $uri/ /index.php?$query_string;
}

# 域名规范化 (非 www 到 www)
server {
    listen 80;
    server_name example.com;
    return 301 $scheme://www.example.com$request_uri;
}

# 强制 HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}