# 定义

Nginx 是一个高性能的 HTTP 服务器、反向代理服务器以及邮件代理服务器。它以高并发、高吞吐量、低内存消耗而著称,常用于静态资源服务、负载均衡、反向代理和缓存等场景。

至于为什么要用代理服务器,请看:代理服务器

# 主要功能

  1. HTTP 服务器:Nginx 可以作为静态文件服务器,直接提供 HTML、CSS、JavaScript、图片等文件。它非常高效,适合用作前端项目的静态资源托管服务器。
  2. 反向代理:Nginx 可以将客户端的请求转发给后端服务器(如 Node.js、Python、Java 应用),起到代理作用,同时隐藏后端服务器,提升安全性。
  3. 负载均衡:Nginx 可以将请求分发到多个后端服务器(负载均衡),根据服务器的健康状态和负载情况,自动选择合适的服务器处理请求。
  4. 缓存功能:Nginx 可以缓存后端服务器返回的响应,提高重复请求的处理效率,减少后端服务器的压力。
  5. SSL/TLS 加密:Nginx 可以处理 HTTPS 请求,支持 SSL/TLS 协议,提供安全的网络通信。

# 预定义变量

# 客户端信息

  • $remote_addr:客户端 IP 地址。
  • $remote_port:客户端端口号。
  • $remote_user:已经认证的客户端用户名(如 HTTP 基本认证)。
  • $http_user_agent:客户端的 User-Agent 信息。
  • $http_referer:HTTP 请求头中的 Referer 信息。

# 请求信息

  • $request:请求的完整行(例如 GET /index.html HTTP/1.1)。
  • $request_uri:原始请求的 URI,包括请求参数(例如 /index.html?query=1)。
  • $uri:请求的 URI,但不包含参数,且可能已被 location 重写。
  • $args:请求的参数部分(即?之后的部分)。
  • $request_method:请求方法(如 GET、POST)。
  • $query_string:请求的查询字符串(与 $args 相同)。
  • $http_<header_name>:访问请求头信息。例如,$http_host 用于获取请求头中的 Host 信息。

# 响应信息

  • $status:响应的 HTTP 状态码。
  • $sent_http_<header_name>:自定义响应头的信息。可以通过这种方式在配置中指定和修改响应头。

# 服务器信息

  • $server_addr:服务器地址,Nginx 尝试解析配置的地址,但此变量可能影响性能。
  • $server_name:处理请求的服务器名称。
  • $server_port:请求到达的服务器端口。

# 连接信息

  • $connection:当前连接的序列号。
  • $connection_requests:当前连接已经处理的请求数量。

# 文件路径

  • $document_root:当前请求的 root 路径(文件系统中的路径)。
  • $realpath_root:当前请求的真实路径,即解析符号链接后的路径。
  • $request_filename:当前请求的完整文件路径。

# 其他

  • $hostname:Nginx 服务器的主机名。
  • $binary_remote_addr:客户端 IP 的二进制表示(用于哈希计算)。
  • $time_local:请求的本地时间。
  • $msec:当前时间的 Unix 时间戳(毫秒级)。
  • $scheme:请求使用的协议(如 http 或 https)。

# 配置项

# 全局配置

这些配置位于 nginx.conf 文件的最外层,影响整个 Nginx 的行为。

# worker_processes

  • 定义:Nginx 启动的工作进程数,一般设置为服务器的 CPU 核心数,或者使用 auto 让 Nginx 自动优化。
  • 用法:
worker processes auto;

# error_log

  • 定义:指定错误日志文件和日志级别。
  • 用法:
error_log /var/log/nginx/error.log warn;

# pid

  • 定义:指定保存 Nginx 进程 ID 的文件路径。
  • 用法:
pid /var/run/nginx.pid;

# events 模块配置

# worker_connections

  • 定义:每个工作进程允许的最大连接数。
  • 用法:
events {
    worker_connections 1024;
    multi_accept: on;
}

# multi_accept

  • 定义:当设置为 on 时,每个工作进程会一次性接受尽可能多的连接,这可以提高请求处理效率。默认为 off。
  • 用法:
events {
    worker_connections 1024;
    multi_accept: on;
}

# use

  • 定义:用于指定事件模型(如 epoll、kqueue、select 等),Nginx 会根据操作系统自动选择最优的事件模型。
  • 用法:
events {
    use: epoll;
}

# accept_mutex

  • 定义:用于启用 “接受互斥锁”,防止多个工作进程同时接受请求,避免竞争,提升负载均衡。默认值为 on。
  • 用法:
events {
    accept_mutex: on;
}

# worker_aio_requests

  • 定义:用于设置异步 I/O 的最大请求数(主要用于文件操作)。
  • 用法:
events {
    worker_aio_requests 1024;
}

# http 模块配置

http 模块是处理 HTTP 请求的核心模块,定义了如何处理客户端请求。

# server

  • 定义:定义一个虚拟主机块。一个 Nginx 实例可以有多个 server 块,每个块定义一个虚拟主机。
  • 用法:
server {
    listen 80;
    server_name example.com;
    root /var/www/html;
}

# location

  • 定义:匹配 URL 路径的处理规则。不同的路径可以有不同的处理方式。比如代理、文件服务等。
  • 用法:
location / {
    try_files $uri $uri/ =404;
}

try_files 会尝试按照指定的顺序检查文件是否存在,并返回找到的第一个文件。如果所有指定的文件都不存在, try_files 可以将请求重定向到另一个 URI 或返回一个指定的 HTTP 状态码。

在这个例子中,当请求匹配到 / 时,Nginx 会首先尝试直接返回请求的 URI 对应的文件(即 $uri )。如果该文件不存在,Nginx 会尝试将请求作为目录处理,即在该目录下找到默认的索引文件(一般为 index.html )。如果目录也不存在或没有默认索引文件,Nginx 最终会返回 404 状态码。

# listen

  • 定义:指定虚拟主机监听的端口,通常是 80(HTTP)或者 443(HTTPS)。
  • 用法:
listen 80;

# server_name

  • 定义:指定虚拟主机的域名,支持通配符匹配。
  • 用法:
server_name example.com www.example.com;
# server_name  *.example.com;

# root/alias

  • 定义:root 设置根目录路径,alias 设置路径别名。alias 在匹配 location 时不会追加匹配的路径,而 root 会追加匹配路径

root 指令允许你指定 Nginx 在文件系统中的哪个目录开始查找和返回请求的文件。这是处理静态文件(如 HTML、CSS、JavaScript、图片等)和可能的服务端脚本或程序的基础。

alias 指令用于映射请求的 URI 到一个确切的文件系统路径。它不会将请求的 URI 与指定路径拼接,而是直接替换掉 URI 中的部分或全部,以定位到具体的文件。

  • 用法:
location /static/ {
    root /var/www/html;
}

在这个配置中,如果 Nginx 接收到一个对 http://example.com/static/images/logo.png 的请求,它会将 /static/images/logo.png 拼接到 /var/www/html 后面,形成 /var/www/html/images/logo.png 的完整文件路径,然后去尝试找到并返回该文件。

location /some/path/ {
    alias /path/to/actual/directory/;
}

在这个例子中,当请求以 /some/path/ 开头时,Nginx 会将 /some/path/ 部分替换为 /path/to/actual/directory/ ,并在新的路径下查找资源。重要的是要注意 alias 路径末尾的斜杠,它会影响 Nginx 如何处理剩余的 URI 部分。

alias 路径处理

  • 如果 location 块中的 URI 以斜杠结尾(如 /some/path/ ),则 Nginx 会在 alias 指定的路径后直接添加请求的剩余 URI 部分(不包括 location 块中指定的 URI 部分)来查找文件。
  • 如果 location 块中的 URI 不以斜杠结尾(如 /some/file ),则 Nginx 会将请求的最后一个部分(即最后一个 / 之后的部分)作为文件名,并在 alias 指定的路径下查找这个文件。

# index

  • 定义:指定当访问目录时,默认加载的文件。
  • 用法:
index index.html index.htm;

# gzip

  • 定义:启用 gzip 压缩以提高传输效率
  • 用法:
gzip on;
gzip_types text/plain application/javascript text/css;

# client_max_body_size

  • 定义:设置客户端请求的最大允许大小,常用于限制上传文件的大小。
  • 用法:
client_max_body_size 50M;

# 反向代理配置

Nginx 常被用于反向代理,通过它可以将请求转发到后端服务器。

# proxy_pass

  • 定义:转发请求到后端服务器。
  • 用法:
location /api/ {
    proxy_pass http://localhost:3000/;
}

# proxy_set_header

  • 定义:在转发请求时,设置额外的 HTTP 请求头。
  • 用法:
location /api/ {
    proxy_pass http://localhost: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_redirect

  • 定义:修改后端服务器返回的 Location 和 Refresh HTTP 响应头字段。这在你使用 Nginx 作为反向代理时特别有用,因为后端服务器返回的响应可能会包含指向其自身的 URL,而不是你希望客户端访问的公共 URL(即 Nginx 代理的 URL)。

关于 Location 和 Refresh 的更多内容,可以看:请求头和响应头

  • 用法:
proxy_redirect http://backend.example.com/ http://example.com/;

# 负载均衡配置

Nginx 支持将请求分发到多个后端服务器,实现负载均衡。

# upstream

  • 定义:定义后端服务器组。
upstream name {
    server address [parameters];
    server address [parameters];
   ...
}
  • 说明:
    • name :上游服务器组的名称,可以在 proxy_pass 指令中引用。
    • address :上游服务器的地址,可以是 IP 地址和端口号,也可以是域名。
    • parameters :可选参数,用于配置服务器的权重、最大失败次数、超时时间等。
  • 用法:
http {
    upstream myapp {
        server 192.168.1.100:8080 weight=2;
        server 192.168.1.101:8080;
        server 192.168.1.102:8080 backup;
    }
    server {
        listen 80;
        server_name example.com;
        location / {
            proxy_pass http://myapp;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

# 复杂均衡策略

  • 策略:轮询(默认),将请求依次分配给后端服务器。
  • parameters 常用属性:
    • weight :设置服务器的权重,默认为 1。权重越高,分配到的请求越多。
    • max_fails :在指定的时间内,连接失败的最大次数。当超过这个次数时,Nginx 会认为该服务器不可用,并在一段时间内不再将请求转发到该服务器。
    • fail_timeout :设置服务器不可用的时间。在这段时间内,Nginx 不会将请求转发到该服务器。一般与 max_fails 配合使用。
    • backup :标记该服务器为备用服务器。当其他非备用服务器都不可用时,才会将请求转发到备用服务器。
    • ip_hash :根据客户端的 IP 地址进行哈希计算,将同一客户端的请求始终转发到同一台上游服务器。这样可以保证同一客户端的会话保持在同一台服务器上。
    • least_conn :将请求转发到连接数最少的上游服务器,实现基于最少连接数的负载均衡。

# 缓存策略

Nginx 支持配置代理缓存,用于缓存后端服务器的响应。

# proxy_cache_path

  • 定义:定义缓存路径和相关参数。
  • 用法:
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
  • 说明:
    • /data/nginx/cache :设置缓存的存储路径为 /data/nginx/cache 。所有被缓存的响应内容将存储在这个目录下。
    • levels=1:2 :定义缓存的目录层级结构。这里表示使用两级目录结构。例如,可能会生成类似于 /data/nginx/cache/a/b 的目录路径,其中 ab 是根据缓存键动态生成的目录名称。
    • keys_zone=my_cache:10m :创建一个名为 my_cache 的缓存区,大小为 10MB。这个缓存区用于存储缓存的元数据,如缓存键、缓存的过期时间等信息。
    • max_size=1g :设置整个缓存的最大尺寸为 1GB。当缓存的总大小超过这个限制时,Nginx 会根据缓存的策略(如 inactive 参数定义的策略)来清理一些缓存内容,以保持缓存的总大小在这个限制之内。
    • inactive=60m :如果一个缓存项在 60 分钟内没有被访问,那么它将被视为不活跃,并可能被清理。
    • use_temp_path=off :关闭临时路径的使用。通常,Nginx 在缓存文件时可能会先将文件存储在临时路径中,然后再移动到最终的缓存路径。设置这个参数为 off 可以避免使用临时路径,直接将缓存文件存储到指定的缓存路径中,提高缓存的效率。

# proxy_cache

  • 定义:启用缓存,制定缓存区。
  • 用法:
location / {
    proxy_cache my_cache;
    proxy_pass http://backend;
}

# SSL 配置

Nginx 支持 HTTPS,配置 SSL 可以提升安全性。

# ssl_certificate / ssl_certificate_key

  • 定义:指定 SSL 证书和秘钥。
  • 用法:
server {
    listen 443 ssl;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
}

# ssl_protocols

  • 定义:指定支持的 SSL/TLS 协议。
  • 用法:
ssl_protocols TLSv1.2 TLSv1.3;

# 日志相关配置

# access_log

  • 定义:指定访问日志文件路径和格式。
  • 用法:
# log_format 用于定义日志格式
log_format myFormat '$remote_addr$remote_user [$time_local] $request $status $body_bytes_sent $http_referer
access_log /var/log/nginx/access.log myFormat;

# 示例

来源:稀土掘金

# 全局段配置
# ------------------------------
# 指定运行 nginx 的用户或用户组,默认为 nobody。
#user administrator administrators;
# 设置工作进程数,通常设置为等于 CPU 核心数。
#worker_processes 2;
# 指定 nginx 进程的 PID 文件存放位置。
#pid /nginx/pid/nginx.pid;
# 指定错误日志的存放路径和日志级别。
error_log log/error.log debug;
# events 段配置信息
# ------------------------------
events {
    # 设置网络连接序列化,用于防止多个进程同时接受到新连接的情况,这种情况称为 "惊群"。
    accept_mutex on;
    # 设置一个进程是否可以同时接受多个新连接。
    multi_accept on;
    # 设置工作进程的最大连接数。
    worker_connections  1024;
}
# http 配置段,用于配置 HTTP 服务器的参数。
# ------------------------------
http {
    # 包含文件扩展名与 MIME 类型的映射。
    include       mime.types;
    # 设置默认的 MIME 类型。
    default_type  application/octet-stream;
    # 定义日志格式。
    log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for';
    # 指定访问日志的存放路径和使用的格式。
    access_log log/access.log myFormat;
    # 允许使用 sendfile 方式传输文件。
    sendfile on;
    # 限制每次调用 sendfile 传输的数据量。
    sendfile_max_chunk 100k;
    # 设置连接的保持时间。
    keepalive_timeout 65;
    # 定义一个上游服务器组。
    upstream mysvr {
      server 127.0.0.1:7878;
      server 192.168.10.121:3333 backup;  #此服务器为备份服务器。
    }
    # 定义错误页面的重定向地址。
    error_page 404 https://www.baidu.com;
    # 定义一个虚拟主机。
    server {
        # 设置单个连接上的最大请求次数。
        keepalive_requests 120;
        # 设置监听的端口和地址。
        listen       4545;
        server_name  127.0.0.1;
        # 定义 location 块,用于匹配特定的请求 URI。
        location  ~*^.+$ {
           # 设置请求的根目录。
           #root path;
           # 设置默认页面。
           #index vv.txt;
           # 将请求转发到上游服务器组。
           proxy_pass  http://mysvr;
           # 定义访问控制规则。
           deny 127.0.0.1;
           allow 172.18.5.54;
        }
    }
}

一些说明:

# sendfile

  • 定义: sendfile 是一种高效的文件传输方式,用于在操作系统层面直接将文件内容从磁盘传输到网络接口,绕过用户空间。它主要用于提高数据传输性能,特别是在处理大文件的场景下。
  • 工作原理:
    • 传统的文件传输过程通常需要以下步骤:
      • 将文件从磁盘读取到内核空间。
      • 将内核空间的数据拷贝到用户空间。
      • 用户空间将数据发送到网络接口。
    • sendfile 函数的作用是在内核空间中直接完成文件到网络套接字的传输,避免了数据从内核空间到用户空间的多次拷贝,从而减少了上下文切换和系统开销。整个过程简化为:直接将文件数据从内核空间传输到网络接口,无需经过用户空间。

# location 路径映射详解

以下格式用法在 nginx 均适用,例如:

if ($request_uri ~ ^/_proxy/(.*)){
    set $backend_host http://$1;
}

如果请求的 URI 匹配 ^/_proxy/(.*) 这个正则表达式,那么就将 $1 设置为变量 $backend_host 的值,

  • 格式:
location [ = | ~ | ~* | !~ | !~* | ^~ | @ ] uri {...}
  • 各标识符解释:
    • = :精确匹配。如果匹配成功,立即停止搜索并处理此请求。
    • ~ :执行正则匹配,区分大小写。
    • ~* :执行正则匹配,不区分大小写。
    • !~ :正则匹配,区分大小写不匹配。
    • !~* :正则匹配,不区分大小写不匹配。
    • ^~ :前缀匹配。如果匹配成功,不再匹配其他 location ,且不查询正则表达式。
    • @ :指定命名的 location ,主要用于内部重定向请求,如 error_pagetry_files
    • uri :待匹配的请求字符串。可以是普通字符串或包含正则表达式。
  • 优先级:优先级顺序:无特定标识 < ^~ < = < 正则匹配 ( ~ , ~* , !~ , !~* )
  • 示例:
location = / {
    # 精确匹配 /,主机名后面不能带任何字符串
    # http://abc.com [匹配成功]
    # http://abc.com/index [匹配失败]
}
location ^~ /img/ {
    # 以 /img/ 开头的请求,都会匹配上
    # http://abc.com/img/a.jpg [匹配成功]
    # http://abc.com/img/b.mp4 [匹配成功]
}
location ~* /Example/ {
    # 忽略 uri 部分的大小写
    # http://abc.com/test/Example/ [匹配成功]
    # http://abc.com/example/ [匹配成功]
}
location /documents {
    # 如果有正则表达式可以匹配,则优先匹配正则表达式
    # http://abc.com/documentsabc [匹配成功]
}
location / {
    # http://abc.com/abc [匹配成功]
}

# 动静分离

  • 概念:动静分离是指将动态内容和静态内容分开处理。静态内容通常包括:图片、CSS、JavaScript、HTML 文件等,这些内容不需要经常更改。而动态内容则是经常变化的,如:PHP、ASP、JSP、Servlet 等生成的内容。
  • 配置:
  1. 设置根目录
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
    root /path/to/static/files;
    expires 30d;  # 设置缓存时间
}

在上述配置中,所有的静态文件都被存放在 /path/to/static/files 目录下。 expires 指令设置了静态文件的缓存时间。

  1. 使用 alias 别名
location /static/ {
    alias /path/to/static/files/;
}

在这个配置中,URL 中的 /static/ 会映射到文件系统的 /path/to/static/files/

  1. 代理动态内容
location / {
    proxy_pass http://backend_server_address;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}
  • 注意事项:
    • 确保你的静态文件路径配置正确,避免 404 错误。
    • 使用 expires 指令为静态内容设置缓存,这可以减少服务器的负载并提高页面加载速度。
    • 动静分离不仅可以提高服务器的响应速度,还可以减少后端服务器的压力,因为静态文件通常由 Nginx 直接处理,而不需要代理到后端服务器。

# 防盗链

防盗链是指防止其他网站直接链接到你的网站资源(如图片、视频等),从而消耗你的服务器带宽。Nginx 提供了一个非常方便的模块 —— ngx_http_referer_module ,用于实现防盗链功能。

  • 基本配置:
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ {
    valid_referers none blocked www.example.com example.com *.example.net;
    if ($invalid_referer) {
        return 403;
    }
}
  • 说明:
    • valid_referers 定义了合法的来源页面。 none 表示直接访问, blocked 表示没有 Referer 头的访问, www.example.comexample.com 是合法的来源域名, *.example.net 表示 example.net 的所有子域名都是合法的来源。
    • $invalid_referer 变量会在来源不在 valid_referers 列表中时变为 "true"。
    • 如果来源不合法,服务器将返回 403 禁止访问的状态码。
  • 注意事项:
    • 防盗链配置可能会影响搜索引擎的爬虫,因此在实施防盗链策略时要小心。
    • 如果你的网站使用了 CDN,确保 CDN 的服务器也在 valid_referers 列表中,否则 CDN 可能无法正常工作。
    • 为了确保防盗链配置正确,你应该在生产环境之前在测试环境中进行充分的测试。