Nginx

1. Nginx 概述


Nginx 是一款轻量级的套接字服务,他的特点如下:

基本特点:

  • 高性能:事件驱动架构,能够处理大量并发连接(epoll 网络 IO 模型)。
  • 低内存消耗:相比传统服务器如Apache,内存占用更少。
  • 高并发:单机可支持数万并发连接,官方测试能够支撑5万并发连接,在实际生产环境中可以支撑2到4万并发连接。
  • 模块化设计:通过模块扩展功能。
  • 热部署:支持不停止服务更新配置和二进制文件。

主要用途:

  • Web服务器
  • 反向代理服务器
  • 负载均衡器
  • HTTP缓存,Nginx能够存储来自上游服务器(如应用服务器、API服务器等)的响应内容,并在后续请求相同资源时直接返回缓存内容,而不必每次都向上游服务器请求。
  • 邮件代理服务器

2. Nginx 安装

官网地址:https://nginx.org

官方文档:https://nginx.org/en/docs/

2.1. Linux 系统使用包管理器安装(如 yum、apt等)

安装 nginx 主体:

官方安装文档:https://nginx.org/en/linux_packages.html

yum 安装动态模块示例:

yum install -y nginx-mod-stream  # 安装 stream 模块
yum install -y nginx-all-modules  # 安装所有动态模块
Bash

使用包管理器安装 Nginx 的主要文件路径:

Nginx主配置文件:

路径类型作用
/etc/nginx/nginx.conf配置文件nginx主配置文件
/etc/nginx/conf.d/default.conf配置文件默认网站配置文件

Nginx代理相关参数文件:

路径类型作用
/etc/nginx/fastcgi_params配置文件Fastcgi代理配置文件
/etc/nginx/scgi_params配置文件scgi代理配置文件
/etc/nginx/uwsgi_params配置文件uwsgi代理配置文件

Nginx编码相关参数文件:

路径类型作用
/etc/nginx/win-utf配置文件将 Windows-1251 转换为 UTF-8
/etc/nginx/koi-utf配置文件将 KOI8-R(俄语编码)转换为 UTF-8
/etc/nginx/koi-win配置文件将 KOI8-R 转换为 Windows-1251(另一种俄语编码)
/etc/nginx/mime.types配置文件定义 HTTP 响应的 MIME 类型(文件扩展名与 Content-Type 的映射关系)
mime.types:常用,但通常无需修改。
koi-* 和 win-utf:除非处理特定语言的旧系统,否则可以忽略。

Nginx管理相关命令:

路径类型作用
/usr/sbin/nginx命令Nginxi命令行管理终端工具
/usr/sbin/nginx-debug命令Nginx命令行与终端调试工具
/usr/bin/nginx-upgrade命令用于无缝升级 Nginx(热升级),在不中断服务的情况下替换旧版本 Nginx 进程

Nginx日志相关目录与文件:

路径类型作用
/var/log/nginx目录Nginx默认存放日志目录
/etc/logrotate.d/nginx配置文件Nginx的日志切割配置,由lograte工具管理

Nginx动态模块相关:

路径类型作用
/usr/lib64/nginx/modules/目录存放 Nginx 动态模块(.so 文件)
/usr/share/nginx/modules/目录通常存放 模块的配置文件 或 模块的元数据(如 READMELICENSE),而不是 .so 文件本身。

2.2. 源码安装

源码安装参考文档:https://www.runoob.com/linux/nginx-install-setup.html

3. Nginx 常用命令

Nginx 命令参数:

# Nginx 默认端口号为 80。-v、-t、-s 参数最为常用
# 常用参数:
-h:命令帮助
-v:打印版本号
-V:打印已经安装的插件等信息
-t:测试配置正确性并退出
-q:测试配置时只显示错误
-s:向主进程发送信号(reload 重新加载配置文件、stop 停止服务)
-p:指定Nginx服务器路径前缀
-c:指定Nginx配置文件路径
Bash

启动 Nginx

# 默认启动(根据配置文件),等价于 systemctl start nginx
nginx

# 指定配置文件启动
nginx -c /path/to/nginx.conf

# 以特定用户启动(需权限)
nginx -u www-data
Bash

停止 Nginx

# 立即停止(强制终止),等价于 systemctl stop nginx
nginx -s stop

# 优雅停止(等待请求完成)
nginx -s quit
Bash

重新加载配置(不重启服务)

# 重新加载配置文件(适用于修改配置后)
nginx -s reload

# 重新打开日志文件(日志切割后使用)
nginx -s reopen
Bash

其他命令:

nginx -t  # 检测配置文件是否有语法错误,然后退出

nginx -?,-h  # 打开帮助信息
 
nginx -v  # 显示版本信息并退出
 
nginx -V  # 显示版本和配置选项信息,然后退出
 
nginx -V 2>&1 | sed "s/\s\+--/\n --/g"  # 配置选项信息格式化输出
 
killall nginx  # 杀死所有nginx进程
 
systemctl enable nginx  # 加入开机自启

nginx -T  # 检测配置文件是否有语法错误,并打印完整配置
 
nginx -q  # 在检测配置文件期间屏蔽非错误信息
 
nginx -p prefix  # 设置前缀路径(默认是:/usr/share/nginx/)
 
nginx -c filename  # 设置配置文件(默认是:/etc/nginx/nginx.conf)
 
nginx -g "directive;"  # 覆盖配置文件中的全局指令(如 nginx -g "daemon off;" 禁止后台运行)
Bash

4. Nginx 配置文件

4.1. 配置文件 nginx.conf 结构

说明:

  • main:全局配置,所有其他配置块都包含在其内部。
    • events 块:Nginx 连接相关配置。
    • http 块:Nginx 处理 http 请求的主要配置。
      • upstream 块:配置负载均衡。
      • server 块:Nginx 主机配置块,可用于配置多个虚拟主机。
        • localtion 块:可以有多个,用于匹配 URI 路径。
    • stream 块:stream 做四层负载均衡并不常用
      • upstream块:配置负载均衡。
      • server 块:四层的 server 块使用 TCP 协议,不能使用 localtion。
  • http 块与 stream 块内的 upstream 及 server 均可以有多个。
  • 在 Nginx 配置文件中,每一条指令配置都必须以“;”分号结束。

4.2. 全局配置

user  nobody;  # 运行用户
worker_processes  auto;  # worker 进程数,通常与cpu核数保持一致,设置为 auto 时 nginx 会自动根据核数启动 worker 进程。

# 全局错误日志:日志级别有:debug、info、notice、warn、error、crit、alert
error_log  /var/log/nginx/error.log;
# error_log  /var/log/nginx/error.log  notice;
# error_log  /var/log/nginx/error.log  info;

# PID 文件
pid        logs/nginx.pid;

# include 用来引入配置文件,下述指令表示 nginx 启动时会加载 dynamic 模块的所有配置,确保动态模块都加载到 nginx 中
include /usr/share/nginx/modules/*.conf;


events {
    ...
}


http {
    ...
}
Bash

4.3. events 块配置

events 块是 Nginx 配置中用于设置事件处理模型和工作连接相关参数的指令块,它位于主配置文件中与 http 块同级的位置。

events 块配置示例:

events {
    worker_connections 2048;
    use epoll;
}


# epoll 仅用于 linux2.6 以上内核,
# worker_connections 单个 worker 进程的最大并发链接数,可以调大,但是文件描述也要一起调大(每个TCP连接对应一个文件描述符)
Bash

nginx 实现高并发的原理:

  • 多进程模型
    • Master 进程:
      • 负责管理 Worker 进程(启动、停止、重载配置)
      • 不处理客户端请求,系统开销极小
    • Worker 进程:
      • 实际处理请求的进程(数量通常配置为 CPU 核心数)
      • 完全独立,避免锁竞争和上下文切换开销
      • 通过共享内存实现进程间通信
  • 非阻塞 I/O + 事件驱动模型
    • 事件驱动模型
      • Linux 下使用 epoll 模型,相比 select/poll 的 O(n) 遍历,epoll 仅返回就绪的 FD(文件描述符)。
    •  非阻塞 I/O
      • 所有操作(accept/read/write)均为非阻塞
      • Worker 进程不会被单个慢请求阻塞

4.4. http 块配置

http 块全局配置:

http {
    # 设定日志输出模板
    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 模块错误日志配置,如果未单独定义则会继承全局配置中的错误日志配置
    error_log   /var/log/nginx/http_error.log;
 
 
    # 网络io优化参数
    # 1.开启 sendfile 特性可以显著提高静态文件(如图片、CSS、JavaScript文件等)传输的效率
    # 原理如下:
    # 开启 sendfile 后可以减少数据在操作系统内核和用户空间之间的拷贝次数。
    # 没有 sendfile 的情况下,传输文件通常需要经历如下步骤,数据需要在用户空间和内核空间之间进行两次拷贝。
    # (1)从硬盘读取文件到用户空间的缓冲区(内核→用户空间)
    # (2)将读取的数据从用户空间缓冲区写入到操作系统的网络缓冲区(用户空间→内核)
    # (3)操作系统网络缓冲区发送数据到网络(内核→网络)
    # 当开启了 sendfile 之后,这个操作简化了,并且可以避免将数据从内核空间拷贝到用户空间。sendfile 系统调用可以直接在内核中传输数据:
    # (1)内核会将数据从文件系统缓冲区直接发送到网络堆栈,无需先拷贝到用户空间,然后再从用户空间拷贝到内核的网络堆栈
    # (2)数据可以直接在内核地址空间中移动,避免了额外的上下文切换和数据复制开销
    # 所以,sendfile 能够减少 CPU 的使用,减少操作系统的上下文切换,并允许更快地传输文件数据,特别是对于大型文件的传输
    sendfile     on;
    
    # 2.通常与 sendfile 一起使用用,当 tcp_nopush 设置为 on 时,Nginx 将尽可能发送较大的 TCP 数据包,减少 TCP 报文的数量,提高传输效率。这对于减少网络传输中的 TCP 慢启动阶段,减少网络延迟和提高网络吞吐量非常有用。这在传输大型文件或使用 HTTP/1.1 的 Keep-Alive 长连接时特别有效。
    tcp_nopush     on;
    
    # 3.禁用 Nagle 算法,数据将会尽快发送出去,而不是等待缓冲区满或者接收到ACK。这会减少延迟,但可能会造成网络利用率低。这个选项在处理需要快速响应的短数据流(例如HTTP/1.1的 keep-alive 连接)时非常有用。
    tcp_nodelay     on;
    
    # 4.控制长连接的两个参数:
    keepalive_timeout  65; 
    # 开启长连接:如果客户端在65秒内没有再次发送新的请求,那么Nginx将关闭这个连接,反之如果在65秒内有新的请求到来,那么这个连接会保持开启,等待处理新的请求。
    keepalive_requests 100; 
    # 默认情况下,Nginx 的 keepalive_requests 是设置为 100,这个设置针对的是每个长连接在关闭前能处理的最大请求数量。你可以根据需要调整这个值。
    # keepalive_timeout 与 keepalive_requests 两个条件是"或"的关系,满足任一条件都会关闭连接
    # 配置 keepalive_requests 的目的:
    # 防止某些客户端长期占用连接导致负载不均
    # 定期重建连接可以释放积累的内存碎片
    # 限制单个连接的使用寿命,降低某些攻击的影响
 
    # 5.开启 gzip 压缩,节省带块加速网络传输
    gzip  on;
 
 
    # 控制客户端请求头的缓冲区大小和数量:应对请求头过大的情况
    client_header_buffer_size    128k;  #  设定用于保存客户端请求头的缓冲区的大小,当客户端发送的请求头超过这个大小时,Nginx 会使用 large_client_header_buffers 分配更大的缓冲区。如果请求头超过这个总容量,Nginx 会返回 414 (Request-URI Too Large) 错误,这可以防止恶意客户端发送大量数据来消耗服务器资源。
    large_client_header_buffers  4 128k;  # 如果请求头过大,可以使用多个缓冲区来保存。格式为 <数量> <大小>。<数量>代表缓冲区数量,<大小>代表每个缓冲区的大小。
 
 
    # mime.types定义了nginx可以识别的网络资源类型,例如css、js、jpg等
    include  /etc/nginx/mime.types; 
    
    
    # http 响应头中,如果没有明确指定 Content-Type,则默认使用 default_type 指定的
    default_type application/octet-stream; # application/octet-stream。这是一种二进制的数据类型,意味着这种内容不会被浏览器解析,而是作为一个下载文件来处理。这主要用于那些不适合以普通文本或者其他MIME类型表示的文件,例如可执行文件。
    
    
    # 设定虚拟主机配置
    server {
        # 详细配置见下一小结
    }
}
Bash

4.5. server 块虚拟主机配置

server 块主要负责配置虚拟主机,每个 http 块可以包含多个 server 块,而每个server 块就相当于一个虚拟主机。

虚拟主机概念:

  • 虚拟主机,在Web服务里就是一个独立的网站站点,这个站点对应独立的域名(也可能是IP或端口),具有独立的程序及资源,可以独立地对外提供服务供用户访问。
  • 在Nginx中,使用一个 server{} 标签来标识一个虚拟主机,一个Web服务里可以有多个虚拟主机标签对,即可以同时支持多个虚拟主机站点。
  • 虚拟主机有三种类型:基于域名的虚拟主机、基于端口的虚拟主机、基于 IP的虚拟主机。

基于域名的虚拟主机:

域名的虚拟主机是生产环境中最常用的,请求的时候必须使用域名,如果使用 IP 地址访问并且没有禁止通过 IP 直接访问,则会默认使用第一个监听该端口的 server 块处理 IP 访问。

工作原理:使用域名访问一个 URL 地址时,该请求中必然包含该域名;请求到达 nginx 后,nginx 会获取到该域名并根据域名匹配相应的 server 虚拟主机。

配置示例:

server {
    listen 80;
    server_name example.com;          # 域名1
    root /var/www/example;
    # 其他配置...
}

server {
    listen 80;
    server_name test.com;             # 域名2
    root /var/www/test;
    # 其他配置...
}

# 访问 http://example.com 和 http://test.com 会显示不同内容。
Bash

禁用 IP 地址直接访问配置示例:

# 在HTTP(80端口)和HTTPS(443端口)都添加默认服务器拦截
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;  # 所有域名不匹配的请求
    ssl_certificate /pingk.top.pem;
    ssl_certificate_key /pingk.top.key;
    return 444; # Nginx特有的直接关闭连接
}
Bash

基于端口的虚拟主机:

配置示例:

server {
    listen 8080;                     # 端口1
    server_name localhost;
    root /var/www/site1;
}

server {
    listen 8081;                     # 端口2
    server_name localhost;
    root /var/www/site2;
}

# 访问 http://localhost:8080 和 http://localhost:8081 显示不同内容。
Bash

基于 IP 的虚拟主机

基于 IP 的虚拟主机在生产环境中不常使用,只需要将基于域名的虚拟主机中的域名修改为 IP 就可以了,前提是服务器配置有多个 IP 地址。

虚拟主机别名设置:

虚拟主机别名,就是为虚拟主机设置除了主域名以外的一个或多个域名,这样就能实现用户访问的多个域名对应同一个虚拟主机网站的功能。

 server {
    listen       80;
    server_name  example.com test.com;  
    location / {
        root   /usr/share/nginx/html/www;
        index  index.html index.htm;
    }
}
Bash

4.6. server 块 location 配置

location 用于匹配 URI 并定义处理规则。对于一个 URL 地址,location 只会匹配 URI 地址部分,? 号后的参数部分不匹配。即对 localtion 来说,/test 和 /test?a=1是一样的路径。

4.6.1. 基本语法

location [匹配模式] {
    # 处理逻辑
}
Bash

4.6.2. 匹配模式

  • 前缀匹配
    • 匹配以指定字符串开头的 URI。
    • 示例:
# 两种形式同时存在时匹配的路径不能相同,否则会报错
location /images
location ^~ /images  

# 以 /images 开头的 URI 会被匹配到
Bash
  • 精确匹配
    • 只匹配完全相同的 URI(优先级最高)。
    • 示例:
location = /login

# 只有 /login 会被匹配到
Bash
  • 正则匹配
    • 使用正则表达式匹配 URI
    • location ~(区分大小写)
    • location ~*(不区分大小写)
    • 示例:
location ~ \.php$

# 匹配以 .php 结尾的 URI 地址
Bash

4.6.3. 匹配优先级规则

Nginx 按 从高到低 的顺序检查 location一旦匹配成功则停止搜索。优先级如下:

  • = 精确匹配
location = /test { ... }  # 仅匹配 /test
Bash
  • ^~ 前缀匹配(匹配成功则停止后续匹配)
location ^~ /static/ { ... }  # 匹配 /static/ 开头的 URI,不检查后续正则
Bash
  • ~ 或 ~* 正则匹配(按配置文件中的顺序匹配)
location ~ \.php$ { ... }   # 区分大小写匹配 .php 结尾
location ~* \.(jpg|png)$ { ... }  # 不区分大小写匹配 .jpg 或 .png
Bash
  • 普通前缀匹配(按最长前缀优先)
location / { ... }          # 默认匹配所有 URI
location /docs/ { ... }     # 比 / 更具体,优先级更高
Bash

4.7. server 块 listen 指令

4.7.1. listen 指令用法介绍

基础语法:

listen address[:port] [additional_parameters];
listen port [additional_parameters];
Bash

基本用法示例:

# 监听指定端口(IPv4)
listen 80;  # 监听所有IPv4地址的80端口

# 监听指定IP和端口
listen 192.168.1.100:8080;  # 只监听192.168.1.100的8080端口

# 监听IPv6地址
listen [::]:80;  # 监听所有IPv6地址的80端口
listen [fe80::1]:80;  # 监听特定IPv6地址
Bash

高级参数选项:

  •  协议相关参数
    • default_server 设为默认服务器,示例:listen 80 default_server;
    • ssl 启用SSL/TLS,示例:listen 443 ssl;
    • http2 启用HTTP/2(需同时启用ssl),示例:listen 443 ssl http2;
    • proxy_protocol 启用PROXY协议,示例:listen 80 proxy_protocol;
      • Nginx 将在 80 端口监听普通 HTTP 请求。
      • 但期望接收到的连接使用 PROXY 协议(而不是原始 HTTP 请求)。
      • Nginx 会先解析 PROXY 协议头,然后才处理后续的 HTTP 请求。
      • 使用场景不多。
  • 连接处理参数
    • backlog= 设置待处理连接队列的最大长度。
    • rcvbuf= 设置接收缓冲区大小。
    • sndbuf= 设置发送缓冲区大小。
    • bind 单独绑定地址/端口。
    • reuseport 启用SO_REUSEPORT(内核级负载均衡)。
    • so_keepalive= 配置TCP keepalive参数

4.7.2. listen 指令 reuseport 参数详解

nginx 有两种工作模式:

  • 1个 master 主进程 + 多个 worker 子进程(worker 进程禁用 reuseport 模式,默认模式)
    • 特点:所有 worker 进程共享同一个监听套接字
    • 优点:因为全连接队列是共享的,所以当某个 worker 进程繁忙时,它去全连接队列里 accpet 的能力会降低,但其他空闲的 worker 进程则不受影响,这会平衡所有 worker 进程的压力。
    • 缺点:多个 worker 进程争抢会带来额外的损耗。
    • 配置示例:
server {
    listen 80;  # 不添加 reuseport 参数
    listen [::]:80;
    # 其他配置...
}
Bash
  • 1个 master 主进程 + 多个 worker 子进程(worker 进程启用 reuseport 模式)
    • 特点:每个 worker 进程有自己独立的监听套接字。
    • 优点:多个进程不需要竞争某个公共资源,减少竞争的资源消耗,提高处理效率。
    • 缺点:应为每个 worker 监听独立的连接队列,当某个 worker 进程繁忙时,其他空闲进程不能帮忙分摊压力。可能会导致个别连接的请求的延迟增大。
      • 解决方案:引入线程池,但同时增大了出现 bug 的几率,例如锁竞争问题、单个线程 bug 导致整个进程退出的问题。
      • 配置示例:
# 如果需要完整的多线程支持,编译时需要的模块,且需要 Nginx 1.7.11+
./configure --with-threads \
            --with-file-aio \
            --with-http_ssl_module

# 定义线程池
thread_pool default threads=32 max_queue=65536;
# threads:线程池中的线程数量(建议设置为CPU核心数的2-4倍)
# max_queue:等待队列的最大任务数(超过此值将返回错误)

http {
    aio threads=thread_pool;  # 启用线程池
 
    # 启用线程池与reuseport并不冲突
    server {
        listen 8089 reuseport backlog=10240;
        ...
    }
}        
Bash

4.8. server 块 return 指令

在 Nginx 中,return 指令用于立即终止请求处理并返回指定的 HTTP 状态码或重定向 URL。它通常用于重定向、快速响应或阻止某些请求。

基本语法

return code [text];
return code URL;
return URL;

# code:HTTP 状态码(如 301, 302, 404, 200 等)。
# text:直接返回的响应内容(适用于 2xx 或 4xx 状态码)。
# URL:重定向目标地址(适用于 3xx 状态码)。
Bash

使用示例

直接返回状态码:

location /forbidden {
    return 403 "Access Denied";  # 返回 403 并显示自定义文本
}

location /health {
    return 200 "OK";  # 返回 200 状态码和 "OK"
}

# 访问 /forbidden → 返回 HTTP 403 和文本 "Access Denied"。
# 访问 /health → 返回 HTTP 200 和 "OK"。
Bash

重定向(3xx):

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

location /temporary {
    return 302 /new-location;  # 临时重定向(相对路径)
}

# 访问 /old-url → 浏览器跳转到 https://example.com/new-url(301 永久重定向)。
# 访问 /temporary → 跳转到 /new-location(302 临时重定向)。
Bash

直接返回 URL(隐式 302):

location /go-to-home {
    return https://example.com;  # 默认 302 临时重定向
}

# 等同于
location /go-to-home {
    return 302 https://example.com;
}
Bash

阻止特定请求:

location /admin {
    return 403;  # 禁止访问 /admin
}

location ~* \.php$ {
    return 444;  # 静默关闭连接(Nginx 特有)
}
# 444 是 Nginx 的特殊状态码,直接关闭连接,不返回任何内容。
Bash

结合变量:

location /check-ip {
    return 200 "Your IP: $remote_addr";  # 返回客户端 IP
}

location /dynamic-redirect {
    return 302 "https://example.com/user/$arg_id";  # 根据查询参数重定向
}
Bash

4.9. server 块 rewrite 配置

基本语法

rewrite regex replacement [flag];

# regex:正则表达式匹配原始 URI(PCRE 语法)。
# replacement:替换后的新 URI(可含变量)。
# flag:可选参数,控制重写行为(如 last, break, redirect, permanent)。
## last:停止当前 rewrite,用新 URI 重新匹配 location(类似新请求)。
## break:停止所有 rewrite,直接使用当前结果继续处理(不重新匹配 location)。
## redirect:返回 302 临时重定向(浏览器地址栏变化)。
## permanent:返回 301 永久重定向(SEO 友好)。
Bash

使用示例

简单重写(无 flag):

location /old {
    rewrite ^/old/(.*)$ /new/$1;  # /old/path → /new/path
}

# 默认行为:隐式 last,重写后重新匹配 location。
Bash

强制重定向(301/302):

location /legacy {
    rewrite ^/legacy/(.*)$ https://example.com/new/$1 permanent;  # 301
}

location /temp {
    rewrite ^/temp/(.*)$ /new/$1 redirect;  # 302
}
Bash

终止后续处理(break):

location /static {
    rewrite ^/static/(.*)$ /data/$1 break;  # 直接映射到文件系统
    proxy_pass http://backend;  # 这行不会执行
}

# break 会跳过后续的 rewrite 和 location 重新匹配。
Bash

与 return 的区别

rewritereturn
作用修改 URI 内部重写或外部重定向直接返回状态码或重定向
性能略低(需正则匹配)更高(直接响应)
适用场景复杂 URL 规则、动态路径简单重定向、快速拦截
是否重新匹配 location取决于 flag(last 会重新匹配)立即终止,不重新匹配
除非需要基于复杂条件重定向(如按路径、参数动态跳转),否则始终优先使用 return

4.10. server 块 root 与 alias 指令

4.10.1. root 指令

基本语法:

root path;
Bash

工作原理:

  • root 指令会将 location 匹配的 URI 部分附加到指定的路径后面
  • 它是将完整的请求 URI 附加到 root 路径之后

示例:

location /images/ {
    root /data/www;
}

# 对于请求 /images/example.jpg,Nginx 会查找 /data/www/images/example.jpg
Bash

4.10.2. alias 指令

基本语法:

alias path;
Bash

工作原理:

  • alias 指令会 用指定的路径替换 location 匹配的部分
  • 它只替换匹配的部分,而不是附加整个 URI

示例:

location /images/ {
    alias /data/images/;
}

# 对于请求 /images/example.jpg,Nginx 会查找 /data/images/example.jpg(注意 /images/ 被替换为 /data/images/)
# alias 替换目录时结尾必须带斜线
Bash

4.11. server 块代理指令

代理模式:

  • 正向代理(Forward Proxy)
    • 定义:正向代理是客户端的代理服务器,代表客户端向外部服务器发送请求。客户端需要显式配置代理服务器。
    • 核心特点
      • 代理对象:代理的是客户端。
      • 隐藏客户端:外部服务器只能看到代理服务器的IP,无法识别真实客户端。
      • 客户端控制:由客户端主动配置使用(如企业内网、科学上网工具)。
    • 典型应用场景
      • 访问限制资源:突破地域限制(如访问Google)。
      • 企业内网安全:统一通过代理访问外部,便于监控和过滤。
      • 匿名性:隐藏客户端真实IP。
    • 典型工具Shadowsocks、Squid
    • 示例
用户(客户端) → 正向代理 → 互联网 → 目标服务器
目标服务器看到的请求来源是正向代理的IP。
TeX
  • 反向代理(Reverse Proxy)
    • 定义:反向代理是服务端的代理服务器,代表服务器接收客户端请求,并将请求转发到内部服务器。客户端无需感知代理存在。
    • 核心特点
      • 代理对象:代理的是服务端。
      • 隐藏服务器:客户端不知道真实服务器的IP或架构。
      • 服务端控制:由服务器管理员配置,对客户端透明。
    • 典型应用场景
      • 负载均衡:将请求分发到多台后端服务器(如Nginx)。
      • 安全防护:隐藏后端服务器,防御DDoS攻击(如Cloudflare)。
      • 缓存加速:缓存静态内容,减轻服务器压力。
      • SSL终结:统一处理HTTPS加密/解密,降低后端负担。
    • 典型工具Nginx、HAProxy、CDN
    • 示例
用户(客户端) → 互联网 → 反向代理 → 内部服务器集群
客户端认为反向代理就是真实的服务器。
TeX

Nginx 常用的代理指令:

proxy_pass    # 代理http协议
fastcgi_pass  # 代理fastcgi协议,适用 PHP 语言程序
uwsgi_pass    # 代理uwsgi协议,使用 Python 语言程序
grpc_pass     # 代理gRPC协议,适用 go 语言程序
Bash

代理指令优化:

以 proxy_pass 为例:

# nginx的配置文件如下
server {
    listen 80;
    server_name linux.lb.com;
 
    location / {
        proxy_pass xxxx;
        include proxy_params;
    }
}
# 优化参数可以单独写入一个文件proxy_params中,当然你也可以直接与proxy_pass并列放置。


vim /etc/nginx/proxy_params 
#(1)转发原始请求的 host 头部
proxy_set_header X-Real-IP $remote_addr;  # 设置真实/原始客户端的 IP 地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 追加原始客户端的 IP 地址到 X-Forwarded-For 头信息中。这样,在后端服务器中就可以通过读取 X-Forwarded-For 头信息来获取原始客户端的 IP 地址。
proxy_set_header Host $host;
#(2)代理到后端的TCP连接、响应、返回等超时时间
proxy_connect_timeout 10s; # nginx代理与后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 10s; # nginx代理等待后端服务器的响应时间
proxy_send_timeout 10s; #后端服务器数据回传给nginx代理超时时间
#(3)proxy_buffer代理缓冲区:nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端,边收边传, 不是全部接收完再传给客户端
proxy_buffering on;
proxy_buffer_size 8k; # 设置nginx代理保存用户头信息的缓冲区大小
proxy_buffers 8 8k;   #proxy_buffers 缓冲区
Bash

4.12. upstream 块配置

upstream 在 http 或 stream 块内,与 server 块并列,用于配置负载均衡。虽然 upstream 模块需要与代理指令一起使用,但代理指令仅仅只是用于转发请求它本身并没有任 何负载均衡的功能,upstream 才是实现负载均衡的具体模块。

upstream 块负载均衡详细配置

4.13. 一些资源分离配置示例

动态与静态请求分离:

server {
    listen 80;
    server_name www.example.com;
    
    # 静态资源处理
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?|ttf|svg|eot|mp4|webm)$ {
        root /var/www/static;
        expires 365d;
        add_header Cache-Control "public, immutable";
        access_log off;
        
        # 文件不存在时不转发到后端
        try_files $uri =404;
    }
    
    # 动态请求处理
    location / {
        proxy_pass http://backend_server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
Bash

通过判断请求的资源类型进行分离:

upstream android {
    server 10.0.0.7;
}
 
upstream iphone {
    server 10.0.0.8;
}
 
upstream pc {
    server 10.0.0.9;
}
 
server {
    listen 80;
    server_name linux.sj.com;
 
    location / {
        if ($http_user_agent ~* "Android") { #判断如果是安卓端
            proxy_pass http://android;       #代理到android虚拟主机池
        }
        if ($http_user_agent ~* "iPhone") {    #判断如果是苹果端
            proxy_pass http://iphone;       #代理到iphone虚拟主机池
        }
        if ($http_user_agent ~* "WOW64") {    #判断如果是IE浏览器
            return 403;                    #直接返回403
        }
        proxy_pass http://pc;               #如果没有匹配到以上内容,默认都代理到pc虚拟主机池
        include proxy_params;
    }
}
Bash

4.14. 一个参考配置示例

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    use epoll;
    worker_connections  1024;
    multi_accept on;  # 启用multi_accept提高连接处理效率,允许worker一次性接受所有新连接请求,减少唤醒次数
}

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;
    
    # 传输性能优化
    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    keepalive_timeout  65;
    keepalive_requests 100;
    reset_timedout_connection on;  # 超时连接直接重置而非缓慢关闭,释放资源更快
    
    # 压缩与缓存
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
   
    client_header_buffer_size    128k;  #  设定用于保存客户端请求头的缓冲区的大小,当客户端发送的请求头超过这个大小时,Nginx 会使用 large_client_header_buffers 分配更大的缓冲区。如果请求头超过这个总容量,Nginx 会返回 414 (Request-URI Too Large) 错误,这可以防止恶意客户端发送大量数据来消耗服务器资源。
    large_client_header_buffers  4 128k;

    # SSL优化配置
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    
    # 安全头
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy "strict-origin-when-cross-origin";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    include /etc/nginx/conf.d/*.conf;
}

# 在HTTP(80端口)和HTTPS(443端口)都添加默认服务器拦截
server {
    listen 80 default_server;
    server_name _;
    return 444;
}

server {
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate /etc/nginx/ssl_key/pingk.top.pem;
    ssl_certificate_key /etc/nginx/ssl_key/pingk.top.key;
    return 403; # 改为403比444更友好
}

# # HTTP重定向到HTTPS   
server {
    listen 80;
    server_name pingk.top;

    # 301永久重定向到HTTPS
    return 301 https://$host$request_uri;
}

# 主服务器配置
server {
    listen       443 ssl reuseport;
    http2 on;
    server_name  pingk.top;
    root   /var/www/html/wordpress;

    ssl_certificate /etc/nginx/ssl_key/pingk.top.pem;
    ssl_certificate_key /etc/nginx/ssl_key/pingk.top.key;
    
    index index.php index.html;
    
    # 静态资源缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?|ttf|svg|eot)$ {
        expires 30d;
        access_log off;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }
        
    # 安全防护:禁止访问隐藏文件
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # 禁止访问敏感文件
    location ~* ^/(wp-config\.php|license\.txt|readme\.html) {
        deny all;
    }
    
    # 限制访问上传目录中的PHP文件
    location ~* /wp-content/uploads/.*\.php$ {
        deny all;
    } 
    
    # 以 .php 结尾的请求,交给 php-fpm 程序处理
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass   172.22.251.33:9000;
        # 设置 FastCGI 参数 SCRIPT_FILENAME,告诉 PHP-FPM 要执行的脚本路径。
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        # 安全防护:限制PHP执行目录
        fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/tmp:/proc";
        # 加载默认的 FastCGI 参数文件(通常位于 /etc/nginx/fastcgi_params)
        include        fastcgi_params;
    }
   
    location / {
        # 按顺序尝试查找文件
        # 先尝试直接访问 $uri(请求的原始文件路径)
        # 如果不存在,尝试访问 $uri/(作为目录处理)
        # 如果都不存在,最后转发到 /index.php,并保留原始查询参数 $args
        try_files $uri $uri/ /index.php?$args;
    }
}
Bash

5. Nginx 其他模块配置参考

链接:https://egonlin.com/?p=9573

上一篇
下一篇