# Nginx基础知识

声明:本文转自他人

  1. Nginx 概述

Nginx 是一个高性能的 HTTP 和反向代理服务器,广泛用于处理大量并发连接。它的设计初衷是为了应对高流量网站的需求,具有占用内存少和并发能力强的特点。

Nginx 由俄罗斯的程序员伊戈尔·赛索耶夫 在2002开始设计,并于 2004 年发布第一个公开版本。

# 定义

Nginx("engine x")是一个开源的 Web 服务器软件,主要用于提供 HTTP 服务,同时也支持反向代理、负载均衡、IMAP/POP3/SMTP 等功能。它的高效处理能力使其成为现代 Web 应用程序架构中不可或缺的一部分。

# 用途

  1. HTTP 服务器:Nginx 可以作为静态内容的服务器,处理 HTML 文件、图片、CSS 和 JavaScript 等静态资源。

  2. 反向代理服务器:Nginx 可以接收来自客户端的请求,并将其转发到后端服务器(如应用服务器或数据库服务器)。这使得 Nginx 能够隐藏后端服务器的真实地址,增强安全性,同时可以实现负载均衡,分散请求到多个后端服务器上,以提高处理能力和可靠性。

  3. 负载均衡:Nginx 支持多种负载均衡算法(如轮询、最少连接、IP 哈希等),能够有效分配客户端请求,提高系统的响应速度和可用性。

  4. SSL/TLS 终止:Nginx 可以处理 HTTPS 请求,提供 SSL/TLS 加密,确保数据传输的安全性。

  5. 缓存:Nginx 可以缓存后端服务器的响应,以减少对后端的请求,提高访问速度和系统性能。

  6. 动静分离:Nginx 可以将静态资源和动态请求分开处理,通常使用 Nginx 处理静态内容,而将动态请求转发到后端应用服务器(如 Tomcat)。

Nginx 的灵活性和高性能使其成为许多大型网站(如百度、京东、腾讯等)的首选解决方案,能够有效支持高并发的访问需求。

  1. Nginx 安装与配置

可参考网上教程,不多赘述

官方网站:https://nginx.org/en/download.html (opens new window)

Nginx模块的配置文件路径(一般情况下) /etc/nginx/nginx.conf

  1. Nginx 工作原理

Nginx 的工作原理基于其多进程架构,主要由两个类型的进程组成:master 进程worker 进程。这种设计使得 Nginx 能够高效地处理大量并发请求,确保其在高负载情况下的稳定性和性能。

  1. Nginx 的多进程架构

# Master 进程

  • 角色:Master 进程是 Nginx 的主控制进程,负责管理整个 Nginx 的生命周期。

  • 功能:启动和管理 worker 进程。处理配置文件的加载和信号的接收(如重载配置、优雅关闭等)。监控 worker 进程的状态,确保其正常运行。

  • 进程数量:通常只有一个 master 进程在运行。

# Worker 进程

  • 角色:Worker 进程是实际处理客户端请求的进程。每个 worker 进程可以独立处理多个连接。

  • 功能:接收和处理来自客户端的请求。执行具体的请求响应逻辑,包括与后端服务器的通信、静态文件的服务等。通过事件驱动机制(如 epoll)高效管理连接,处理大量并发请求。

  • 进程数量:可以根据服务器的 CPU 核心数配置多个 worker 进程,以提高并发处理能力。一般建议设置为与 CPU 核心数相同或稍多。

  1. 工作流程
  • 请求接收:客户端发送请求到 Nginx,master 进程接收请求并将其分发给可用的 worker 进程。

  • 请求处理:worker 进程接收到请求后,根据配置文件中的规则处理请求,包括反向代理、负载均衡、静态文件服务等。

  • 响应返回:worker 进程处理完请求后,将响应数据返回给客户端。

这种多进程架构使得 Nginx 能够充分利用多核 CPU 的优势,提升并发处理能力,确保在高流量情况下的稳定性和响应速度。通过 master 进程的管理和 worker 进程的高效处理,Nginx 成为一个极为强大的 Web 服务器和反向代理解决方案。

  1. 反向代理

    1. 反向代理的概念

反向代理是一种代理服务器,位于客户端和后端服务器之间,主要用于接收客户端的请求并将其转发给相应的后端服务器,然后将后端服务器的响应返回给客户端。反向代理的工作方式对客户端是透明的,客户端并不知道其请求被转发到了哪台服务器。

    反向代理的核心功能是充当中介,接收来自客户端的请求并将其转发到内部网络中的真实服务器,而不需要直接访问后端服务器,这样可以隐藏后端服务器的真实地址。
  1. 反向代理的应用
  • 负载均衡:反向代理可以根据后端服务器的负载情况,将请求分发到不同的服务器上,从而实现负载均衡。这有助于提高系统的性能和可用性,防止某一台服务器过载而导致性能下降。

  • 安全性:通过使用反向代理,后端服务器的 IP 地址可以被隐藏,从而提高系统的安全性。反向代理可以过滤掉无权限或非法的请求,保护内部服务器免受直接攻击。

  • Web 加速:反向代理能够缓存常见的请求内容,压缩入站和出站数据,从而加快客户端和服务器之间的流量速度。此外,它还可以处理 SSL 加密,减轻后端服务器的负担。

  • 请求转发:反向代理可以根据请求的 URL 或其他参数,将请求转发到特定的后端服务器。这种灵活性使得系统可以根据不同的业务需求进行动态调整。

  • 故障转移:如果某台后端服务器发生故障,反向代理可以自动将流量重定向到其他可用的服务器,确保服务的连续性和可靠性。

反向代理在现代 Web 应用架构中扮演着重要的角色,帮助提升系统的性能、安全性和可维护性。

  1. 反向代理机制如何工作

Nginx 的反向代理机制是一种网络架构模式,主要用于接收客户端的请求并将其转发到后端服务器,然后将后端服务器的响应返回给客户端。以下是 Nginx 反向代理机制的工作原理:

  1. Nginx 反向代理工作原理

    1. 请求接收
    • 当客户端发送 HTTP 请求时,Nginx 作为反向代理服务器接收这些请求。此时,客户端并不知道其请求被转发到哪个后端服务器。
    1. 请求转发
    • Nginx 根据配置文件中的 proxy_pass 指令,将接收到的请求转发到指定的后端服务器。这个指令可以指定后端服务器的地址,包括协议(如 HTTP 或 HTTPS)、主机名或 IP 地址及端口号。
    1. 处理请求
    • 后端服务器接收到请求后,进行相应的处理,并生成响应数据。
    1. 响应返回
    • 后端服务器将处理结果返回给 Nginx,Nginx 再将这些响应数据返回给原始的客户端。
  2. 反向代理的优势

  • 负载均衡:Nginx 可以将请求分发到多个后端服务器,实现负载均衡,提升系统的并发处理能力和稳定性。

  • 安全性:通过反向代理,Nginx 可以隐藏后端服务器的真实地址,提供额外的安全防护,防止直接访问后端服务器。

  • 缓存加速:Nginx 可以缓存静态资源或动态页面的响应结果,提高响应速度,减轻后端服务器的负担。

  • 协议转换:Nginx 可以处理 HTTP 和 HTTPS 之间的协议转换,支持安全通信。

  • 请求头处理:Nginx 可以通过 proxy_set_header 指令设置请求头,以便将客户端的真实 IP 等信息传递给后端服务器。

以下是一个简单的 Nginx 反向代理配置示例:

http {
    upstream backend {
        server backend1.example.com;
        server backend2.example.com;
    }
​
    server {
        listen 80;
        server_name example.com;
​
        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
        
    }
}
  1. 延伸

# 反向代理与正向代理

正向代理是一个位于客户端和服务器之间的代理服务器,客户端通过这个代理服务器来访问目标服务器。 反向代理:是为服务器服务的 正向代理:是为客户端服务 客户端将请求发送给正向代理服务器,代理服务器再将请求转发到目标服务器,并将服务器的响应返回给客户端。客户端知道目标服务器的地址,但目标服务器不知道客户端的真实 IP。

类型 正向代理 反向代理
代理对象 代理客户端,帮助客户端访问外部服务器 代理服务器,帮助服务器处理来自客户端的请求
客户端是否知道服务器 客户端知道目标服务器 客户端不知道后端服务器
服务器是否知道客户端 服务器知道客户端 服务器不知道客户端
主要功能 访问受限资源、隐藏客户端身份 负载均衡、隐藏服务器、增强安全性
常见应用场景 用户通过代理访问外部网站,如 VPN 等 网站使用反向代理进行负载均衡和缓存,如 Nginx
  1. 负载均衡

Nginx 支持多种负载均衡策略,可以根据实际需求进行选择。常见的负载均衡策略包括:

负载均衡策略 使用方式 特点 优点 缺点 使用场景 注意事项
轮询(默认) 无需额外配置 按时间顺序逐一将请求分配到不同的服务器 简单易用,适用于大多数场景 不考虑服务器负载情况,可能导致负载不均 适用于后端服务器性能一致的场景 如果服务器性能不一致,可能造成性能瓶颈
最少连接 least_conn; 将请求分配给当前连接数最少的服务器 更智能的负载均衡,适合长连接场景 实时计算连接数,可能增加服务器开销 长连接场景,如 WebSocket,API 服务 配置复杂度较低,但适合长时间处理的请求
IP 哈希 ip_hash; 根据客户端 IP 进行哈希分配请求 保证相同客户端 IP 始终访问同一服务器,适合会话保持 客户端 IP 分布不均可能导致负载不均 需要会话保持的场景,如购物车、登录状态管理 若使用 NAT,多个客户端可能共享相同 IP,影响负载分配
权重 server 127.0.0.1:8080 weight=3; 根据服务器权重分配请求,权重越大,被分配几率越大 灵活性高,可根据服务器性能调整负载分配 不自动调整负载,需要手动配置权重 服务器性能不均衡的场景 合理设置权重至关重要,需考虑实际服务器性能
fair(第三方) fair;(需要第三方模块) 根据服务器响应时间分配请求,响应时间短的优先 动态负载均衡,提升系统响应效率 依赖第三方模块,增加系统复杂度 服务器性能波动较大的动态负载场景 第三方模块支持,监控响应时间增加负载
url_hash(第三方) hash $request_uri;(需要第三方模块) 根据 URL 哈希结果分配请求,相同 URL 总是分配给同一服务器 提高缓存命中率,减少重复计算 URL 分布不均可能导致负载不均,依赖第三方模块 静态资源缓存、CDN 增加/减少服务器节点时,可能导致哈希失效,缓存失效
  • 轮询:最基础的策略,适合均衡的服务器场景,简单高效。

  • 最少连接:适合处理长连接或不同请求处理时间差异大的场景,确保实时负载均衡。

  • IP 哈希:会话保持的绝佳选择,但要考虑 NAT 环境下的影响。

  • 权重:灵活且适合服务器性能不均衡的场景,但需要管理员手动配置。

  • fair:动态响应时间调度,适合实时负载调整的场景,但需使用第三方模块。

  • url_hash:提升缓存系统的一致性,适合静态资源分发或缓存优化场景。

# 1)轮询(默认)

描述:每个请求按时间顺序逐一分配给不同的后端服务器,默认情况下,不需要额外配置。

特点:优点:简单有效,均匀分配负载。缺点:忽略了服务器的实际负载情况。

当后端服务器宕机时,Nginx 会自动剔除它,不再分配请求给它。

upstream backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

# 2)最少连接

“最少连接”策略是 Nginx 中的一种负载均衡方式,它会将新的请求分配给当前连接数最少的后端服务器。这种策略特别适合处理长连接或者每个请求的处理时间较长的应用场景(例如 WebSocket 或者长轮询)。

智能负载均衡:相比默认的轮询,它更为智能,因为它考虑了每个服务器的实时负载情况。

适合长连接:如果每个请求的处理时间不同或有长时间保持的连接,那么“最少连接”策略可以确保将新请求分配给负载较轻的服务器,从而减少延迟。

动态调整:随着连接数的变化,Nginx 会自动调整每个服务器分配到的请求数量。

upstream backend {
    least_conn;  # 启用最少连接策略
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

# 3)IP哈希

根据客户端IP的哈希结果来分配请求,确保来自同一个IP的客户端始终访问到同一个后端服务器。这种方式适合需要会话保持的应用场景,如在线购物车系统、用户登录状态管理等。

# 特点:

会话保持:客户端的每次请求都发送到同一个服务器,适用于需要保持状态的场景。

避免状态丢失:适合那些不能轻易共享会话或状态的应用,确保在相同服务器上处理相同客户端的请求。

分布稳定性:哈希算法可以均匀分配请求,避免某台服务器负载过高。

upstream backend {
    ip_hash;  # 启用IP哈希策略
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}

# 注意事项:

  • 负载不均问题:如果客户端的 IP 分布不均匀,可能会导致某些服务器负载较高,而其他服务器负载较轻。

  • NAT 问题:如果客户端的 IP 地址通过 NAT 设备转换,多个客户端会显示相同的 IP 地址,可能会导致多个客户端请求被分配到同一台服务器,导致负载不均。

# 4)权重

指定轮询几率,weight值越大,被分配到的几率越大。

负载均衡策略允许为每台后端服务器分配不同的权重,权重值越大,被分配到请求的几率越高。通过这种方式,Nginx 可以根据每台服务器的处理能力或者当前负载情况来进行合理的请求分配,适用于服务器性能不均衡的场景。

# 特点:

灵活的负载分配:可以根据服务器的处理能力或者业务需求灵活调整负载分配比例。

适应性能差异:适合在服务器性能不同的情况下,为性能较好的服务器分配更多的请求,提升整体处理效率。

简单配置:只需设置不同的权重值,Nginx 会自动按照比例分配请求。

upstream backend {
    server 127.0.0.1:8080 weight=3;  # 权重为3
    server 127.0.0.1:8081 weight=1;  # 权重为1
}

# 使用场景:

服务器性能不均衡:当服务器性能差异较大时,可以为性能更高的服务器配置更高的权重,从而让它处理更多的请求。

负载优化:通过合理配置权重,动态调整各服务器的请求数量,优化整体的负载分配。

# 注意事项:

  • 合理设置权重:应根据服务器的实际处理能力来设置权重,过高或过低的权重都可能导致负载不均或资源浪费。

  • 健康检查结合:如果某台服务器出现故障(宕机),Nginx 会自动跳过该服务器进行分配,不再根据权重进行调度。

# 5)fair(公平调度)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

需要通过安装第三方模块(如 ngx_http_upstream_fair_module)来实现。 下载地址:https://github.com/gnosek/nginx-upstream-fair 安装参考:https://cloud.tencent.com/developer/article/1692153 该策略根据后端服务器的响应时间来分配请求,响应时间较短的服务器优先处理新的请求。这种方式可以有效避免请求被分配到负载过重的服务器上,适合需要根据实时负载动态调整请求分配的场景。

# 特点:

  • 动态响应:根据服务器的实际响应时间动态分配请求,确保性能较好的服务器处理更多请求。

  • 避免过载:可以避免请求被分配到响应时间较长的服务器,降低服务器过载的可能性。

  • 实时优化:能够在多服务器环境中保持较好的性能分配。

upstream backend {
    fair;  # 启用 fair 调度策略
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

# 使用场景:

  • 动态负载场景:如请求处理时间差异较大或后端服务器的负载经常变化的场景,能够动态调整负载分配,提升系统响应效率。

  • 提高响应速度:适合对响应时间敏感的应用,可以优先分配请求给响应更快的服务器,减少整体的请求延迟。

# 注意事项:

  • 第三方模块支持:Nginx 默认不支持 fair 策略,需要通过安装第三方模块(如 ngx_http_upstream_fair_module)来启用该功能。

  • 复杂性增加:由于该策略需要动态监控服务器的响应时间,可能会增加负载均衡的计算复杂度,尤其是在大量服务器节点的情况下。

# 优缺点总结:

  • 优点:能够更好地平衡负载,避免服务器过载,提升系统整体的响应速度。

  • 缺点:依赖第三方模块,且监控服务器响应时间会增加一定的系统开销。

# 总结

策略是为高性能和负载优化场景而设计的,当需要根据服务器的实时性能进行负载均衡时,它能够显著提高系统的响应效率。

# 6)url_hash(第三方)

根据请求的URL的hash结果来分配请求,使每个URL定向到同一个后端服务器。

需要通过第三方模块(如 ngx_http_upstream_hash_module)来实现。 下载地址:https://github.com/evanmiller/nginx_upstream_hash 该策略根据请求的URL 的哈希值将请求分配给后端服务器,这样相同的 URL 始终会被分配到同一台服务器。这种方式可以保证请求的一致性,尤其是在与缓存系统结合使用时,避免不同服务器处理相同的请求导致缓存不一致。

# 特点:

  • 一致性分配:相同的 URL 请求总是被分配到同一台服务器。

  • 缓存优化:适用于静态资源缓存场景,确保缓存的一致性,减少缓存穿透。

  • 负载均衡:在负载均衡的同时,保证相同 URL 的请求总是由同一台服务器处理,减少后端重复计算和资源占用。

upstream backend {
    hash $request_uri;  # 根据请求的URL进行哈希
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

# 使用场景:

  • 静态资源分发:适用于静态资源服务和 CDN 缓存场景,确保相同的 URL 请求总是由同一台服务器处理,从而提高缓存命中率。

  • 数据一致性场景:在需要保持同一资源一致性的场景下,url_hash 可以避免不同服务器间的数据不同步问题,尤其适合需要高命中率的缓存系统。

# 注意事项:

  • 依赖第三方模块:Nginx 默认不支持 url_hash 策略,必须通过安装第三方模块 ngx_http_upstream_hash_module 实现。

  • 负载分布问题:如果某些 URL 访问量过大,会导致某些服务器负载过高,可能出现负载不均衡的情况。

  • 节点变动影响:如果增加或减少后端服务器节点,可能会改变现有的 URL 哈希分配,导致部分请求被分配到不同的服务器,缓存可能会失效。

# 优缺点总结:

  • 优点:提高缓存一致性,减少不同服务器对相同 URL 的重复计算,适合需要高缓存命中率和一致性的场景。

  • 缺点:如果访问的 URL 分布不均匀,可能导致某些服务器负载较高,影响整体负载均衡效果。

策略非常适合与缓存系统结合使用,尤其是 CDN、静态资源缓存等场景,通过确保相同的 URL 始终被同一服务器处理,可以大幅提升缓存命中率并减少后端服务器的重复工作。

# 示例配置

以下是一个完整的负载均衡策略的示例配置:

http {
    upstream backend {
        least_conn;
        server backend1.example.com;
        server backend2.example.com;
        server backend3.example.com;
    }
​
    server {
        listen 80;
        server_name example.com;
​
        location / {
            proxy_pass http://backend;
        }
    }
}

在这个示例中,Nginx 会根据后端服务器的连接数情况,将请求分配给当前连接数最少的服务器。通过合理选择负载均衡策略,可以有效提高系统的可用性和响应速度。不同的策略适用于不同的场景,需要根据实际情况进行评估和选择。

upstream tornado_servers {
    server 127.0.0.1:29100 weight=100;
    server 127.0.0.1:29101 weight=100;
    check interval=30000 rise=3 fall=3 timeout=30000 type=tcp;
}
  1. 虚拟主机配置

虚拟主机配置允许在一台服务器上托管多个独立的网站。通过配置多个 server 块,可以实现基于域名、IP 地址或端口的虚拟主机。

  1. 虚拟主机的类型
  • 基于域名的虚拟主机:通过不同的域名来区分不同的网站,最常用的方式。

  • 基于IP的虚拟主机:每个虚拟主机使用不同的IP地址。

  • 基于端口的虚拟主机:同一IP地址上,通过不同的端口来区分虚拟主机。

虚拟主机类型 使用方式 优点 缺点 使用场景
基于域名的虚拟主机 通过不同的域名区分虚拟主机,使用同一IP地址 易于管理,不需要分配多个IP,节省IP资源 依赖于客户端支持HTTP/1.1,SSL配置复杂(多域名时需SNI支持) 共享主机、需要通过多个域名托管多个网站的场景
基于IP的虚拟主机 每个虚拟主机绑定不同的IP地址 适用于不支持HTTP/1.1的客户端,SSL配置简单 IP资源消耗大,需为每个虚拟主机分配单独的IP 需要为每个网站分配唯一IP的情况,SSL不支持SNI的场景
基于端口的虚拟主机 通过不同的端口号区分虚拟主机,使用同一IP地址 节省IP地址,配置简单 需要用户指定端口号,默认端口号以外的访问需要明确指定 测试环境、内部系统或者指定端口访问的场景

SNI(服务器名称指示,Server Name Indication) 是 TLS/SSL 协议的一个扩展,它允许在同一个 IP 地址和端口上托管多个 SSL 证书,以支持多个 HTTPS 网站。SNI 解决了传统 SSL 协议在虚拟主机环境下的限制,使得基于域名的虚拟主机能够通过同一个 IP 地址提供 HTTPS 服务。

SNI 通过让客户端在发起 SSL 握手时,在握手消息中发送所请求的主机名(域名),这样服务器就可以知道客户端希望访问哪个网站,并返回相应的 SSL 证书。基于 SNI 的服务器可以为多个域名配置不同的证书,即使这些域名共享同一个 IP 和端口。

用最少的端口,实现服务的代理

  1. 配置步骤

    1. 准备网站文件

首先,确保每个虚拟主机都有独立的网站文件。假设我们要配置两个网站:example1.comexample2.com

bashmkdir -p /var/www/example1
mkdir -p /var/www/example2
​
echo '<h1>Welcome to Example 1</h1>' > /var/www/example1/index.html
echo '<h1>Welcome to Example 2</h1>' > /var/www/example2/index.html
  2. 配置 Nginx 虚拟主机

编辑 Nginx 的配置文件,通常位于 /etc/nginx/nginx.conf/etc/nginx/conf.d/ 目录下的 .conf 文件中。以下是一个示例配置:

http {
    include       mime.types;
    default_type  application/octet-stream;
​
    server {
        listen       80;
        server_name  example1.com www.example1.com;
​
        location / {
            root   /var/www/example1;
            index  index.html index.htm;
        }
    }
​
    server {
        listen       80;
        server_name  example2.com www.example2.com;
​
        location / {
            root   /var/www/example2;
            index  index.html index.htm;
        }
    }
}

在这个配置中,两个 server 块分别定义了两个虚拟主机。每个虚拟主机都有自己的 server_nameroot 指令,指向不同的网站文件目录。 3. 测试配置并重启 Nginx

在修改配置文件后,使用以下命令测试 Nginx 配置的正确性:

nginx -t

图片

如果以上图片所示successful 表示配置文件没有错误,重启 Nginx 以使配置生效:

systemctl restart nginx
或者
nginx -s reload
  1. location 匹配规则

在 Nginx 中,location 指令用于根据请求的 URI 匹配特定的处理规则。理解 location 指令的使用及其匹配规则对于配置 Nginx 是很重要的。

  1. Nginx 中 location 指令的使用

location 指令的基本语法如下:

location [=|~|~*|^~|@] /uri/ {
    # 配置
}
  1. 匹配类型比较
匹配类型 配置方式 特点 使用场景 匹配优先级
精确匹配 (=) location = /exact-path 路径必须与请求的 URI 完全匹配 特定文件或路径请求,如 /favicon.ico 1
区分大小写的正则匹配 (~) location ~ regex 使用正则表达式匹配,区分大小写 复杂路径匹配,如 .php 文件 3
不区分大小写的正则匹配 (****~*) location ~* regex 使用正则表达式匹配,不区分大小写 忽略大小写的复杂路径匹配,如图片文件 4
前缀匹配(带**^~****)** location ^~ /prefix 当 URI 以指定前缀开头时,停止进一步匹配正则规则;性能高 避免使用正则匹配时的额外开销,常用于高流量或静态资源路径,如 /static/ 2
普通前缀匹配 location /prefix 匹配以指定路径为前缀的所有 URI,默认的前缀匹配类型 处理通用路径,如 /images/、 /api/ 5
  1. 匹配优先级

当多个 location 规则存在时,Nginx 会按照以下优先级进行匹配:

精确匹配 (=) > 前缀匹配(带 ^~ )> 正则匹配(区分大小 ~ ) > 正则匹配(不区分大小写 ~*) > 普通前缀匹配

  1. 匹配规则

    1. 精确匹配 (=)

只有当请求的 URI 完全匹配指定的 URI 时,该规则才会生效。

示例:

 location = /example {    # 处理请求}

注:仅当请求为 /example 时才匹配。 2. 区分大小写的正则匹配 (~)

使用正则表达式进行匹配,并且匹配是区分大小写的。

示例:

location ~ \.php$ {    # 处理 PHP 文件}
 
location ~ ^/images/.*\.(jpg|jpeg|png)$ {
    root /var/www/html;
    # 处理图片请求
}

注:该规则匹配所有以 .php 结尾的请求。

  3. 不区分大小写的正则匹配 (~\*)

使用正则表达式进行匹配,且匹配不区分大小写。

示例:

 location ~* \.jpg$ {    # 处理 JPG 文件}

注:该规则匹配所有以 .jpg.JPG 结尾的请求。 4. 前缀匹配 (^~)

用于普通字符的前缀匹配,如果该规则匹配成功,则不再进行正则匹配。

示例:

 location ^~ /images/ {    # 处理图像请求}

注:该规则匹配所有以 /images/ 开头的请求。

  5. 普通前缀匹配

不带任何修饰符的 location 指令表示普通的前缀匹配,优先级低于精确匹配和 ^~ 前缀匹配。

示例:

 location / {    # 处理所有未匹配的请求}
  1. 示例配置

以下是一个简单的 Nginx 配置示例,展示了如何使用不同的 location 指令:

server {
    listen 80;
    server_name example.com;
​
    location = / {
        return 200 "Welcome to Example.com";
    }
​
    location ^~ /images/ {
        root /var/www/images;
    }
​
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
    }
​
    location / {
        try_files $uri $uri/ =404;
    }
}

在这个示例中,Nginx 会根据请求的 URI 选择合适的 location 块进行处理。理解这些匹配规则能够帮助管理员更灵活地配置 Nginx,以满足不同的业务需求。

  1. 关键字: break 和 last
关键字 描述 使用场景 示例
break 停止当前的请求处理,继续在当前 location 块中执行后续指令,但不重新评估请求的 URI。 需要在当前 location 块中处理请求,但不希望触发其他 location 块时使用。 例如,处理静态文件请求或进行简单的重写,而不需要改变请求的 URI。
last 停止当前的请求处理,并重新评估请求的 URI,寻找匹配的新 location 块。 当需要将请求重写到新的 URI,并希望 Nginx 重新评估以找到合适的 location 块时使用。 例如,重定向到一个新的路径,并希望根据新的路径应用不同的配置或处理

# 使用 break 的示例:

server {
    listen 80;
    server_name example.com;


    location / {
        rewrite ^/old/(.*)$ /new/$1 break;  # 处理完后继续在当前 location 块中
        # 其他处理逻辑
    }
}

# 使用 last 的示例

server {
    listen 80;
    server_name example.com;


    location / {
        rewrite ^/old/(.*)$ /new/$1 last;  # 重写后重新评估请求
    }


    location /new/ {
        # 针对 /new/ 的处理逻辑
    }
}


# 思考题

根据以下配置内容,判断当请求/1.html,最终访问到哪个页面?

# 思考题1

连续两条rewrite规则

server{
    listen 8081; 
    server_name _;
    root /var/www/html2;


    rewrite /1.html /2.html ;
    rewrite /2.html /3.html ;
    
}

# 思考题2

server 中没有location

server{
    listen 8081; 
    server_name _;
    root /var/www/html2;


    rewrite /1.html /2.html break;
    rewrite /2.html /3.html;
}

# 思考题3

break或last后面还有location时

server{
    listen 8081; 
    server_name _;
    root /var/www/html2;


    rewrite /1.html /2.html;
    break;
    rewrite /2.html /3.html;    
   
    location /2.html {              
        return 403;
    }
}


# 思考题4

当break在location{}里面

多个rewrite 没有break

server{
    listen 8081; 
    server_name _;
    root /var/www/html2;
    
    location / {
        rewrite /1.html /2.html;
        rewrite /2.html /3.html;
    }
    location /2.html {
        rewrite /2.html /a.html;
    }
    location /3.html {
        rewrite /3.html /b.html;
    }
}

# 思考题5

location 里面有break

server{
    listen 8081; 
    server_name _;
    root /var/www/html2;
    
    location / {
        rewrite /1.html /2.html;
        break;
        rewrite /2.html /3.html;
    }
    location /2.html
    {
        rewrite /2.html /a.html;
    }
    location /3.html
    {
        rewrite /3.html /b.html;
    }
}

# 思考题6

last 在location里面

  server{
      listen 8081; 
      server_name _;
      root html;
      
      location / {
          rewrite /1.html /2.html last;
          rewrite /2.html /3.html;        
      }
      location /2.html
      {
          rewrite /2.html /a.html;
      }
      location /3.html
      {
          rewrite /3.html /b.html;
      }
  }
  1. 重定向
指令 作用 语法 特点
rewrite 根据正则表达式重写请求的 URI rewrite regex replacement [flag]; - 可以修改 URI 的部分或全部内容。
return 立即返回指定的 HTTP 状态码和可选的响应内容 return code [text]; - 用于简单的重定向或返回错误信息。
root 设置请求的根目录 root path; - 请求的 URI 会被追加到 root 指定的路径后面。
alias 设置请求的别名路径 alias path; - 请求的 URI 中的 location 部分会被替换为 alias 指定的路径。

# rewrite

  • 含义:rewrite 指令用于根据正则表达式重写请求的 URI。它可以改变请求的 URL,并可以选择是否继续处理该请求。

  • 使用场景:当需要根据特定的 URL 模式重定向请求到新的 URL,或者需要修改请求的 URI 时使用。

location /old {
    rewrite ^/old/(.*)$ /new/$1 permanent;  # 将 /old/ 重定向到 /new/
}

# return

  • 含义:return 指令用于立即返回指定的 HTTP 状态码和可选的响应内容。它通常用于简单的重定向或返回错误信息。

  • 使用场景:当需要快速重定向到新的 URL 或返回特定的状态码时使用,通常比 rewrite 更高效。

location / {
    return 301 http://www.example.com/new;  # 永久重定向到新 URL
}

# root

  • 含义:root 指令用于指定请求的根目录。它定义了文档根目录的路径,Nginx 将根据此路径查找请求的文件。

  • 使用场景:用于配置静态文件的存放路径,例如 HTML、CSS、JavaScript 文件等。

location / {
    root /var/www/html;  # 设置文档根目录
}

# alias

  • 含义:alias 指令用于设置请求的别名路径。它告诉 Nginx 将请求的 URI 中的 location 部分替换为 alias 指定的路径。

  • 路径处理:当使用 alias 指令时,URI 中的 location 部分会被替换为 alias 指定的路径。例如,如果配置为 alias /var/www/static;,请求 /images/logo.png 将被解析为 /var/www/static/logo.png

  • 使用场景:适合用于复杂的 URI 映射,特别是当需要将多个 URI 映射到同一个目录时,或者 URI 结构与文件系统结构不一致时。

location /images/ {
    alias /var/www/static/;  # 处理请求时查找 /var/www/static/logo.png
}
  1. 动静分离

动静分离的核心思想是将不经常变化的静态资源(如图片、CSS、JavaScript 文件)与经常变化的动态内容(如数据库驱动的网页)分开处理。Nginx 作为反向代理服务器,负责处理静态资源请求,而将动态请求转发给后端应用服务器(如 Tomcat、Node.js 等)。

  1. 准备静态资源

确保您的静态资源文件已经准备好,通常存放在一个专门的目录中。例如:

mkdir -p /var/www/static
echo '<h1>Welcome to Static Content</h1>' > /var/www/static/index.html
  1. 编辑 Nginx 配置文件

打开 Nginx 的配置文件,通常位于 /etc/nginx/nginx.conf/etc/nginx/conf.d/ 目录下的 .conf 文件中。以下是一个示例配置,展示了如何实现动静分离:

http {
    include       mime.types;
    default_type  application/octet-stream;
​
    server {
        listen       80;
        server_name  example.com;
​
        # 配置静态资源的处理
        location /static/ {
            alias /var/www/static/;  # 指定静态资源的路径
            expires 30d;             # 设置缓存过期时间
            add_header Cache-Control public;  # 设置缓存控制头
        }
​
        # 配置动态请求的处理
        location / {
            proxy_pass http://backend_server;  # 将请求转发给后端服务器
            proxy_set_header Host $host;        # 设置请求头
            proxy_set_header X-Real-IP $remote_addr;  # 传递客户端真实 IP
        }
    }
}
  • 静态资源处理location /static/:匹配所有以 /static/ 开头的请求。alias /var/www/static/;:指定静态资源的存储路径。expires max;:设置缓存过期时间,浏览器在此时间内无需重新请求服务器。add_header Cache-Control public;:设置缓存控制头,允许浏览器缓存。

  • 动态请求处理location /:匹配所有其他请求。proxy_pass http://backend_server;:将请求转发到后端服务器(如 Tomcat)。proxy_set_header 指令用于传递客户端的请求头信息。

    1. 测试和重启 Nginx

在修改配置文件后,使用以下命令测试 Nginx 配置的正确性:

nginx -t

如果没有错误,重启 Nginx 以使配置生效:

systemctl restart nginx
或者
nginx -s reload
  1. Nginx 日志管理

掌握访问日志和错误日志的配置与分析方法。

访问日志记录了所有客户端请求的信息,包括请求的时间、请求的 URL、响应状态、客户端 IP 地址等。

访问日志可以通过 access_log 指令进行配置。

错误日志记录了 Nginx 在处理请求时遇到的错误信息。可以通过 error_log 指令进行配置。

默认记录的日志格式

$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"

图片

具体字段含义如下:

  • $remote_addr:客户端 IP 地址。

  • $remote_user:远程用户名称,如果使用了 HTTP 基本认证,这里会记录认证用户名;没有时为空。

  • $time_local:本地时间,表示请求的时间。

  • $request:客户端的请求行,包括请求方法、URI 和 HTTP 版本。

  • $status:响应状态码,比如 200 表示成功,404 表示资源未找到。

  • $body_bytes_sent:发送给客户端的字节数,不包括响应头。

  • $http_referer:从哪个页面跳转过来的,如果没有则为 "-"

  • $http_user_agent:客户端的用户代理信息,一般是浏览器的类型和版本信息。

修改日志记录格式:

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;
    error_log /var/log/nginx/error.log crit;
    server {
        listen 80;
        server_name example.com;
​
        location / {
            # 处理请求
        }
    }
}
  1. 重要变量
  • $remote_addr:客户端的 IP 地址。

  • $remote_user:客户端的用户名(如果有)。

  • $time_local:请求的时间和时区。

  • $request:请求的方式和 URI。

  • $status:响应状态码(如 200、404)。

  • $body_bytes_sent:发送给客户端的字节数。

  • $http_referer:请求来源页面。

  • $http_user_agent:客户端浏览器的用户代理信息。

  • $http_x_forwarded_for:客户端的真实 IP 地址(如果经过代理)。

    1. 错误日志级别

错误日志的级别可以设置为以下几种:

  • emerg:紧急情况,Nginx 不可用、通常是系统级别的故障,如磁盘满、核心崩溃等。。

  • alert:必须立即处理的问题,如数据库无法连接等。

  • crit:严重情况,关键功能失败,如配置文件语法错误等。

  • error:一般错误,通常会影响服务功能,如请求失败等。

  • warn:警告,但不影响服务运行,可能是潜在问题。

  • notice:正常但重要的事件。

  • info:普通信息性消息。

  • debug:调试级别的详细信息,记录所有活动细节,可以帮助开发人员排查问题。

    1. 日志分析

# 常用分析命令

# 查看访问日志

cat /var/log/nginx/access.log

# 统计特定状态码的请求**:**

grep "404" /var/log/nginx/access.log | wc -l

# 列出响应时间超过 3 秒的请求**:**

awk '{ if ($NF > 3) print $0; }' /var/log/nginx/access.log

# 获取访问量前 10 的 IP 地址**:**

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -n 10
  1. 常见错误码以及解决方案
错误码 描述 原因 解决方案
400 Bad Request 请求的语法错误,服务器无法理解 - 检查请求的格式和内容。 - 查看 Nginx 的错误日志,获取详细信息。
401 Unauthorized 请求未提供有效的身份验证凭据 - 确保请求中包含正确的身份验证信息。 - 检查身份验证配置。
403 Forbidden 服务器理解请求但拒绝执行 - 检查文件和目录的权限。 - 查看 allow 和 deny 指令,确保访问控制设置正确。
404 Not Found 请求的资源未找到,可能是 URL 错误或文件不存在 - 检查请求的 URL 是否正确。 - 确保请求的文件或目录存在于服务器上。 - 检查 root 或 alias 指令是否指向正确的路径。
405 Method Not Allowed 请求使用了不被允许的 HTTP 方法 - 检查 Nginx 配置,确保允许的 HTTP 方法与请求相匹配。 - 修改客户端请求,使用正确的方法。
500 Internal Server Error 服务器内部错误,无法完成请求 - 查看 Nginx 和应用程序的错误日志。 - 检查 Nginx 配置文件的语法。 - 确保后端服务正常运行。
502 Bad Gateway Nginx 未能从上游服务器获得有效响应 - 检查上游服务器是否正在运行。 - 验证 proxy_pass 指令是否正确。 - 检查网络连接是否正常。
503 Service Unavailable 服务器暂时无法处理请求,可能是过载或维护 - 检查服务器负载,确保有足够的资源可用。 - 检查后端服务器的健康状态。 - 考虑增加缓存机制。
504 Gateway Timeout 上游服务器未能在规定时间内响应请求 - 检查上游服务器的性能。 - 增加 proxy_read_timeout 设置。 - 确保网络连接正常。
  1. 请求过滤与限流

Nginx 提供了多种方式来实现请求过滤和流量控制,以保护服务器免受恶意请求和流量攻击的影响。以下是一些常见的方法:

  1. IP 黑名单和白名单

使用 allowdeny 指令可以设置 IP 黑名单和白名单。

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    deny  all;
}

在这个例子中,192.168.1.1 将被拒绝访问,而 192.168.1.0/2410.1.1.0/16 网段的 IP 地址可以访问。最后的 deny all 会拒绝其他所有 IP。 2. 基于 Referer 的防盗链

使用 valid_referers 指令可以防止资源被盗链。

location ~* \.(jpg|jpeg|png|css|js)$ {
    valid_referers none blocked server_names *.example.com example.org;
    if ($invalid_referer) {
        return 403;
    }
}

在这个例子中,只有来自 *.example.comexample.org 或无 Referer 头的请求才能访问图片、CSS 和 JavaScript 文件。 3. 基于 User-Agent 的过滤

使用 if 指令可以根据 $http_user_agent 变量过滤请求。

if ($http_user_agent ~* "bad_bot") {
    return 403;
}

这个例子会拦截 User-Agent 中包含 "bad_bot" 的请求。

  1. 基于 URL 的访问控制

使用 location 指令可以对特定 URL 进行访问控制。

location /admin/ {
    allow 192.168.1.1;
    deny all;
}

在这个例子中,只有 192.168.1.1 可以访问 /admin/ 目录下的内容。 5. 基于连接数和请求频率的限流

使用 limit_connlimit_req 模块可以限制并发连接数和请求频率。

limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=req:10m rate=1r/s;
​
server {
    location /api/ {
        limit_conn addr 10;  # 每个 IP 地址最多 10 个并发连接(每秒1次)
        limit_req zone=req burst=5; # 突发请求最多 5 次。
    }
}

在以上示例中,每个 IP 的并发连接数限制为 10,每秒请求频率限制为 1 次,突发请求最多 5 次。通过以上方法,您可以有效地保护 Nginx 服务器免受恶意请求和流量攻击的影响。根据实际需求选择合适的过滤和限流策略,并结合其他安全措施,可以大大提高服务器的安全性。

  1. Nginx 模块介绍

Nginx 的模块系统是其强大功能的核心部分,允许用户根据需要扩展和定制其功能。Nginx 模块分为核心模块和第三方模块,以下是对这两类模块的介绍。

  • 核心模块:nginx 最基本最核心的服务,如进程管理、权限控制、日志记录;

  • 标准 HTTP 模块:nginx 服务器的标准 HTTP 功能;

  • 可选 HTTP 模块:处理特殊的 HTTP 请求

  • 邮件服务模块:邮件服务

  • 第三方模块:作为扩展,完成特殊功能

    1. 核心模块

核心模块是 Nginx 的基本组成部分,提供了处理 HTTP 请求、管理服务器事件、支持 SSL/TLS 加密等基本功能。以下是一些重要的核心模块:

# 1. ngx_http_core_module

  • 提供 HTTP 服务器的基本功能,包括请求处理、URI 映射和访问控制。

  • 该模块是配置 Nginx HTTP 服务器的基础。

# 2. ngx_http_ssl_module

  • 支持 SSL/TLS 加密,允许安全的客户端与服务器之间的通信。

  • 使得 Nginx 能够配置 SSL 证书和加密套件。

# 3. ngx_http_access_module

  • 控制对服务器的访问,基于客户端 IP 地址、域名或其他请求属性。

  • 提供 allowdeny 指令来指定访问规则。

# 4. ngx_http_proxy_module

  • 实现代理服务器功能,使 Nginx 能作为反向代理,将客户端请求转发到其他服务器。

  • 常用于负载均衡和缓存。

# 5. ngx_http_fastcgi_module

  • 允许 Nginx 与 FastCGI 服务器交互,支持动态脚本和应用程序的执行。

  • 提供定义 FastCGI 服务器地址的指令。

# 6. ngx_http_rewrite_module

  • 提供 URL 重写功能,允许根据定义的规则修改请求 URI 或重定向请求。

  • 常用于 URL 操作和重定向。

    1. 第三方模块

第三方模块是由 Nginx 社区开发的,提供了更多特定功能。这些模块不是 Nginx 源代码的一部分,但可以通过编译或动态加载的方式添加到 Nginx 中。以下是一些常用的第三方模块:

# 1) Nginx RTMP Module

  • 用于实时流媒体传输,支持直播和点播功能。

# 2) Nginx Fancy Index Module

  • 生成文件列表,提供更美观的目录索引页面。

# 3) Nginx Lua Module

  • 允许在 Nginx 中嵌入 Lua 脚本,提供更灵活的请求处理能力。

# 4) Nginx GeoIP Module

  • 根据客户端 IP 地址提供地理位置服务,常用于个性化内容或访问控制。

# 4) nginx_upstream_check_module

  • nginx主动健康检查
  1. 模块的工作原理

Nginx 模块通过共享内存区和回调机制进行交互。共享内存区允许模块在工作进程之间共享数据,而回调机制使得模块能够在处理管道的特定点执行其功能。

  1. 模块的启用与禁用
  • 编译时启用:在编译 Nginx 时,可以通过命令行参数启用特定模块。
./configure --with-http_ssl_module --with-stream

编译时****禁用模块

./configure --without-http_autoindex_module
  • 动态模块:动态模块可以在运行时加载或卸载,无需重启或重新编译 Nginx。
load_module modules/ngx_http_image_filter_module.so;

禁用动态模块:只需从配置文件中删除或注释掉 load_module 指令。

Nginx 的模块系统使得其具有高度的灵活性和可扩展性。通过选择合适的核心模块和第三方模块,用户可以根据具体需求定制 Nginx 的功能,以满足不同的应用场景。这种模块化设计不仅提高了内存使用效率,还增强了 Nginx 的整体性能。

  1. 性能优化

Nginx 的性能优化主要集中在以下几个方面:

    1. 连接数限制
  • worker_connections:每个 worker 进程的最大连接数。默认值为 1024。

  • multi_accept:是否在接受新连接时尽可能多地接受。默认为 off。

  • listen backlog:TCP 连接的 backlog 大小。

      1. 请求处理时间限制
  • client_body_timeout:客户端请求体的读取超时时间。默认为 60s。

  • client_header_timeout:客户端请求头的读取超时时间。默认为 60s。

  • keepalive_timeout:客户端连接的超时时间。默认为 75s。

  • send_timeout:向客户端发送响应的超时时间。默认为 60s。

      1. 缓冲区大小
  • client_body_buffer_size:客户端请求体的缓冲区大小。默认为 8k/16k。

  • client_header_buffer_size:客户端请求头的缓冲区大小。默认为 1k。

  • large_client_header_buffers:读取大客户端请求头的缓冲区数量和大小。默认为 4 8k。

      1. 文件描述符限制
  • worker_rlimit_nofile:每个 worker 进程可以打开的最大文件描述符数量。

      1. 压缩和缓存
  • Gzip 压缩:通过 gzip 指令开启 Gzip 压缩。

  • Proxy 缓存:通过 proxy_cache 指令配置反向代理缓存。

  • 浏览器缓存:通过 expires 指令设置浏览器缓存。

      1. 其他优化
  • worker_processes:设置 worker 进程的数量。通常设置为 CPU 核心数。

  • worker_cpu_affinity:将 worker 进程绑定到特定的 CPU 核心。

  • aio:开启异步 I/O。

  • directio:使用直接 I/O 读取大文件。

    1. 示例配置

以下是一个综合性能优化的 Nginx 配置示例:

worker_processes auto;
worker_cpu_affinity auto;
​
events {
    worker_connections 16384;
    multi_accept on;
}
​
http {
    client_body_timeout 10;
    client_header_timeout 10;
    keepalive_timeout 30;
    send_timeout 10;
​
    client_body_buffer_size 128k;
    client_header_buffer_size 4k;
    large_client_header_buffers 4 8k;
​
    gzip on;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
​
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
​
    server {
        listen 80;
        server_name example.com;
​
        location / {
            root /var/www/html;
            index index.html index.htm;
            expires 30d;
        }
​
        location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
            root /var/www/html;
            expires 30d;
        }
​
        location /api/ {
            proxy_pass http://backend;
            proxy_cache my_cache;
            proxy_cache_valid 200 302 10m;
            proxy_cache_valid 404 1m;
        }
    }
}

合理配置这些参数,可以有效提高 Nginx 的性能,提升网站的响应速度和并发能力。以上是一个通用的优化配置,但也需要根据实际情况进行测试和调优。

  1. Nginx优化置后如何进行效果验证
验证方法 描述 工具示例 步骤
压力测试 通过模拟高并发请求,测试 Nginx 的响应时间和吞吐量 Apache Bench (ab) 1. 使用 ab 命令进行压力测试,设置并发数和请求数。
性能监控 监控 Nginx 的资源使用情况,如 CPU、内存和网络带宽 Nginx Status Module 1. 启用 Nginx 状态监控模块。
响应时间分析 测量请求的平均响应时间和最大响应时间 JMeter 1. 使用 JMeter 创建测试计划。
日志分析 分析 Nginx 的访问日志和错误日志 GoAccess, AWStats 1. 使用日志分析工具读取 Nginx 日志。
缓存效果验证 测试静态资源的缓存命中率 curl 1. 使用 curl 请求静态资源,观察是否从缓存中获取数据。
  1. 监控与调试

Nginx 在处理高并发时可能会遇到以下几种常见故障:

  1. 内存泄漏:如果 Nginx 模块或第三方模块存在内存泄漏问题,长时间运行下来会导致内存占用不断增加,最终耗尽系统内存,引发服务崩溃。

  2. CPU 占用过高:某些复杂的正则表达式、大量的日志记录、SSL 加解密等操作会导致 CPU 占用过高,影响 Nginx 的处理能力。

  3. 文件描述符耗尽:每个客户端连接都会占用一个文件描述符,如果连接数过多或者没有及时关闭连接,可能会导致文件描述符耗尽。

  4. 慢客户端:客户端在发送请求或接收响应时网速很慢,会占用 Nginx 的工作进程,影响并发处理能力。

  5. 后端服务器故障:如果后端应用服务器宕机或响应很慢,会导致大量请求在 Nginx 处堆积,最终耗尽 Nginx 的资源。

  6. DDoS 攻击:海量的恶意请求会占用 Nginx 大量资源,导致正常请求得不到及时响应。

  7. 配置错误:不当的配置,如连接超时时间过短、缓冲区过小等,可能会导致大量请求失败。

  8. 硬件瓶颈:如果 Nginx 所在服务器的 CPU、内存、磁盘 I/O 等资源不足,也会成为高并发处理的瓶颈。

要预防和解决这些故障,需要合理规划 Nginx 的配置、监控 Nginx 的运行状态、优化后端应用、采用集群部署等手段。同时也要注意系统内核参数的优化,如文件描述符限制、TCP 连接参数等。

  1. 安全配置

Nginx 是一个强大的 Web 服务器和反向代理,能够有效地进行安全配置,以防止 DDoS 攻击和其他安全威胁。以下是一些关键的安全配置和措施,以增强 Nginx 的安全性。

  1. 防止 DDoS 攻击

    1. 限制请求速率

使用 limit_req 指令来限制来自单个 IP 地址的请求速率,limit_conn 限制每个IP的连接数,可以有效防止 DDoS 攻击。以下是一个示例配置:

http {
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=1r/s;
​
    server {
        location / {
            limit_req zone=req_limit_per_ip burst=5;
            limit_conn addr 10;  # 每个 IP 地址最多 10 个连接
        }
    }
}

在这个配置中,limit_req_zone 定义了一个区域 req_limit_per_ip,限制每个 IP 地址每秒最多 1 个请求,允许突发 5 个请求;每个 IP 地址最多 10 个连接。

  2. 限制并发连接数

使用 limit_conn 指令限制每个 IP 地址的并发连接数,防止某个 IP 地址打开过多连接:

http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;
​
    server {
        location / {
            limit_conn addr 10;  # 每个 IP 地址最多 10 个连接
        }
    }
}
  3. IP 黑白名单

可以使用 allowdeny 指令来阻止特定的 IP 地址访问:

http {
    server {
        location / {
            deny 192.168.1.1;  # 阻止该 IP 地址
            allow 192.168.1.0/24;  # 允许该网段
            deny all;  # 拒绝其他所有 IP
        }
    }
}
  1. 加强安全性

    1. 启用 HTTPS

启用 HTTPS:使用 SSL/TLS 加密所有传输的数据,确保数据的安全性。

server {
    listen 443 ssl;
    server_name example.com;
​
    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;
​
    location / {
        # 处理请求
    }
}

使用强加密套件:配置强加密套件,确保使用安全的加密算法。

ssl_protocols TLSv1.2 TLSv1.3;  # 只启用安全的协议ssl_ciphers 'HIGH:!aNULL:!MD5';  # 使用强加密套件
  2. 防止常见攻击

  * 隐藏 Nginx 版本信息 

通过配置文件隐藏 Nginx 的版本信息以及 X-Powered-By信息,减少被攻击的风险。

http {
    ...
    server_tokens off;  # 禁用版本信息
    ...
}

如何在Nginx中隐藏版本信息和X-Powered-By头

http {
    server {
        listen 80;
        server_name example.com;


        location / {
            proxy_pass http://backend_server;  # 代理到后端服务器
            proxy_hide_header X-Powered-By;  # 隐藏 X-Powered-By 头
        }
    }
}

如果使用 PHP-FPM 处理 PHP 文件,可以在相应的 location 块中使用

fastcgi_hide_header 指令来隐藏 X-Powered-By 头。

server {
    listen 80;
    server_name example.com;


    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;  # 根据您的 PHP-FPM 配置调整
        fastcgi_hide_header X-Powered-By;  # 隐藏 X-Powered-By 头
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
  * 防止 SQL 注入和 XSS 攻击

通过配置 add_header 指令设置安全头,防止 XSS 攻击。

add_header X-XSS-Protection "1; mode=block";add_header X-Content-Type-Options nosniff;
  * 限制文件上传

对上传文件进行限制,防止恶意文件上传。

client_max_body_size 2M;  # 限制上传文件大小
  3. 禁用不必要的模块

通过禁用不必要的 Nginx 模块,减少攻击面:

./configure --without-http_autoindex_module --without-http_ssi_module
  4. 禁用不必要的 HTTP 方法

限制只允许 GET 和 POST 方法,防止不必要的请求。

if ($request_method !~ ^(GET|POST)$) {    return 444;  # 直接关闭连接}
  5. 定期更新与备份
  • 定期更新 Nginx:确保使用最新版本的 Nginx,以获得最新的安全补丁和功能。

  • 配置备份:定期备份 Nginx 配置文件和重要数据,以防止数据丢失。

  1. 日志监控

  2. 日志监控流量

使用 Nginx 的内置状态监控模块,监控活动连接和请求数,以便及时发现异常流量。

  2. 分析日志

定期检查访问日志和错误日志,识别潜在的攻击模式和异常行为。

tail -f /var/log/nginx/access.log
  • 使用监控工具:结合 Prometheus、Grafana 等工具监控 Nginx 的状态和性能。

    1. 其他安全措施
  • 设置合理的超时时间:配置 client_body_timeoutclient_header_timeout,防止连接被长时间占用。

  • 使用缓存:启用缓存以减少对后端服务器的请求压力。

通过以上配置和措施,您可以有效增强 Nginx 的安全性,降低 DDoS 攻击和其他安全威胁的风险。

  1. nginx 内置预定义变量

按字母顺序,变量名与对应定义:

  • $arg_PARAMETER #GET 请求中变量名 PARAMETER 参数的值

  • $args #这个变量等于 GET 请求中的参数,例如,foo=123&bar=blahblah;这个变量可以被修改

  • $binary_remote_addr #二进制码形式的客户端地址

  • $body_bytes_sent #传送页面的字节数

  • $content_length #请求头中的 Content-length 字段

  • $content_type #请求头中的 Content-Type 字段

  • $cookie_COOKIE #cookie COOKIE 的值

  • $document_root #当前请求在 root 指令中指定的值

  • $document_uri #与 $uri 相同

  • $host #请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的 server 名称(处理请求的 server 的 server_name 指令的值)。值为小写,不包含端口

  • $hostname #机器名使用 gethostname 系统调用的值

  • $http_HEADER #HTTP 请求头中的内容,HEADER 为 HTTP 请求中的内容转为小写,-变为*(破折号变为下划线),例如:$http*user_agent(Uaer-Agent 的值)

  • $sent_http_HEADER #HTTP 响应头中的内容,HEADER 为 HTTP 响应中的内容转为小写,-变为*(破折号变为下划线),例如:$sent*http_cache_control$sent_http_content_type

  • $is_args #如果 $args 设置,值为”?”,否则为””

  • $limit_rate #这个变量可以限制连接速率

  • $nginx_version #当前运行的 nginx 版本号

  • $query_string #与 $args 相同

  • $remote_addr #客户端的 IP 地址

  • $remote_port #客户端的端口

  • $remote_port #已经经过 Auth Basic Module 验证的用户名

  • $request_filename #当前连接请求的文件路径,由 root 或 alias 指令与 URI 请求生成

  • $request_body #这个变量(0.7.58+)包含请求的主要信息。在使用 proxy_pass 或 fastcgi_pass 指令的 location 中比较有意义

  • $request_body_file #客户端请求主体信息的临时文件名

  • $request_completion #如果请求成功,设为”OK”;如果请求未完成或者不是一系列请求中最后一部分则设为空

  • $request_method #这个变量是客户端请求的动作,通常为 GET 或 POST。包括 0.8.20 及之前的版本中,这个变量总为 main request 中的动作,如果当前请求是一个子请求,并不使用这个当前请求的动作

  • $request_uri #这个变量等于包含一些客户端请求参数的原始 URI,它无法修改,请查看 $uri 更改或重写 URI

  • $scheme #所用的协议,例如 http 或者是 https,例如 rewrite ^(.+)$$scheme://example.com$1 redirect

  • $server_addr #服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在 listen 中指定地址并且使用 bind 参数

  • $server_name #服务器名称

  • $server_port #请求到达服务器的端口号

  • $server_protocol #请求使用的协议,通常是 HTTP/1.0、HTTP/1.1 或 HTTP/2

  • $uri #请求中的当前 URI(不带请求参数,参数位于 args ) , 不 同 于 浏 览 器 传 递 的 args),不同于浏览器传递的 args),不同于浏览器传递的 request_uri 的值,它可以通过内部重定向,或者使用 index 指令进行修改。不包括协议和主机名,例如 /foo/bar.html

#