nginx ngx_http_module(5) 指令详解

nginx ngx_http_module(5) 指令详解

相关链接

  • nginx 嵌入式变量解析目录
  • nginx 嵌入式变量全目录
  • nginx 指令模块目录
  • nginx 指令全目录

一、目录

1.1 模块简介

  • ngx_http_js_module:JavaScript支持模块,允许在Nginx配置中使用JavaScript编写脚本。这使得开发者可以更灵活地处理请求和响应逻辑,例如进行复杂的请求重写、响应生成或访问控制等。该模块通常用于需要动态行为但又不想引入额外应用服务器的场景。

  • ngx_http_keyval_module:键值对变量模块,提供了一种机制来存储和检索键值对数据。它可以在不同的请求之间共享状态信息,适用于需要跨请求维护状态的应用场景,如会话管理或用户跟踪。

  • ngx_http_limit_conn_module:连接限制模块,允许根据定义的条件(如IP地址)限制并发连接数。这对于防止资源耗尽攻击(如SYN Flood攻击)非常有用,通过设置合理的连接数上限,保护服务器免受过度负载的影响。

  • ngx_http_limit_req_module:请求速率限制模块,用于限制客户端请求的频率。可以通过设定每秒最大请求数来避免DDoS攻击或其他形式的滥用。此模块支持平滑限制和突发流量处理,确保服务的稳定性。

  • ngx_http_log_module:日志记录模块,负责记录HTTP请求的各种信息到日志文件中。通过自定义日志格式,可以记录诸如请求时间、客户端IP、请求方法、返回状态码等信息。这对于监控、调试和分析网站流量非常重要。

  • ngx_http_map_module:映射模块,可以根据输入变量创建新的变量。它常用于条件判断和变量转换,例如将用户代理字符串映射为浏览器类型,或者基于某些条件设置响应头。这种灵活性有助于实现复杂的行为逻辑。

  • ngx_http_memcached_module:Memcached支持模块,使Nginx可以直接从Memcached缓存中读取内容。这对于加速动态页面加载特别有用,因为它减少了后端应用服务器的负载,并加快了响应速度。此模块适合用作前端缓存层的一部分。

  • ngx_http_mirror_module:镜像请求模块,允许复制原始请求并发送到另一个位置而不影响主请求的处理。这在测试新功能或收集统计信息时非常有用,因为你可以同时向生产环境和测试环境发送相同的请求以进行比较或分析。

  • ngx_http_mp4_module:MP4流媒体模块,支持HTTP上的MP4视频流播放。它能够根据用户的网络状况动态调整视频片段的传输,从而提供流畅的观看体验。此外,还支持拖动进度条直接跳转到视频的任意部分进行播放。

  • ngx_http_perl_module:Perl语言支持模块,允许在Nginx配置中嵌入Perl代码。虽然不如ngx_http_js_module那样常用,但对于熟悉Perl的开发者来说,它可以提供一种快速集成复杂逻辑的方式,而无需外部脚本或应用程序的支持。

1.2 指令目录

1.2.27 ngx_http_js_module
  • js_body_filter
  • js_content
  • js_context_reuse
  • js_engine
  • js_fetch_buffer_size
  • js_fetch_ciphers
  • js_fetch_max_response_buffer_size
  • js_fetch_protocols
  • js_fetch_timeout
  • js_fetch_trusted_certificate
  • js_fetch_verify
  • js_fetch_verify_depth
  • js_header_filter
  • js_import
  • js_include
  • js_path
  • js_periodic
  • js_preload_object
  • js_set
  • js_shared_dict_zone
  • js_var
1.2.28 ngx_http_keyval_module
  • keyval
  • keyval_zone
1.2.29 ngx_http_limit_conn_module
  • limit_conn
  • limit_conn_dry_run
  • limit_conn_log_level
  • limit_conn_status
  • limit_conn_zone
  • limit_zone
1.2.30 ngx_http_limit_req_module
  • limit_req
  • limit_req_dry_run
  • limit_req_log_level
  • limit_req_status
  • limit_req_zone
1.2.31 ngx_http_log_module
  • access_log
  • log_format
  • open_log_file_cache
1.2.32 ngx_http_map_module
  • map
  • map_hash_bucket_size
  • map_hash_max_size
1.2.33 ngx_http_memcached_module
  • memcached_bind
  • memcached_buffer_size
  • memcached_connect_timeout
  • memcached_gzip_flag
  • memcached_next_upstream
  • memcached_next_upstream_timeout
  • memcached_next_upstream_tries
  • memcached_pass
  • memcached_read_timeout
  • memcached_send_timeout
  • memcached_socket_keepalive
1.2.34 ngx_http_mirror_module
  • mirror
  • mirror_request_body
1.2.35 ngx_http_mp4_module
  • mp4
  • mp4_buffer_size
  • mp4_max_buffer_size
  • mp4_limit_rate
  • mp4_limit_rate_after
  • mp4_start_key_frame
1.2.36 ngx_http_perl_module
  • perl
  • perl_modules
  • perl_require
  • perl_set

二、解释

2.27 ngx_http_js_module

ngx_http_js_module 是 Nginx 的一个模块,它允许在 Nginx 配置中嵌入和执行 JavaScript 代码。这个模块扩展了 Nginx 的功能,使得你可以在请求处理的不同阶段(如重写、访问控制、日志记录等)中使用 JavaScript 进行更复杂的逻辑处理。

主要功能

  • 动态处理:在 Nginx 请求处理的各个阶段执行 JavaScript 代码,实现更复杂的逻辑。
  • 灵活配置:通过 JavaScript 编写自定义的逻辑,而不仅仅依赖于 Nginx 的配置指令。
  • 增强功能:可以用于日志处理、请求重写、响应修改等多种场景。

常用指令

以下是与 ngx_http_js_module 模块相关的常用配置指令及其简要说明:

  • js_include:指定包含 JavaScript 代码的文件路径。

  • js_set:设置一个 Nginx 变量,并将其值由 JavaScript 函数计算得出。

  • js_content:将整个请求的内容处理交给 JavaScript 函数来生成。

  • js_access:在访问阶段执行 JavaScript 代码,决定是否允许访问。

  • js_header_filterjs_body_filter:分别在响应头和响应体过滤阶段执行 JavaScript 代码,允许修改响应内容。

使用示例

以下是一些具体的配置示例,展示如何利用 ngx_http_js_module 来增强 Nginx 的功能。

基本配置

首先,确保你的 Nginx 已经编译并启用了 ngx_http_js_module。你可以通过以下命令检查是否已启用该模块:

nginx -V 2>&1 | grep -- '--with-http_js_module'

如果输出中包含 --with-http_js_module,则表示已启用该模块。

设置变量

假设你想根据客户端的 IP 地址设置一个自定义变量,可以通过 JavaScript 实现:

  1. 创建一个 JavaScript 文件 example.js,内容如下:

    // example.js
    function getCustomValue(r) {
        var ip = r.remoteAddress;
        if (ip.startsWith("192.168")) {
            return "internal";
        } else {
            return "external";
        }
    }
    
    export default {getCustomValue};
    
  2. 在 Nginx 配置中引用该 JavaScript 文件,并设置一个变量:

    http {
        js_include /path/to/example.js;
    
        server {
            listen 80;
            server_name example.com;
    
            js_set $custom_value getCustomValue;
    
            location / {
                add_header X-Custom-Value $custom_value;
                proxy_pass http://backend;
            }
        }
    }
    

在这个例子中:

  • js_include /path/to/example.js; 引入了包含 JavaScript 代码的文件。
  • js_set $custom_value getCustomValue; 设置了一个名为 $custom_value 的 Nginx 变量,并将其值由 JavaScript 函数 getCustomValue 计算得出。
  • add_header X-Custom-Value $custom_value; 将计算出的值添加到响应头中。

动态生成响应内容

你可以使用 js_content 指令让 JavaScript 函数生成整个响应内容:

  1. 创建一个 JavaScript 文件 dynamic_response.js,内容如下:

    // dynamic_response.js
    function generateResponse(r) {
        r.return(200, "Hello from JavaScript in Nginx!");
    }
    
    export default {generateResponse};
    
  2. 在 Nginx 配置中引用该 JavaScript 文件,并设置 js_content

    http {
        js_include /path/to/dynamic_response.js;
    
        server {
            listen 80;
            server_name example.com;
    
            location /js-response {
                js_content generateResponse;
            }
        }
    }
    

在这个例子中:

  • 当用户访问 /js-response 路径时,Nginx 会调用 generateResponse 函数生成响应内容,并返回给客户端。

访问控制

你可以在访问阶段使用 JavaScript 代码进行访问控制:

  1. 创建一个 JavaScript 文件 access_control.js,内容如下:

    // access_control.js
    function checkAccess(r) {
        var ip = r.remoteAddress;
        if (ip.startsWith("192.168")) {
            return true;
        } else {
            return false;
        }
    }
    
    export default {checkAccess};
    
  2. 在 Nginx 配置中引用该 JavaScript 文件,并设置访问控制:

    http {
        js_include /path/to/access_control.js;
    
        server {
            listen 80;
            server_name example.com;
    
            js_access checkAccess;
    
            location / {
                proxy_pass http://backend;
            }
        }
    }
    

在这个例子中:

  • js_access checkAccess; 在访问阶段调用 checkAccess 函数,决定是否允许访问。
  • 如果客户端 IP 地址以 192.168 开头,则允许访问;否则拒绝访问。

修改响应头和体

你可以使用 js_header_filterjs_body_filter 在响应头和响应体过滤阶段执行 JavaScript 代码,修改响应内容:

  1. 创建一个 JavaScript 文件 modify_response.js,内容如下:

    // modify_response.js
    function modifyHeaders(r) {
        r.headersOut['X-Custom-Header'] = 'Modified by JS';
    }
    
    function modifyBody(r) {
        var body = r.responseBody.toString();
        body += "\n";
        r.sendBuffer(body);
    }
    
    export default {modifyHeaders, modifyBody};
    
  2. 在 Nginx 配置中引用该 JavaScript 文件,并设置响应过滤:

    http {
        js_include /path/to/modify_response.js;
    
        server {
            listen 80;
            server_name example.com;
    
            location / {
                proxy_pass http://backend;
    
                js_header_filter modifyHeaders;
                js_body_filter modifyBody;
            }
        }
    }
    

在这个例子中:

  • js_header_filter modifyHeaders; 在响应头过滤阶段调用 modifyHeaders 函数,修改响应头。
  • js_body_filter modifyBody; 在响应体过滤阶段调用 modifyBody 函数,修改响应体内容。

注意事项

  • 性能考虑

    • JavaScript 代码的执行会影响性能,尤其是在高并发场景下。尽量保持 JavaScript 代码简洁高效。
    • 如果有大量复杂的业务逻辑,考虑将这些逻辑移到后端服务中处理。
  • 安全性

    • 确保 JavaScript 代码的安全性,避免引入潜在的安全漏洞。
    • 对输入数据进行适当的验证和清理,防止注入攻击。
  • 调试

    • 使用日志记录和调试工具来帮助排查问题。可以在 JavaScript 代码中使用 r.warn()r.error() 输出日志信息。
2.27.1 指令列表
js_body_filter

js_body_filter 指令用于在响应体过滤阶段调用 JavaScript 函数或模块中的函数。这个指令允许你对响应体进行动态处理,如修改内容、添加水印等。

Syntax:	js_body_filter function | module.function [buffer_type=string | buffer];
Default: —
Context: location, if in location, limit_except
This directive appeared in version 0.5.2.
  • function:要调用的 JavaScript 函数。
  • module.function:要调用的模块中的 JavaScript 函数。
  • [buffer_type=string | buffer]:可选参数,指定缓冲区类型,默认为 string。如果设置为 buffer,则传递给 JavaScript 函数的是二进制数据。

案例

基本用法

最简单的 js_body_filter 用法是指定一个 JavaScript 函数来处理响应体:

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

        location /modify_response/ {
            # 启用 JavaScript 过滤器
            js_body_filter modifyResponse;

            # 其他配置
        }

        js_include /path/to/your_script.js;
    }
}

在这个例子中:

  • 当用户访问 /modify_response/ 路径时,Nginx 将调用 modifyResponse 函数来处理响应体内容。

使用模块中的函数和指定缓冲区类型

你可以使用模块中的函数,并指定缓冲区类型为 buffer

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

        location /binary_processing/ {
            # 启用 JavaScript 过滤器并指定缓冲区类型为 buffer
            js_body_filter myModule.processBinary buffer;

            # 其他配置
        }

        js_include /path/to/your_module.js;
    }
}

在这个例子中:

  • 访问 /binary_processing/ 路径时,Nginx 将调用 myModule.processBinary 函数来处理二进制响应体。

注意事项

  • 性能影响:JavaScript 处理可能会影响性能,特别是在高并发场景下。确保 JavaScript 函数高效且简洁。
  • 错误处理:确保在 JavaScript 函数中正确处理错误,以避免意外行为或崩溃。
  • 安全性考虑:确保 JavaScript 函数不会暴露敏感信息或引入安全漏洞。
js_content

js_content 指令用于直接通过 JavaScript 函数生成 HTTP 响应内容。这个指令非常适合用于生成动态内容或执行复杂的逻辑。

Syntax:	js_content function | module.function;
Default: —
Context: location, if in location, limit_except
  • function:要调用的 JavaScript 函数。
  • module.function:要调用的模块中的 JavaScript 函数。

案例

基本用法

最简单的 js_content 用法是指定一个 JavaScript 函数来生成响应内容:

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

        location /dynamic_content/ {
            # 使用 JavaScript 函数生成响应内容
            js_content generateContent;

            # 其他配置
        }

        js_include /path/to/your_script.js;
    }
}

在这个例子中:

  • 当用户访问 /dynamic_content/ 路径时,Nginx 将调用 generateContent 函数来生成并返回响应内容。

使用模块中的函数

你可以使用模块中的函数来生成响应内容:

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

        location /complex_logic/ {
            # 使用模块中的 JavaScript 函数生成响应内容
            js_content myModule.generateComplexContent;

            # 其他配置
        }

        js_include /path/to/your_module.js;
    }
}

在这个例子中:

  • 访问 /complex_logic/ 路径时,Nginx 将调用 myModule.generateComplexContent 函数来生成并返回响应内容。

注意事项

  • 性能优化:确保 JavaScript 函数高效运行,特别是在高并发场景下。可以考虑缓存计算结果或使用异步操作。
  • 错误处理:确保在 JavaScript 函数中正确处理错误,以避免意外行为或崩溃。
  • 安全性考虑:确保 JavaScript 函数不会暴露敏感信息或引入安全漏洞。
js_context_reuse

js_context_reuse 指令用于设置 JavaScript 上下文重用的数量。通过重用上下文,可以减少 JavaScript 引擎初始化的时间,从而提高性能。

Syntax:	js_context_reuse number;
Default: js_context_reuse 128;
Context: http, server, location
This directive appeared in version 0.8.6.
  • number:要重用的 JavaScript 上下文数量。默认值是 128。

案例

基本用法

最简单的 js_context_reuse 用法是指定上下文重用的数量:

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

        location /optimized/ {
            # 设置 JavaScript 上下文重用数量为 256
            js_context_reuse 256;

            # 其他配置
        }
    }
}

在这个例子中:

  • Nginx 将设置 JavaScript 上下文重用数量为 256,以优化性能。

自定义上下文重用数量

你可以根据需要调整上下文重用的数量:

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

        location /high_performance/ {
            # 设置 JavaScript 上下文重用数量为 512(适用于高并发场景)
            js_context_reuse 512;

            # 其他配置
        }

        location /low_performance/ {
            # 设置 JavaScript 上下文重用数量为 64(适用于低并发场景)
            js_context_reuse 64;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /high_performance/ 路径时,Nginx 将设置 JavaScript 上下文重用数量为 512,以适应高并发场景。
  • 访问 /low_performance/ 路径时,Nginx 将设置 JavaScript 上下文重用数量为 64,以适应低并发场景。

注意事项

  • 性能优化:增加上下文重用数量可以减少初始化时间,但在内存有限的情况下可能会导致内存不足。需根据服务器资源进行合理配置。
  • 内存管理:确保有足够的内存来支持设定的上下文重用数量,以避免内存溢出或其他问题。
js_engine

js_engine 指令用于选择使用的 JavaScript 引擎。Nginx 支持多种 JavaScript 引擎,如 njs 和 qjs。

Syntax:	js_engine njs | qjs;
Default: js_engine njs;
Context: http, server, location
This directive appeared in version 0.8.6.
  • njs:使用 Nginx 的内置 JavaScript 引擎 njs。
  • qjs:使用 QuickJS 引擎。

案例

基本用法

最简单的 js_engine 用法是指定使用的 JavaScript 引擎:

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

        location /njs_engine/ {
            # 使用 njs 引擎
            js_engine njs;

            # 其他配置
        }
    }
}

在这个例子中:

  • 当用户访问 /njs_engine/ 路径时,Nginx 将使用 njs 引擎来处理 JavaScript 代码。

使用 qjs 引擎

你可以选择使用 QuickJS 引擎:

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

        location /qjs_engine/ {
            # 使用 qjs 引擎
            js_engine qjs;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /qjs_engine/ 路径时,Nginx 将使用 QuickJS 引擎来处理 JavaScript 代码。

注意事项

  • 兼容性检查:不同的 JavaScript 引擎可能有不同的特性和限制。确保所选引擎支持你的 JavaScript 代码。
  • 性能对比:不同引擎的性能表现可能有所不同,建议进行实际测试以找到最适合你应用的引擎。
  • 安装与配置:确保正确安装并配置所选的 JavaScript 引擎。某些引擎可能需要额外的依赖或配置步骤。
js_fetch_buffer_size

js_fetch_buffer_size 用于设置在使用 Nginx 的 JavaScript(njs)模块进行 HTTP 请求时,请求体缓冲区的大小。这个指令影响到 Nginx 在处理请求体数据时的内存分配。

Syntax:	js_fetch_buffer_size size;
Default: js_fetch_buffer_size 16k;
Context: http, server, location
This directive appeared in version 0.7.4.
  • size:指定缓冲区大小,默认是 16KB (16k)。

案例

基本用法

最简单的 js_fetch_buffer_size 用法是指定请求体缓冲区的大小:

server {
    listen 80;
    server_name example.com;

    location /api/ {
        js_fetch_buffer_size 32k;  # 设置为 32KB
        js_content some_js_function;
    }
}

在这个例子中,设置了 js_fetch_buffer_size 32k,这意味着 Nginx 将为每个请求分配 32KB 的缓冲区来处理请求体数据。

调整缓冲区大小

根据实际需求调整缓冲区大小:

server {
    listen 80;
    server_name example.com;

    location /small_requests/ {
        js_fetch_buffer_size 8k;  # 设置较小的缓冲区,适用于小请求
        js_content smallRequestHandler;
    }

    location /large_requests/ {
        js_fetch_buffer_size 64k;  # 设置较大的缓冲区,适用于大请求
        js_content largeRequestHandler;
    }
}

在这个例子中:

  • 对于 /small_requests/ 路径下的请求,设置了较小的缓冲区(8KB),适用于处理较小的请求。
  • 对于 /large_requests/ 路径下的请求,设置了较大的缓冲区(64KB),适用于处理较大的请求。

注意事项

  • 内存占用:增加缓冲区大小会增加内存占用,确保服务器有足够的内存来支持这些设置。
  • 性能优化:适当的缓冲区设置可以提高请求处理的效率,但过大的缓冲区可能会导致不必要的内存浪费。

js_fetch_ciphers

js_fetch_ciphers 指令用于配置在使用 njs 进行 HTTPS 请求时,允许使用的加密套件列表。这有助于增强安全性,通过限制仅使用安全的加密方法。

Syntax:	js_fetch_ciphers ciphers;
Default: js_fetch_ciphers HIGH:!aNULL:!MD5;
Context: http, server, location
This directive appeared in version 0.7.0.
  • ciphers:指定要使用的加密套件列表,格式遵循 OpenSSL 标准。

案例

基本用法

最简单的 js_fetch_ciphers 用法是指定加密套件列表:

server {
    listen 80;
    server_name example.com;

    location /secure_api/ {
        js_fetch_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';  # 自定义加密套件
        js_content secure_js_function;
    }
}

在这个例子中,指定了两个高强度的加密套件,以增强通信的安全性。

调整加密套件列表

根据实际需求调整加密套件列表:

server {
    listen 80;
    server_name example.com;

    location /legacy_secure_api/ {
        js_fetch_ciphers 'AES256-SHA:AES128-SHA';  # 使用旧版加密套件,适用于兼容性要求高的场景
        js_content legacySecureFunction;
    }

    location /modern_secure_api/ {
        js_fetch_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';  # 使用现代加密套件,适用于高安全要求的场景
        js_content modernSecureFunction;
    }
}

在这个例子中:

  • 对于 /legacy_secure_api/ 路径下的请求,使用了旧版加密套件,适用于需要与旧客户端兼容的场景。
  • 对于 /modern_secure_api/ 路径下的请求,使用了现代加密套件,适用于对安全性要求较高的场景。

注意事项

  • 安全性考虑:选择合适的加密套件列表非常重要,建议定期更新并参考最新的安全建议。
  • 兼容性:确保所选的加密套件列表能够与目标客户端兼容。
js_fetch_max_response_buffer_size

js_fetch_max_response_buffer_size 用于设置在使用 njs 进行 HTTP 请求时,响应体的最大缓冲区大小。这对于控制Nginx 处理大响应体的能力非常重要。

Syntax:	js_fetch_max_response_buffer_size size;
Default: js_fetch_max_response_buffer_size 1m;
Context: http, server, location
This directive appeared in version 0.7.4.
  • size:指定最大缓冲区大小,默认是 1MB (1m)。

案例

基本用法

最简单的 js_fetch_max_response_buffer_size 用法是指定响应体的最大缓冲区大小:

server {
    listen 80;
    server_name example.com;

    location /large_data/ {
        js_fetch_max_response_buffer_size 2m;  # 设置为 2MB
        js_content fetch_large_data;
    }
}

在这个例子中,设置了 js_fetch_max_response_buffer_size 2m,这意味着 Nginx 将为每个响应分配最多 2MB 的缓冲区来处理响应体数据。

调整最大缓冲区大小

根据实际需求调整最大缓冲区大小:

server {
    listen 80;
    server_name example.com;

    location /small_responses/ {
        js_fetch_max_response_buffer_size 512k;  # 设置较小的缓冲区,适用于小响应
        js_content smallResponseHandler;
    }

    location /huge_responses/ {
        js_fetch_max_response_buffer_size 4m;  # 设置较大的缓冲区,适用于大响应
        js_content hugeResponseHandler;
    }
}

在这个例子中:

  • 对于 /small_responses/ 路径下的请求,设置了较小的最大缓冲区(512KB),适用于处理较小的响应。
  • 对于 /huge_responses/ 路径下的请求,设置了较大的最大缓冲区(4MB),适用于处理较大的响应。

注意事项

  • 内存占用:增加最大缓冲区大小会增加内存占用,确保服务器有足够的内存来支持这些设置。
  • 性能优化:适当的缓冲区设置可以提高响应处理的效率,但过大的缓冲区可能会导致不必要的内存浪费。
js_fetch_protocols

js_fetch_protocols 用于配置在使用 njs 进行 HTTPS 请求时支持的 TLS 协议版本。选择合适的协议版本对于确保连接的安全性和兼容性至关重要。

Syntax:	js_fetch_protocols [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];
Default: js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2;
Context: http, server, location
This directive appeared in version 0.7.0.
  • 可选参数包括 TLSv1, TLSv1.1, TLSv1.2, 和 TLSv1.3,默认情况下启用前三个协议版本。

案例

基本用法

最简单的 js_fetch_protocols 用法是指定支持的 TLS 协议版本:

server {
    listen 80;
    server_name example.com;

    location /modern_secure_api/ {
        js_fetch_protocols TLSv1.2 TLSv1.3;  # 仅支持现代 TLS 版本
        js_content modernSecureFunction;
    }
}

在这个例子中,设置了 js_fetch_protocols TLSv1.2 TLSv1.3,这意味着 Nginx 仅支持 TLS 1.2 和 TLS 1.3 协议版本。

调整支持的 TLS 协议版本

根据实际需求调整支持的 TLS 协议版本:

server {
    listen 80;
    server_name example.com;

    location /modern_secure_api/ {
        js_fetch_protocols TLSv1.2 TLSv1.3;  # 仅支持现代 TLS 版本,适用于高安全要求的场景
        js_content modernSecureFunction;
    }

    location /legacy_secure_api/ {
        js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2;  # 支持旧版和新版 TLS,适用于兼容性要求高的场景
        js_content legacySecureFunction;
    }
}

在这个例子中:

  • 对于 /modern_secure_api/ 路径下的请求,仅支持 TLS 1.2 和 TLS 1.3,提供更高的安全性。
  • 对于 /legacy_secure_api/ 路径下的请求,支持所有版本的 TLS(从 TLS 1.0 到 1.2),以确保与旧客户端的兼容性。

注意事项

  • 安全性考虑:选择合适的 TLS 协议版本非常重要,建议优先支持较新的协议版本以增强安全性。
  • 兼容性:确保所选的 TLS 协议版本能够与目标客户端兼容。
js_fetch_timeout

js_fetch_timeout 指令用于设置通过 js_fetch 方法进行HTTP请求时的超时时间。这个指令帮助控制请求的响应时间,确保不会因为长时间等待而阻塞服务器资源。

Syntax:	js_fetch_timeout time;
Default:	js_fetch_timeout 60s;
Context:	http, server, location
This directive appeared in version 0.7.4.
  • time:指定超时时间,单位可以是秒(s)、毫秒(ms)等,默认值为 60s

案例

基本用法

最简单的 js_fetch_timeout 用法是指定一个具体的超时时间:

http {
    js_fetch_timeout 30s;

    server {
        listen 80;
        server_name example.com;

        location /fetch_data/ {
            js_content fetch_handler;
        }
    }

    js_import /path/to/fetch_module.js;
}

// fetch_module.js
function fetch_handler(r) {
    r.fetch({
        url: 'https://api.example.com/data',
        method: 'GET'
    }).then(reply => {
        r.return(200, reply.response);
    }).catch(error => {
        r.return(500, error.message);
    });
}

在这个例子中:

  • 设置了 js_fetch_timeout 30s,这意味着Nginx将等待最多30秒来获取响应。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的超时时间:

server {
    listen 80;
    server_name example.com;

    location /fast_endpoint/ {
        # 设置较短的超时时间,适合快速响应的服务
        js_fetch_timeout 10s;

        js_content fast_fetch_handler;
    }

    location /slow_endpoint/ {
        # 设置较长的超时时间,适合需要更多处理时间的服务
        js_fetch_timeout 90s;

        js_content slow_fetch_handler;
    }
}

在这个例子中:

  • 对于 /fast_endpoint/ 路径,设置了 js_fetch_timeout 10s,适合快速响应的服务。
  • 对于 /slow_endpoint/ 路径,设置了 js_fetch_timeout 90s,适合需要更多处理时间的服务。

注意事项

  • 性能影响:较短的超时时间可以减少服务器资源的占用,但可能导致更多的请求失败。较长的超时时间则相反。根据实际应用场景选择合适的超时时间,以平衡响应时间和资源使用。
  • 适用场景:适用于需要通过JavaScript代码发起HTTP请求的应用场景。例如,在API代理、数据聚合等环境中使用。
  • 调试和监控:如果你遇到超时问题,可以检查以下几点:
    • 确保超时时间设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
js_fetch_trusted_certificate

js_fetch_trusted_certificate 指令用于指定受信任的SSL证书文件。这个指令帮助确保通过 js_fetch 发起的HTTPS请求的安全性。

Syntax:	js_fetch_trusted_certificate file;
Default:	—
Context:	http, server, location
This directive appeared in version 0.7.0.
  • file:指定包含受信任证书的文件路径。

案例

基本用法

最简单的 js_fetch_trusted_certificate 用法是指定一个具体的证书文件:

http {
    js_fetch_trusted_certificate /etc/nginx/certs/ca.crt;

    server {
        listen 80;
        server_name example.com;

        location /secure_data/ {
            js_content secure_fetch_handler;
        }
    }

    js_import /path/to/secure_module.js;
}

// secure_module.js
function secure_fetch_handler(r) {
    r.fetch({
        url: 'https://secure.api.example.com/data',
        method: 'GET'
    }).then(reply => {
        r.return(200, reply.response);
    }).catch(error => {
        r.return(500, error.message);
    });
}

在这个例子中:

  • 设置了 js_fetch_trusted_certificate /etc/nginx/certs/ca.crt,这意味着Nginx将使用该文件中的证书来验证HTTPS连接的安全性。

注意事项

  • 安全性:确保提供的证书文件是可信的,并且定期更新以防止安全漏洞。
  • 适用场景:适用于需要通过HTTPS进行安全通信的应用场景。例如,在涉及敏感数据传输、跨网络通信等环境中使用。
  • 调试和监控:如果你遇到证书验证问题,可以检查以下几点:
    • 确保证书文件路径正确,并且文件内容有效。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
js_fetch_verify

js_fetch_verify 指令用于控制是否启用对 js_fetch 请求的SSL证书验证。这个指令帮助确保通过 js_fetch 发起的HTTPS请求的安全性。

Syntax:	js_fetch_verify on | off;
Default:	js_fetch_verify on;
Context:	http, server, location
This directive appeared in version 0.7.4.
  • on:启用SSL证书验证(默认值)。
  • off:禁用SSL证书验证。

案例

基本用法

最简单的 js_fetch_verify 用法是指定是否启用SSL证书验证:

http {
    js_fetch_verify on;

    server {
        listen 80;
        server_name example.com;

        location /secure_data/ {
            js_content secure_fetch_handler;
        }
    }

    js_import /path/to/secure_module.js;
}

// secure_module.js
function secure_fetch_handler(r) {
    r.fetch({
        url: 'https://secure.api.example.com/data',
        method: 'GET'
    }).then(reply => {
        r.return(200, reply.response);
    }).catch(error => {
        r.return(500, error.message);
    });
}

在这个例子中:

  • 设置了 js_fetch_verify on,这意味着Nginx将启用SSL证书验证。

动态设置不同配置

你可以根据不同的路径或条件动态设置是否启用SSL证书验证:

server {
    listen 80;
    server_name example.com;

    location /test_env/ {
        # 禁用 SSL 证书验证,适合测试环境
        js_fetch_verify off;

        js_content test_fetch_handler;
    }

    location /prod_env/ {
        # 启用 SSL 证书验证,适合生产环境
        js_fetch_verify on;

        js_content prod_fetch_handler;
    }
}

在这个例子中:

  • 对于 /test_env/ 路径,设置了 js_fetch_verify off,适合测试环境。
  • 对于 /prod_env/ 路径,设置了 js_fetch_verify on,适合生产环境。

注意事项

  • 安全性:启用SSL证书验证可以提高安全性,但在某些测试环境下可能需要禁用它。确保根据实际需求选择合适的设置。
  • 适用场景:适用于需要通过HTTPS进行安全通信的应用场景。例如,在涉及敏感数据传输、跨网络通信等环境中使用。
  • 调试和监控:如果你遇到SSL证书验证问题,可以检查以下几点:
    • 确保证书验证设置正确,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
js_fetch_verify_depth

js_fetch_verify_depth 指令用于设置SSL证书链验证的最大深度。这个指令帮助控制Nginx在验证 js_fetch 请求的SSL证书时允许的最大证书链长度。

Syntax:	js_fetch_verify_depth number;
Default:	js_fetch_verify_depth 100;
Context:	http, server, location
This directive appeared in version 0.7.0.
  • number:指定证书链验证的最大深度,默认值为 100

案例

基本用法

最简单的 js_fetch_verify_depth 用法是指定一个具体的证书链验证深度:

http {
    js_fetch_verify_depth 5;

    server {
        listen 80;
        server_name example.com;

        location /secure_data/ {
            js_content secure_fetch_handler;
        }
    }

    js_import /path/to/secure_module.js;
}

// secure_module.js
function secure_fetch_handler(r) {
    r.fetch({
        url: 'https://secure.api.example.com/data',
        method: 'GET'
    }).then(reply => {
        r.return(200, reply.response);
    }).catch(error => {
        r.return(500, error.message);
    });
}

在这个例子中:

  • 设置了 js_fetch_verify_depth 5,这意味着Nginx将在验证SSL证书时允许最多五级证书链。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的证书链验证深度:

server {
    listen 80;
    server_name example.com;

    location /short_chain/ {
        # 设置较小的证书链验证深度,适合简单证书链
        js_fetch_verify_depth 2;

        js_content short_chain_fetch_handler;
    }

    location /long_chain/ {
        # 设置较大的证书链验证深度,适合复杂证书链
        js_fetch_verify_depth 10;

        js_content long_chain_fetch_handler;
    }
}

在这个例子中:

  • 对于 /short_chain/ 路径,设置了 js_fetch_verify_depth 2,适合简单证书链。
  • 对于 /long_chain/ 路径,设置了 js_fetch_verify_depth 10,适合复杂证书链。

注意事项

  • 性能影响:增加证书链验证深度可能会增加验证时间,特别是在证书链较长的情况下。根据实际应用场景选择合适的验证深度,避免不必要的性能开销。
  • 适用场景:适用于需要对SSL证书链进行细粒度控制的应用场景。例如,在涉及多级证书链验证、跨组织信任链等环境中使用。
  • 调试和监控:如果你遇到证书链验证问题,可以检查以下几点:
    • 确保证书链验证深度设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
js_header_filter

js_header_filter 指令用于指定一个 JavaScript 函数或模块中的函数,该函数将在响应头生成之前被调用,允许你对响应头进行动态修改。

Syntax:	js_header_filter function | module.function;
Default:	—
Context:	location, if in location, limit_except
This directive appeared in version 0.5.1.
  • function:直接指定一个全局 JavaScript 函数。
  • module.function:指定一个模块中的 JavaScript 函数。

案例

基本用法

最简单的 js_header_filter 用法是指定一个全局 JavaScript 函数:

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

        location /api/ {
            # 使用全局 JavaScript 函数来修改响应头
            js_header_filter modifyHeaders;

            js_include modify_headers.js;
        }
    }
}

在这个例子中:

  • modifyHeaders 是一个定义在 modify_headers.js 文件中的全局函数,它会在响应头生成之前被调用以修改响应头。

使用模块中的函数

你可以使用模块中的函数来处理响应头:

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

        location /api/ {
            # 使用模块中的 JavaScript 函数来修改响应头
            js_header_filter myModule.modifyHeaders;

            js_import myModule from 'my_module.js';
        }
    }
}

在这个例子中:

  • myModule.modifyHeaders 是一个定义在 my_module.js 文件中的模块函数,它会在响应头生成之前被调用以修改响应头。

注意事项

  • 函数定义:确保在 js_includejs_import 中正确导入了所需的 JavaScript 文件,并且函数定义正确。
  • 性能影响:频繁地修改响应头可能会增加服务器的负载,尤其是在高并发场景下。根据实际需求合理使用此功能。
  • 调试和监控:如果你遇到响应头处理问题,可以检查以下几点:
    • 确保 JavaScript 函数逻辑正确,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
js_import

js_import 指令用于导入 JavaScript 模块或导出特定名称的模块,以便在 Nginx 配置中使用。

Syntax:	js_import module.js | export_name from module.js;
Default:	—
Context:	http, server, location
This directive appeared in version 0.4.0.
  • module.js:直接导入一个 JavaScript 模块。
  • export_name from module.js:从模块中导入特定名称的导出对象。

案例

导入整个模块

最简单的 js_import 用法是导入整个模块:

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

        location /api/ {
            # 导入整个 JavaScript 模块
            js_import myModule.js;

            # 使用模块中的函数
            js_header_filter myModule.modifyHeaders;
        }
    }
}

在这个例子中:

  • myModule.js 是一个包含所需函数的 JavaScript 模块,它将被导入并在 js_header_filter 中使用。

导入特定名称的导出对象

你可以从模块中导入特定名称的导出对象:

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

        location /api/ {
            # 从模块中导入特定名称的导出对象
            js_import myExportName from 'my_module.js';

            # 使用导出对象中的函数
            js_header_filter myExportName.modifyHeaders;
        }
    }
}

在这个例子中:

  • myExportName 是从 my_module.js 中导入的一个特定名称的导出对象,它将被导入并在 js_header_filter 中使用。

注意事项

  • 模块路径:确保模块路径正确,并且模块文件可访问。
  • 导出对象:确保模块中有正确的导出对象,并且它们可以在配置中正确引用。
  • 调试和监控:如果你遇到模块导入问题,可以检查以下几点:
    • 确保模块文件存在并且路径正确。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
js_include

js_include 指令用于包含一个 JavaScript 文件,允许你在 Nginx 配置中使用该文件中的代码。

Syntax:	js_include file;
Default:	—
Context:	http
  • file:指定要包含的 JavaScript 文件。

案例

包含 JavaScript 文件

最简单的 js_include 用法是指定要包含的 JavaScript 文件:

http {
    # 包含一个 JavaScript 文件
    js_include global_functions.js;

    server {
        listen 80;
        server_name example.com;

        location /api/ {
            # 使用包含文件中的函数
            js_header_filter modifyHeaders;
        }
    }
}

在这个例子中:

  • global_functions.js 是一个包含 modifyHeaders 函数的 JavaScript 文件,它将被包含并在 js_header_filter 中使用。

注意事项

  • 文件路径:确保包含文件的路径正确,并且文件可访问。
  • 函数定义:确保包含文件中有正确的函数定义,并且它们可以在配置中正确引用。
  • 调试和监控:如果你遇到包含文件问题,可以检查以下几点:
    • 确保包含文件存在并且路径正确。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
js_path

js_path 指令用于设置 JavaScript 模块的搜索路径,允许你在 Nginx 配置中更灵活地管理模块。

Syntax:	js_path path;
Default:	—
Context:	http, server, location
This directive appeared in version 0.3.0.
  • path:指定 JavaScript 模块的搜索路径。

案例

设置 JavaScript 模块的搜索路径

最简单的 js_path 用法是指定一个或多个 JavaScript 模块的搜索路径:

http {
    # 设置 JavaScript 模块的搜索路径
    js_path /var/www/js_modules;

    server {
        listen 80;
        server_name example.com;

        location /api/ {
            # 使用模块中的函数
            js_import myModule from 'my_module.js';

            js_header_filter myModule.modifyHeaders;
        }
    }
}

在这个例子中:

  • /var/www/js_modules 是一个包含 JavaScript 模块的目录,Nginx 将在此目录中查找并加载 my_module.js 文件。

注意事项

  • 路径设置:确保路径设置正确,并且模块文件存在于这些路径中。
  • 模块查找顺序:如果设置了多个路径,Nginx 会按顺序查找这些路径中的模块文件。
  • 调试和监控:如果你遇到模块查找问题,可以检查以下几点:
    • 确保模块文件存在于指定的路径中。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
js_periodic

js_periodic 指令允许您在Nginx配置中周期性地执行JavaScript函数或模块中的函数。这对于需要定时更新某些状态或数据的场景非常有用,例如定期清理缓存、更新统计数据等。

Syntax:	js_periodic function | module.function [interval=time] [jitter=number] [worker_affinity=mask];
Default:	—
Context:	location
This directive appeared in version 0.8.1.
  • functionmodule.function:指定要周期性执行的JavaScript函数或模块中的函数。
  • interval=time(可选):指定执行间隔,默认单位是秒(s),也可以使用ms(毫秒)、m(分钟)等。
  • jitter=number(可选):添加随机延迟,防止多个工作进程同时执行该函数。jitter 的值表示最大随机延迟的时间范围。
  • worker_affinity=mask(可选):指定哪些工作进程将执行此函数。mask 是一个二进制掩码,每一位对应一个工作进程。

案例

基本用法

假设我们有一个名为 updateStats 的JavaScript函数,希望每60秒执行一次:

location /stats {
    js_periodic updateStats interval=60s;
}

在这个例子中,updateStats 函数将每隔60秒执行一次。

使用模块中的函数和额外参数

如果函数位于某个模块中,并且我们希望添加一些随机延迟以分散负载:

location /metrics {
    js_periodic myModule.collectMetrics interval=30s jitter=5s worker_affinity=0x3;
}

在这个例子中:

  • myModule.collectMetrics 函数每30秒执行一次。
  • jitter=5s 表示每次执行时会有最多5秒的随机延迟。
  • worker_affinity=0x3 表示只有第一个和第二个工作进程会执行这个函数(因为二进制掩码 0x3 对应于 0b11,即前两位为1)。

注意事项

  • 内存管理:确保周期性任务不会导致内存泄漏或其他资源问题。
  • 负载均衡:通过合理设置 jitterworker_affinity,可以有效分散负载,避免所有工作进程同时执行相同的任务。
js_preload_object

js_preload_object 指令用于预先加载JSON对象到Nginx环境中,这可以提高后续请求处理的速度,尤其是在频繁访问相同数据的情况下。这对于静态配置文件或不常变化的数据特别有用。

Syntax:	js_preload_object name.json | name from file.json;
Default:	—
Context:	http, server, location
This directive appeared in version 0.7.8.
  • name.json:直接定义JSON对象并命名。
  • name from file.json:从文件中加载JSON对象并命名。

案例

基本用法

假设我们有一个名为 config.json 的文件,我们希望将其作为 siteConfig 对象预加载:

http {
    js_preload_object siteConfig from config.json;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 使用预加载的对象
            js_content siteConfig;
        }
    }
}

在这个例子中,siteConfig 对象将在启动时从 config.json 文件中加载,并可以在后续请求中使用。

直接定义JSON对象

如果直接定义JSON对象,而不是从文件加载:

http {
    js_preload_object siteConfig {
        "version": "1.0",
        "features": ["login", "signup"]
    };

    server {
        listen 80;
        server_name example.com;

        location / {
            # 使用预加载的对象
            js_content siteConfig;
        }
    }
}

在这个例子中,siteConfig 对象直接在配置文件中定义,包含版本号和功能列表。

注意事项

  • 性能优化:预加载对象可以显著提高处理速度,特别是在高并发环境下频繁访问相同数据时。
  • 维护性:尽量保持预加载对象的简洁和易维护性,避免过于复杂的嵌套结构。
js_set

js_set 指令用于设置一个Nginx变量的值为JavaScript函数的返回结果。这对于动态生成内容或根据条件修改响应非常有用,例如动态生成HTTP头、计算用户角色等。

Syntax:	js_set $variable function | module.function [nocache];
Default:	—
Context:	http, server, location
  • $variable:指定要设置的Nginx变量。
  • functionmodule.function:指定计算该变量值的JavaScript函数或模块中的函数。
  • nocache(可选):禁用缓存,确保每次都重新计算。

案例

基本用法

假设我们有一个名为 getUserRole 的JavaScript函数,希望将其返回值赋给 $role 变量:

server {
    listen 80;
    server_name example.com;

    js_set $role getUserRole;

    location /profile {
        # 使用 $role 变量
        add_header X-User-Role $role;
        proxy_pass http://backend;
    }
}

在这个例子中,getUserRole 函数的返回值会被赋给 $role 变量,并在响应中作为自定义HTTP头 X-User-Role 返回。

禁用缓存

如果我们不希望缓存结果,而是每次都重新计算:

server {
    listen 80;
    server_name example.com;

    js_set $dynamicContent generateContent nocache;

    location /dynamic {
        # 每次都重新计算 $dynamicContent
        return 200 $dynamicContent;
    }
}

在这个例子中,generateContent 函数的结果不会被缓存,每次请求都会重新计算。

注意事项

  • 缓存策略:合理使用缓存可以提高性能,但需要注意缓存一致性问题。
  • 动态内容:对于频繁变化的内容,建议禁用缓存以确保实时性。
js_shared_dict_zone

js_shared_dict_zone 指令用于创建共享字典区,供JavaScript代码在不同请求之间共享数据。这对于需要跨请求保持状态的应用程序非常重要,例如会话管理、计数器等。

Syntax:	js_shared_dict_zone zone=name:size [timeout=time] [type=string|number] [evict];
Default:	—
Context:	http
This directive appeared in version 0.8.0.
  • zone=name:size:指定共享字典区的名字和大小。
  • timeout=time(可选):设置条目过期时间。
  • type=string|number(可选):指定存储的数据类型,默认是字符串。
  • evict(可选):当达到容量限制时,启用驱逐策略。

案例

基本用法

假设我们需要一个名为 userSessions 的共享字典区来存储用户会话信息,大小为1MB:

http {
    js_shared_dict_zone zone=userSessions:1m;

    server {
        listen 80;
        server_name example.com;

        location /login {
            # 使用 userSessions 共享字典区
            js_content handleLogin;
        }
    }
}

在这个例子中,userSessions 共享字典区大小为1MB,可用于存储用户会话信息。

配置超时和数据类型

如果我们还需要设置条目过期时间为1小时,并且仅存储数字类型的数据:

http {
    js_shared_dict_zone zone=userSessions:1m timeout=1h type=number;

    server {
        listen 80;
        server_name example.com;

        location /login {
            # 使用 userSessions 共享字典区
            js_content handleLogin;
        }
    }
}

在这个例子中:

  • timeout=1h 表示每个条目在1小时后过期。
  • type=number 表示存储的数据类型为数字。

启用驱逐策略

为了确保在达到容量限制时能够移除旧条目,我们可以启用驱逐策略:

http {
    js_shared_dict_zone zone=userSessions:1m evict;

    server {
        listen 80;
        server_name example.com;

        location /login {
            # 使用 userSessions 共享字典区
            js_content handleLogin;
        }
    }
}

在这个例子中,evict 参数启用了驱逐策略,当达到容量限制时,旧条目将被移除。

注意事项

  • 数据一致性:确保共享字典区中的数据一致性和及时更新,特别是在多进程或多线程环境下。
  • 容量管理:合理设置字典区大小和驱逐策略,以避免内存溢出或数据丢失。
js_var

js_var 指令用于定义一个 Nginx 变量,并可选地为其赋值。这个变量可以在 JavaScript 代码中使用,以便在 Nginx 配置和 JavaScript 之间传递数据。

Syntax:	js_var $variable [value];
Default: —
Context: http, server, location
This directive appeared in version 0.5.3.
  • $variable:要定义的 Nginx 变量名。
  • [value]:可选参数,为变量赋初始值。

案例

基本用法

最简单的 js_var 用法是指定一个 Nginx 变量并为其赋值:

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

        # 定义一个变量并赋初始值
        js_var $myVar "initial value";

        location /use_variable/ {
            # 使用 JavaScript 函数处理请求,并访问变量
            js_content useVariable;

            # 其他配置
        }

        js_include /path/to/your_script.js;
    }
}

在这个例子中:

  • 当用户访问 /use_variable/ 路径时,Nginx 将调用 useVariable 函数,并在 JavaScript 中可以访问 $myVar 变量及其初始值 "initial value"

动态赋值

你也可以动态地为变量赋值:

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

        location /dynamic_value/ {
            # 根据某些条件动态设置变量值
            set $myDynamicVar "";

            if ($request_method = POST) {
                set $myDynamicVar "POST request";
            }

            # 定义变量并使用动态值
            js_var $myDynamicVar;

            # 使用 JavaScript 函数处理请求,并访问变量
            js_content handleDynamicValue;

            # 其他配置
        }

        js_include /path/to/your_script.js;
    }
}

在这个例子中:

  • 访问 /dynamic_value/ 路径时,Nginx 将根据请求方法动态设置 $myDynamicVar 的值,并在 JavaScript 函数中使用该变量。

注意事项

  • 变量作用域:确保变量的作用域符合预期,特别是在复杂的配置中,避免变量冲突或意外覆盖。
  • 性能影响:频繁地设置和访问变量可能会影响性能,尤其是在高并发场景下。尽量减少不必要的变量操作。

2.28 ngx_http_keyval_module

ngx_http_keyval_module 是 Nginx 的一个模块,用于在 HTTP 请求和响应中处理键值对(key-value pairs)。这个模块允许你在 Nginx 配置中定义键值对的映射,并基于这些映射进行变量设置或条件判断。它特别适用于需要动态调整配置或根据请求参数进行路由和处理的场景。

主要功能

  • 键值对映射:允许定义键值对的映射表,并将其存储在共享内存中。
  • 变量支持:可以将映射结果存储在 Nginx 变量中,便于在配置文件中使用。
  • 灵活应用:可以根据键值对映射进行访问控制、内容定制、重定向等操作。

常用指令

  • keyval:定义键值对映射表。可以在 httpserver 块中使用。

  • keyval_zone:定义用于存储键值对映射的共享内存区域。必须与 keyval 指令一起使用。

使用示例

以下是一些简化的配置示例,展示了如何使用 ngx_http_keyval_module 来处理键值对映射。

基本键值对映射

假设你希望根据请求 URI 将请求转发到不同的后端服务:

http {
    # 定义共享内存区域
    keyval_zone zone=kvzone:10m;

    # 定义键值对映射
    keyval $request_uri $target_backend zone=kvzone {
        /api/v1/users api_backend;
        /api/v1/orders order_backend;
        default default_backend;
    }

    upstream api_backend {
        server 192.168.1.101:8080;
    }

    upstream order_backend {
        server 192.168.1.102:8080;
    }

    upstream default_backend {
        server 192.168.1.103:8080;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://$target_backend;
        }
    }
}

在这个例子中:

  • keyval_zone 定义了一个名为 kvzone 的共享内存区域,大小为 10MB。
  • keyval 指令定义了键值对映射,根据 $request_uri 设置 $target_backend 变量。
  • 根据请求 URI 的不同,代理请求会转发到不同的后端服务。

结合 map 指令使用

假设你希望根据请求头中的某个字段(如 X-Custom-Header)决定将请求转发到哪个后端服务:

http {
    # 定义共享内存区域
    keyval_zone zone=kvzone:10m;

    # 定义键值对映射
    keyval $custom_header_value $target_backend zone=kvzone {
        custom_value_1 backend1;
        custom_value_2 backend2;
        default default_backend;
    }

    upstream backend1 {
        server 192.168.1.101:8080;
    }

    upstream backend2 {
        server 192.168.1.102:8080;
    }

    upstream default_backend {
        server 192.168.1.103:8080;
    }

    server {
        listen 80;
        server_name example.com;

        # 提取自定义请求头的值
        set $custom_header_value $http_x_custom_header;

        location / {
            proxy_pass http://$target_backend;
        }
    }
}

在这个例子中:

  • keyval_zone 定义了一个名为 kvzone 的共享内存区域。
  • keyval 指令根据 $custom_header_value 设置 $target_backend 变量。
  • set 指令提取自定义请求头 X-Custom-Header 的值并存储在 $custom_header_value 变量中。

动态更新键值对

假设你需要动态更新键值对映射表,可以通过外部脚本修改共享内存区域中的数据。以下是一个简单的 Python 脚本示例,展示如何更新键值对:

import nginxparser

# 更新键值对映射
def update_keyval(zone, key, value):
    parser = nginxparser.NginxParser()
    config = parser.load('/etc/nginx/nginx.conf')
    
    for directive in config['http']:
        if 'keyval' in directive:
            if directive['keyval']['zone'] == zone:
                directive['keyval'][key] = value
    
    parser.dump(config, '/etc/nginx/nginx.conf')

update_keyval('kvzone', '/new/api/path', 'new_backend')

请注意,上述 Python 脚本仅作为示例,实际实现时需要根据你的环境和需求进行调整。

注意事项

  • 共享内存区域大小:确保共享内存区域的大小足够大,以容纳所有需要存储的键值对。如果键值对数量较多,可能需要增加内存区域的大小。

  • 性能优化:对于高并发环境,考虑使用缓存机制和其他性能优化措施,如压缩、负载均衡等。

  • 安全性:合理配置访问控制,防止未经授权的访问。可以使用 allowdeny 指令来限制访问。

  • 日志记录:启用详细的日志记录可以帮助监控和故障排查。可以根据需要调整日志级别和格式。

2.28.1 指令列表
keyval

keyval 指令用于在共享内存区域中存储键值对,并将其绑定到一个 Nginx 变量上。这使得多个 Nginx 工作进程可以共享数据。

Syntax:	keyval key $variable zone=name;
Default: —
Context: http
  • key:键名。
  • $variable:与键关联的 Nginx 变量。
  • zone=name:共享内存区域的名称。

案例

基本用法

最简单的 keyval 用法是定义一个键值对并将其绑定到一个变量:

http {
    # 定义共享内存区域
    keyval_zone zone=myZone:1m;

    server {
        listen 80;
        server_name example.com;

        # 定义键值对并绑定到变量
        keyval myKey $myKeyValue zone=myZone;

        location /access_shared_data/ {
            # 使用 JavaScript 函数处理请求,并访问变量
            js_content accessSharedData;

            # 其他配置
        }

        js_include /path/to/your_script.js;
    }
}

在这个例子中:

  • 当用户访问 /access_shared_data/ 路径时,Nginx 将调用 accessSharedData 函数,并在 JavaScript 中可以访问 $myKeyValue 变量,其值来自共享内存中的 myKey 键。

多个键值对

你可以定义多个键值对:

http {
    # 定义共享内存区域
    keyval_zone zone=myZone:1m;

    server {
        listen 80;
        server_name example.com;

        # 定义多个键值对并绑定到变量
        keyval user_id $userId zone=myZone;
        keyval session_token $sessionToken zone=myZone;

        location /manage_sessions/ {
            # 使用 JavaScript 函数处理请求,并访问变量
            js_content manageSessions;

            # 其他配置
        }

        js_include /path/to/your_script.js;
    }
}

在这个例子中:

  • 访问 /manage_sessions/ 路径时,Nginx 将调用 manageSessions 函数,并在 JavaScript 中可以访问 $userId$sessionToken 变量,它们分别对应共享内存中的 user_idsession_token 键。

注意事项

  • 内存管理:确保共享内存区域的大小足够存储所有需要的数据,但不要过大以避免浪费资源。
  • 同步问题:由于多个工作进程共享同一块内存区域,需注意并发访问时的同步问题。
keyval_zone

keyval_zone 指令用于定义共享内存区域,供 keyval 指令使用。这个区域用于存储键值对数据,使得多个 Nginx 工作进程可以共享这些数据。

Syntax:	keyval_zone zone=name:size [state=file] [timeout=time] [type=string|ip|prefix] [sync];
Default: —
Context: http
  • zone=name:共享内存区域的名称。
  • size:共享内存区域的大小(例如 1m 表示 1 MB)。
  • [state=file]:可选参数,指定状态文件路径,用于持久化数据。
  • [timeout=time]:可选参数,指定键值对的有效期。
  • [type=string|ip|prefix]:可选参数,指定键的类型,默认为 string
  • [sync]:可选参数,启用同步模式,确保数据一致性。

案例

基本用法

最简单的 keyval_zone 用法是定义一个共享内存区域:

http {
    # 定义共享内存区域
    keyval_zone zone=myZone:1m;

    server {
        listen 80;
        server_name example.com;

        # 定义键值对并绑定到变量
        keyval myKey $myKeyValue zone=myZone;

        location /shared_memory_example/ {
            # 使用 JavaScript 函数处理请求,并访问变量
            js_content sharedMemoryExample;

            # 其他配置
        }

        js_include /path/to/your_script.js;
    }
}

在这个例子中:

  • Nginx 定义了一个名为 myZone 的共享内存区域,大小为 1 MB,并在后续配置中使用该区域存储键值对。

高级配置

你可以进行更高级的配置,如设置状态文件、有效期和同步模式:

http {
    # 定义共享内存区域并设置高级选项
    keyval_zone zone=myAdvancedZone:2m state=/var/lib/nginx/myStateFile timeout=60s type=ip sync;

    server {
        listen 80;
        server_name example.com;

        # 定义键值对并绑定到变量
        keyval client_ip $clientIp zone=myAdvancedZone;

        location /advanced_shared_memory/ {
            # 使用 JavaScript 函数处理请求,并访问变量
            js_content advancedSharedMemory;

            # 其他配置
        }

        js_include /path/to/your_script.js;
    }
}

在这个例子中:

  • Nginx 定义了一个名为 myAdvancedZone 的共享内存区域,大小为 2 MB,并设置了状态文件路径 /var/lib/nginx/myStateFile、有效期 60 秒、键类型为 IP 地址以及同步模式。

注意事项

  • 内存管理:确保共享内存区域的大小足够存储所有需要的数据,但不要过大以避免浪费资源。
  • 状态文件:如果使用状态文件,请确保文件路径可写,并定期备份以防数据丢失。
  • 同步模式:启用同步模式可以提高数据一致性,但在高并发场景下可能会引入性能开销。

2.29 ngx_http_limit_conn_module

ngx_http_limit_conn_module 是 Nginx 的一个模块,用于限制每个定义的关键字(如客户端 IP 地址)的并发连接数。这个模块可以帮助防止服务器过载,并保护你的服务免受恶意攻击或过多的合法请求。

主要功能

  • 并发连接限制:限制特定关键字(如客户端 IP 地址)的并发连接数。
  • 灵活配置:可以针对不同的服务器块、位置块设置不同的限制规则,提供细粒度的控制。

常用指令

以下是 ngx_http_limit_conn_module 中一些常用的指令及其说明:

  • limit_conn_zone: 定义共享内存区域,用于存储限制状态和计数器。你可以指定关键字(如 $binary_remote_addr 表示客户端的 IP 地址)和存储区大小。

    语法示例:

    limit_conn_zone $binary_remote_addr zone=addr:10m;
    

    这里 $binary_remote_addr 是客户端 IP 地址的二进制表示形式,zone=addr:10m 定义了一个名为 addr 的共享内存区域,大小为 10MB。

  • limit_conn: 在特定上下文中应用并发连接限制。你可以指定之前定义的共享内存区域和允许的最大并发连接数。

    语法示例:

    limit_conn addr 10;
    

    这将限制每个客户端 IP 地址最多有 10 个并发连接。

  • limit_conn_log_level: 设置当达到限制时的日志记录级别。默认是 error 级别,但你可以根据需要调整为 infonotice

  • limit_conn_status: 设置当达到限制时返回的状态码,默认是 503 Service Temporarily Unavailable

使用示例

以下是一个简单的配置示例,展示了如何使用 ngx_http_limit_conn_module 来限制每个客户端 IP 地址的并发连接数:

http {
    # 定义共享内存区域,用于存储限制状态和计数器
    limit_conn_zone $binary_remote_addr zone=per_ip:10m;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 应用并发连接限制,每个IP地址最多允许10个并发连接
            limit_conn per_ip 10;

            # 设置日志级别为 notice
            limit_conn_log_level notice;

            # 设置超过限制时返回的状态码为 429 Too Many Requests
            limit_conn_status 429;

            # 根目录设置
            root /var/www/html;
            index index.html index.htm;
        }
    }
}

在这个例子中:

  • limit_conn_zone $binary_remote_addr zone=per_ip:10m; 定义了一个名为 per_ip 的共享内存区域,大小为 10MB,用于存储每个客户端 IP 地址的并发连接数。
  • limit_conn per_ip 10; 将每个客户端 IP 地址的并发连接数限制为 10。
  • limit_conn_log_level notice; 设置当达到限制时的日志记录级别为 notice
  • limit_conn_status 429; 设置当达到限制时返回的状态码为 429 Too Many Requests

注意事项

  • 性能影响:虽然限制并发连接数有助于保护服务器资源,但如果设置过于严格,可能会导致正常用户无法访问服务。因此,建议根据实际流量模式和服务器容量进行合理配置。
  • 关键字选择:选择合适的关键字对于实现有效的限制至关重要。常见的关键字包括 $binary_remote_addr(客户端 IP 地址的二进制表示)和 $server_name(虚拟主机名)。使用 $binary_remote_addr 可以更高效地利用内存。
  • 缓存和代理的影响:如果客户端通过代理或 CDN 访问你的服务,所有请求可能看起来来自同一个 IP 地址(即代理服务器的 IP 地址),这会影响限制效果。在这种情况下,考虑使用 X-Forwarded-For 头或其他方法来获取真实客户端 IP。
  • 测试验证:在部署之前进行全面测试,确保所有配置按预期工作,并检查是否有任何潜在的问题(如误拒绝合法请求等)。
2.29.1 指令列表
limit_conn

limit_conn 指令用于限制每个定义的共享内存区域中的连接数。这有助于防止服务器过载,特别是在高并发场景下。

Syntax:	limit_conn zone number;
Default: —
Context: http, server, location
  • zone:共享内存区域的名称,通常由 limit_conn_zone 指令定义。
  • number:允许的最大连接数。

案例

基本用法

最简单的 limit_conn 用法是指定一个共享内存区域和最大连接数:

http {
    # 定义共享内存区域
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    server {
        listen 80;
        server_name example.com;

        # 限制每个 IP 地址的最大连接数为 10
        limit_conn addr 10;

        location /limited_resource/ {
            # 其他配置
        }
    }
}

在这个例子中:

  • Nginx 定义了一个名为 addr 的共享内存区域,用于存储每个 IP 地址的连接数,并限制每个 IP 地址最多只能有 10 个并发连接。

多个限制

你可以为不同的位置设置不同的连接限制:

http {
    # 定义共享内存区域
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    server {
        listen 80;
        server_name example.com;

        # 限制每个 IP 地址的最大连接数为 10
        limit_conn addr 10;

        location /high_limit/ {
            # 提高限制,允许每个 IP 地址最多 50 个并发连接
            limit_conn addr 50;

            # 其他配置
        }

        location /low_limit/ {
            # 降低限制,允许每个 IP 地址最多 5 个并发连接
            limit_conn addr 5;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /high_limit/ 路径时,Nginx 将允许每个 IP 地址最多有 50 个并发连接。
  • 访问 /low_limit/ 路径时,Nginx 将允许每个 IP 地址最多有 5 个并发连接。

注意事项

  • 性能影响:限制连接数可以帮助防止服务器过载,但如果设置过于严格,可能会导致合法用户的请求被拒绝。需根据实际需求合理设置。
  • 日志记录:建议启用相关日志记录,以便监控和调试连接限制的效果。
  • 扩展性:如果需要更复杂的限流策略,可以考虑结合其他模块(如 limit_req)一起使用。
limit_conn_dry_run

limit_conn_dry_run 用于启用或禁用连接限制的“试运行”模式。在试运行模式下,Nginx 会记录超出限制的连接数但不会实际拒绝这些连接。这对于测试和调试非常有用。

Syntax:	limit_conn_dry_run on | off;
Default: limit_conn_dry_run off;
Context: http, server, location
This directive appeared in version 1.17.6.
  • on:启用试运行模式。
  • off:禁用试运行模式(默认行为)。

案例

基本用法

最简单的 limit_conn_dry_run 用法是指定是否启用试运行模式:

server {
    listen 80;
    server_name example.com;

    location /limited/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 10;  # 限制每个 IP 地址最多 10 个并发连接
        limit_conn_dry_run on;  # 启用试运行模式,记录但不拒绝超出限制的连接
    }
}

在这个例子中,设置了 limit_conn_dry_run on,这意味着 Nginx 将记录超出限制的连接数但不会实际拒绝这些连接。

调整试运行模式

根据实际需求调整试运行模式:

server {
    listen 80;
    server_name example.com;

    location /test_limit/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 5;  # 限制每个 IP 地址最多 5 个并发连接
        limit_conn_dry_run on;  # 启用试运行模式,适用于测试环境
    }

    location /production_limit/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 5;  # 限制每个 IP 地址最多 5 个并发连接
        limit_conn_dry_run off;  # 禁用试运行模式,适用于生产环境
    }
}

在这个例子中:

  • 对于 /test_limit/ 路径下的请求,启用了试运行模式,适用于测试环境。
  • 对于 /production_limit/ 路径下的请求,禁用了试运行模式,适用于生产环境。

注意事项

  • 调试和监控:试运行模式有助于在不影响用户体验的情况下进行调试和监控。
  • 性能影响:虽然试运行模式不会拒绝连接,但它仍然会产生额外的日志记录开销。
limit_conn_log_level

limit_conn_log_level 用于设置当达到连接限制时的日志级别。这有助于控制日志输出的详细程度,以便更好地理解和分析问题。

Syntax:	limit_conn_log_level info | notice | warn | error;
Default: limit_conn_log_level error;
Context: http, server, location
This directive appeared in version 0.8.18.
  • info:信息级别日志。
  • notice:通知级别日志。
  • warn:警告级别日志。
  • error:错误级别日志(默认行为)。

案例

基本用法

最简单的 limit_conn_log_level 用法是指定日志级别:

server {
    listen 80;
    server_name example.com;

    location /limited/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 10;  # 限制每个 IP 地址最多 10 个并发连接
        limit_conn_log_level warn;  # 设置日志级别为警告
    }
}

在这个例子中,设置了 limit_conn_log_level warn,这意味着当达到连接限制时,Nginx 将记录警告级别的日志。

调整日志级别

根据实际需求调整日志级别:

server {
    listen 80;
    server_name example.com;

    location /critical_limit/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 5;  # 限制每个 IP 地址最多 5 个并发连接
        limit_conn_log_level error;  # 设置日志级别为错误,适用于关键场景
    }

    location /non_critical_limit/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 5;  # 限制每个 IP 地址最多 5 个并发连接
        limit_conn_log_level notice;  # 设置日志级别为通知,适用于非关键场景
    }
}

在这个例子中:

  • 对于 /critical_limit/ 路径下的请求,设置了日志级别为错误,适用于关键场景。
  • 对于 /non_critical_limit/ 路径下的请求,设置了日志级别为通知,适用于非关键场景。

注意事项

  • 日志管理:选择合适的日志级别有助于有效管理和分析日志,避免过多的日志噪音。
  • 性能影响:较高的日志级别可能会产生更多的日志记录,从而增加 I/O 负载。
limit_conn_status

limit_conn_status 用于设置当达到连接限制时返回给客户端的 HTTP 状态码。这有助于定义如何响应超过限制的请求。

Syntax:	limit_conn_status code;
Default: limit_conn_status 503;
Context: http, server, location
This directive appeared in version 1.3.15.
  • code:指定返回的 HTTP 状态码,默认是 503(服务不可用)。

案例

基本用法

最简单的 limit_conn_status 用法是指定返回的状态码:

server {
    listen 80;
    server_name example.com;

    location /limited/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 10;  # 限制每个 IP 地址最多 10 个并发连接
        limit_conn_status 429;  # 设置状态码为 429(请求过多)
    }
}

在这个例子中,设置了 limit_conn_status 429,这意味着当达到连接限制时,Nginx 将返回 429 状态码给客户端。

调整返回状态码

根据实际需求调整返回的状态码:

server {
    listen 80;
    server_name example.com;

    location /overload_limit/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 5;  # 限制每个 IP 地址最多 5 个并发连接
        limit_conn_status 503;  # 设置状态码为 503(服务不可用),适用于过载场景
    }

    location /rate_limit/ {
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 5;  # 限制每个 IP 地址最多 5 个并发连接
        limit_conn_status 429;  # 设置状态码为 429(请求过多),适用于速率限制场景
    }
}

在这个例子中:

  • 对于 /overload_limit/ 路径下的请求,设置了状态码为 503,适用于过载场景。
  • 对于 /rate_limit/ 路径下的请求,设置了状态码为 429,适用于速率限制场景。

注意事项

  • 客户端体验:选择合适的状态码可以提供更清晰的反馈,帮助客户端理解并处理限制情况。
  • API 设计:对于 API 接口,使用标准的状态码(如 429)有助于遵循 RESTful API 的最佳实践。
limit_conn_zone

limit_conn_zone 用于定义一个共享内存区域来存储连接限制的状态数据。这个指令通常与 limit_conn 配合使用,以实现对特定键的连接限制。

Syntax:	limit_conn_zone key zone=name:size;
Default: —
Context: http
  • key:用于计算限制的键值,例如 $binary_remote_addr 表示客户端的二进制 IP 地址。
  • zone:定义共享内存区域的名称和大小,格式为 name:size

案例

基本用法

最简单的 limit_conn_zone 用法是指定键和共享内存区域:

http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;  # 定义共享内存区域,大小为 10MB

    server {
        listen 80;
        server_name example.com;

        location /limited/ {
            limit_conn addr 10;  # 限制每个 IP 地址最多 10 个并发连接
        }
    }
}

在这个例子中,定义了一个名为 addr 的共享内存区域,大小为 10MB,并用于限制每个 IP 地址最多 10 个并发连接。

多种限制组合

根据实际需求组合不同的限制:

http {
    limit_conn_zone $binary_remote_addr zone=per_ip:10m;  # 每个 IP 地址的连接限制
    limit_conn_zone $server_name zone=per_server:10m;  # 每个服务器名的连接限制

    server {
        listen 80;
        server_name example.com;

        location /ip_limited/ {
            limit_conn per_ip 10;  # 限制每个 IP 地址最多 10 个并发连接
        }

        location /server_limited/ {
            limit_conn per_server 100;  # 限制每个服务器名最多 100 个并发连接
        }
    }
}

在这个例子中:

  • 对于 /ip_limited/ 路径下的请求,限制了每个 IP 地址最多 10 个并发连接。
  • 对于 /server_limited/ 路径下的请求,限制了每个服务器名最多 100 个并发连接。

注意事项

  • 内存管理:确保共享内存区域的大小足够大,以避免在高并发情况下出现溢出。
  • 性能优化:合理配置共享内存区域的大小和连接限制,以平衡性能和资源使用。
limit_zone

limit_zone 指令用于定义一个共享内存区域,用于存储客户端的访问信息。这个指令帮助控制请求速率限制,通常与 limit_req 指令结合使用。

Syntax:	limit_zone name $variable size;
Default:	—
Context:	http
  • name:指定共享内存区域的名称。
  • $variable:指定用于标识客户端的变量(如 $binary_remote_addr)。
  • size:指定共享内存区域的大小(例如 10m 表示10兆字节)。

案例

基本用法

最简单的 limit_zone 用法是指定一个共享内存区域并设置其大小:

http {
    # 定义一个名为 'one' 的共享内存区域,使用 $binary_remote_addr 标识客户端,大小为 10MB
    limit_zone one $binary_remote_addr 10m;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 使用 'one' 区域进行限流
            limit_req zone=one burst=5 nodelay;
        }
    }
}

在这个例子中:

  • 设置了 limit_zone one $binary_remote_addr 10m,这意味着Nginx将创建一个名为 one 的共享内存区域,用于存储客户端的访问信息。

注意事项

  • 性能影响:共享内存区域的大小应根据预期的并发请求数量和系统资源合理设置。过小的区域可能导致频繁的内存分配和释放,影响性能。
  • 适用场景:适用于需要对客户端请求进行速率限制的应用场景。例如,在防止DDoS攻击、保护服务器资源等环境中使用。
  • 调试和监控:如果你遇到共享内存区域问题,可以检查以下几点:
    • 确保共享内存区域的名称和大小设置正确。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。

2.30 ngx_http_limit_req_module

ngx_http_limit_req_module 是 Nginx 的一个标准模块,用于限制客户端请求的速率。这个模块通过令牌桶算法(Token Bucket Algorithm)来控制请求频率,防止服务器被过多的请求淹没,从而提高系统的稳定性和安全性。

主要功能

  • 请求速率限制:可以设置每秒允许的最大请求数量。
  • 突发处理:允许配置突发流量的处理方式,即在短时间内接受超过设定速率的请求。
  • 分布式限流:可以通过共享内存区实现多台 Nginx 实例之间的限流同步。

常用指令

以下是与 ngx_http_limit_req_module 模块相关的常用配置指令及其简要说明:

  • limit_req_zone:定义一个共享内存区,用于存储状态信息和限制规则。通常在 http 上下文中定义。

    • 语法:limit_req_zone key zone=name:size rate=rate;
    • 示例:limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
  • limit_req:应用限流规则。通常在 serverlocation 上下文中使用。

    • 语法:limit_req zone=name [burst=number] [nodelay];
    • 示例:limit_req zone=mylimit burst=5 nodelay;
  • limit_req_log_level:当请求被拒绝时的日志级别。默认是 error

    • 示例:limit_req_log_level warn;
  • limit_req_status:当请求被拒绝时返回的 HTTP 状态码。默认是 503

    • 示例:limit_req_status 429;

使用示例

以下是一些具体的配置示例,展示如何利用 ngx_http_limit_req_module 来限制请求速率。

基本配置

假设你想限制每个 IP 地址每秒只能发送一个请求,并且允许最多五个突发请求:

  1. http 上下文中定义限流区域:

    http {
        # 定义限流区域,基于客户端 IP 地址,大小为 10MB,速率限制为每秒 1 个请求
        limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
    
        server {
            listen 80;
            server_name example.com;
    
            location / {
                # 应用限流规则,允许最多 5 个突发请求
                limit_req zone=mylimit burst=5 nodelay;
    
                proxy_pass http://backend;
            }
        }
    }
    

在这个例子中:

  • limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s; 定义了一个名为 mylimit 的限流区域,基于客户端的 IP 地址,分配了 10MB 的共享内存空间,并设置了每秒 1 个请求的速率限制。
  • limit_req zone=mylimit burst=5 nodelay; 应用了该限流规则,允许最多 5 个突发请求,并立即处理这些请求而不是排队等待。

处理突发请求

如果你希望允许突发请求但不立即处理它们,可以去掉 nodelay 参数:

http {
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 允许最多 5 个突发请求,但将它们排队处理
            limit_req zone=mylimit burst=5;

            proxy_pass http://backend;
        }
    }
}

在这个例子中:

  • 如果有突发请求超过速率限制,Nginx 会将这些请求放入队列中逐步处理,而不是立即拒绝。

多级限流

你可以结合多个限流区域来实现更复杂的限流策略。例如,基于不同的条件进行限流:

http {
    # 基于 IP 地址的限流
    limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;

    # 基于 URI 的限流
    limit_req_zone $request_uri zone=peruri:10m rate=1r/m;

    server {
        listen 80;
        server_name example.com;

        location /login {
            # 同时应用两个限流规则
            limit_req zone=perip burst=5 nodelay;
            limit_req zone=peruri burst=10;

            proxy_pass http://backend;
        }

        location / {
            limit_req zone=perip burst=5 nodelay;

            proxy_pass http://backend;
        }
    }
}

在这个例子中:

  • /login 路径下的请求同时受到基于 IP 地址和基于 URI 的限流规则的影响。
  • / 路径下的请求仅受基于 IP 地址的限流规则影响。

日志记录和错误处理

你可以配置日志记录级别和返回的状态码,以便更好地监控和处理限流情况:

http {
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;

    server {
        listen 80;
        server_name example.com;

        # 当请求被拒绝时记录警告日志
        limit_req_log_level warn;

        # 当请求被拒绝时返回 429 Too Many Requests 状态码
        limit_req_status 429;

        location / {
            limit_req zone=mylimit burst=5 nodelay;

            proxy_pass http://backend;
        }
    }
}

在这个例子中:

  • limit_req_log_level warn; 设置了当请求被拒绝时记录警告级别的日志。
  • limit_req_status 429; 设置了当请求被拒绝时返回 429 Too Many Requests 状态码。

注意事项

  • 性能考虑

    • 限流规则应根据实际需求进行调整,避免过于严格的限制导致正常请求被拒绝。
    • 共享内存区的大小应根据预计的并发请求数量合理设置,以确保限流机制能够正常工作。
  • 安全性

    • 正确配置限流规则,防止恶意用户通过大量请求攻击服务器。
    • 结合其他安全措施(如防火墙、WAF 等)增强整体安全性。
  • 调试

    • 使用日志记录功能来监控限流行为,及时发现并解决潜在问题。
    • 在测试环境中充分验证限流配置,确保其在生产环境中能按预期工作。
2.30.1 指令列表
limit_req

limit_req 指令用于限制请求的速率。这个指令通常与 limit_zone 结合使用,以实现对特定区域的请求速率限制。

Syntax:	limit_req zone=name [burst=number] [nodelay | delay=number];
Default:	—
Context:	http, server, location
  • zone=name:指定要使用的共享内存区域。
  • burst=number:指定突发请求的最大数量(可选,默认值为 0)。
  • nodelay:如果设置了此选项,则所有超出限制的请求将立即被拒绝(可选)。
  • delay=number:指定延迟处理超出限制的请求的时间(可选)。

案例

基本用法

最简单的 limit_req 用法是指定一个共享内存区域并设置请求速率限制:

http {
    limit_zone one $binary_remote_addr 10m;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 使用 'one' 区域进行限流,允许每秒最多一个请求,突发请求最多5个
            limit_req zone=one burst=5 nodelay;
        }
    }
}

在这个例子中:

  • 设置了 limit_req zone=one burst=5 nodelay,这意味着Nginx将限制每个客户端每秒最多一个请求,突发请求最多5个,并且不延迟处理超出限制的请求。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的请求速率限制:

server {
    listen 80;
    server_name example.com;

    location /api/ {
        # API 请求限制为每秒最多两个请求,突发请求最多10个
        limit_req zone=one burst=10;

        proxy_pass http://backend_api;
    }

    location /static/ {
        # 静态资源请求限制为每秒最多五个请求,突发请求最多20个
        limit_req zone=one burst=20;

        root /var/www/static;
    }
}

在这个例子中:

  • 对于 /api/ 路径,设置了 limit_req zone=one burst=10,适合API请求。
  • 对于 /static/ 路径,设置了 limit_req zone=one burst=20,适合静态资源请求。

注意事项

  • 性能影响:合理的请求速率限制可以防止服务器过载,但过于严格的限制可能导致合法请求被拒绝。根据实际应用场景选择合适的限制策略。
  • 适用场景:适用于需要对客户端请求进行速率限制的应用场景。例如,在防止DDoS攻击、保护服务器资源等环境中使用。
  • 调试和监控:如果你遇到请求速率限制问题,可以检查以下几点:
    • 确保共享内存区域和限制参数设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
limit_req_dry_run

limit_req_dry_run 指令用于启用或禁用限流规则的“干运行”模式。在这个模式下,Nginx会记录限流日志但不会实际执行限流操作。

Syntax:	limit_req_dry_run on | off;
Default:	limit_req_dry_run off;
Context:	http, server, location
This directive appeared in version 1.17.1.
  • on:启用干运行模式。
  • off:禁用干运行模式(默认值)。

案例

基本用法

最简单的 limit_req_dry_run 用法是指定是否启用干运行模式:

http {
    limit_zone one $binary_remote_addr 10m;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 启用干运行模式,记录限流日志但不实际执行限流
            limit_req_dry_run on;
            limit_req zone=one burst=5 nodelay;
        }
    }
}

在这个例子中:

  • 设置了 limit_req_dry_run on,这意味着Nginx将记录限流日志但不会实际执行限流操作。

动态设置不同配置

你可以根据不同的路径或条件动态设置是否启用干运行模式:

server {
    listen 80;
    server_name example.com;

    location /test_env/ {
        # 在测试环境中启用干运行模式
        limit_req_dry_run on;
        limit_req zone=one burst=5 nodelay;
    }

    location /prod_env/ {
        # 在生产环境中禁用干运行模式
        limit_req_dry_run off;
        limit_req zone=one burst=5 nodelay;
    }
}

在这个例子中:

  • 对于 /test_env/ 路径,设置了 limit_req_dry_run on,适合测试环境。
  • 对于 /prod_env/ 路径,设置了 limit_req_dry_run off,适合生产环境。

注意事项

  • 调试和监控:干运行模式非常适合在部署新规则之前进行测试,以确保限流规则的行为符合预期。
  • 适用场景:适用于需要测试限流规则而不影响实际服务的应用场景。例如,在开发和测试阶段使用。
  • 调试和监控:如果你遇到干运行模式问题,可以检查以下几点:
    • 确保干运行模式设置正确,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
limit_req_log_level

limit_req_log_level 指令用于设置限流日志的记录级别。这个指令帮助控制限流操作的日志详细程度。

Syntax:	limit_req_log_level info | notice | warn | error;
Default:	limit_req_log_level error;
Context:	http, server, location
This directive appeared in version 0.8.18.
  • info:记录详细的信息日志。
  • notice:记录通知级别的日志。
  • warn:记录警告级别的日志。
  • error:记录错误级别的日志(默认值)。

案例

基本用法

最简单的 limit_req_log_level 用法是指定日志记录级别:

http {
    limit_zone one $binary_remote_addr 10m;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 设置限流日志记录级别为 warn
            limit_req_log_level warn;
            limit_req zone=one burst=5 nodelay;
        }
    }
}

在这个例子中:

  • 设置了 limit_req_log_level warn,这意味着Nginx将以警告级别记录限流日志。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的日志记录级别:

server {
    listen 80;
    server_name example.com;

    location /critical_section/ {
        # 对关键路径设置更详细的日志记录级别
        limit_req_log_level info;
        limit_req zone=one burst=5 nodelay;
    }

    location /normal_section/ {
        # 对普通路径设置较简单的日志记录级别
        limit_req_log_level warn;
        limit_req zone=one burst=5 nodelay;
    }
}

在这个例子中:

  • 对于 /critical_section/ 路径,设置了 limit_req_log_level info,适合关键路径。
  • 对于 /normal_section/ 路径,设置了 limit_req_log_level warn,适合普通路径。

注意事项

  • 性能影响:较高的日志记录级别会增加日志文件的大小和I/O负载。根据实际需求选择合适的日志记录级别,避免不必要的性能开销。
  • 适用场景:适用于需要控制限流日志详细程度的应用场景。例如,在调试、监控和故障排查等环境中使用。
  • 调试和监控:如果你遇到日志记录级别问题,可以检查以下几点:
    • 确保日志记录级别设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
limit_req_status

limit_req_status 指令用于设置当请求速率超过限制时返回的 HTTP 状态码。

Syntax:	limit_req_status code;
Default:	limit_req_status 503;
Context:	http, server, location
This directive appeared in version 1.3.15.
  • code:指定当请求速率超过限制时返回的 HTTP 状态码,默认值为 503(服务不可用)。

案例

基本用法

最简单的 limit_req_status 用法是指定一个特定的状态码:

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

        # 设置限速状态码为 429(Too Many Requests)
        limit_req_status 429;

        location /api/ {
            # 使用限速区域
            limit_req zone=my_limit burst=10 nodelay;

            proxy_pass http://backend.example.com;
        }
    }

    # 定义限速区域
    limit_req_zone $binary_remote_addr zone=my_limit:10m rate=1r/s;
}

在这个例子中:

  • 当请求速率超过限制时,Nginx 将返回 429 Too Many Requests 状态码,而不是默认的 503 Service Unavailable

注意事项

  • 状态码选择:根据你的需求选择合适的状态码。例如,429 Too Many Requests 更明确地表示客户端发送了过多的请求。
  • 用户体验:确保返回的状态码能够清晰传达服务器当前的状态,以便客户端可以正确处理。
  • 调试和监控:如果你遇到限速状态码问题,可以检查以下几点:
    • 确保限速配置正确,并且状态码设置符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
limit_req_zone

limit_req_zone 指令用于定义一个限速区域,该区域用于存储会话状态并限制请求速率。

Syntax:	limit_req_zone key zone=name:size rate=rate [sync];
Default:	—
Context:	http
  • key:指定用于限速的键,通常是客户端的 IP 地址或其他唯一标识符。
  • zone:指定限速区域的名称和大小,格式为 name:size
  • rate:指定请求速率限制,例如 1r/s 表示每秒最多允许一个请求。
  • [sync]:可选参数,用于同步多个工作进程之间的共享内存。

案例

定义限速区域

最简单的 limit_req_zone 用法是指定一个限速区域:

http {
    # 定义限速区域
    limit_req_zone $binary_remote_addr zone=my_limit:10m rate=1r/s;

    server {
        listen 80;
        server_name example.com;

        location /api/ {
            # 使用限速区域
            limit_req zone=my_limit burst=10 nodelay;

            proxy_pass http://backend.example.com;
        }
    }
}

在这个例子中:

  • $binary_remote_addr 是客户端的 IP 地址,作为限速的键。
  • my_limit 是限速区域的名称,分配了 10m 的内存空间。
  • 1r/s 表示每秒最多允许一个请求。

使用多个限速区域

你可以定义多个限速区域来处理不同的限速需求:

http {
    # 定义两个限速区域
    limit_req_zone $binary_remote_addr zone=per_ip:10m rate=1r/s;
    limit_req_zone $server_name zone=per_server:10m rate=5r/m;

    server {
        listen 80;
        server_name example.com;

        location /api/ {
            # 使用 per_ip 限速区域
            limit_req zone=per_ip burst=10 nodelay;

            proxy_pass http://backend.example.com;
        }

        location /static/ {
            # 使用 per_server 限速区域
            limit_req zone=per_server burst=5 nodelay;

            root /var/www/static;
        }
    }
}

在这个例子中:

  • per_ip 限速区域针对每个客户端 IP 地址进行限速。
  • per_server 限速区域针对每个服务器名称进行限速。

注意事项

  • 内存使用:确保为限速区域分配足够的内存空间,避免因内存不足导致限速功能失效。
  • 限速策略:根据实际需求选择合适的限速策略,并合理设置 burstnodelay 参数。
  • 调试和监控:如果你遇到限速区域问题,可以检查以下几点:
    • 确保限速区域配置正确,并且内存分配合理。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。

2.31 ngx_http_log_module

ngx_http_log_module 是 Nginx 的一个核心模块,用于记录 HTTP 请求的日志。通过该模块,你可以自定义日志格式、选择日志文件的位置以及控制哪些请求需要记录日志。这有助于监控服务器的运行状态、分析流量模式和排查问题。

主要功能

  • 日志记录:支持将 HTTP 请求的相关信息记录到日志文件中。
  • 自定义日志格式:允许定义多种日志格式,包括常见的组合日志格式(Combined Log Format)和其他自定义格式。
  • 条件日志记录:可以根据特定条件决定是否记录某个请求的日志。
  • 缓冲日志:支持日志缓冲,减少磁盘 I/O 操作,提高性能。

常用指令

  • log_format:定义日志格式。可以指定多个日志格式,并在不同的 location 或 server 中使用。

  • access_log:指定日志文件路径及使用的日志格式。可以为不同的 server 或 location 定义不同的访问日志。

  • error_log:记录错误日志。可以设置不同级别的错误日志(如 debug, info, notice, warn, error, crit, alert, emerg)。

使用示例

以下是一些简化的配置示例,展示了如何使用 ngx_http_log_module 来记录和管理 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;

    server {
        listen 80;
        server_name example.com;

        location / {
            root /var/www/html;
            index index.html index.htm;
        }
    }
}

在这个例子中:

  • log_format 定义了一个名为 main 的日志格式,包含了客户端 IP 地址、用户、时间戳、请求行、状态码、发送字节数、来源页面、用户代理和转发地址等信息。
  • access_log 指令指定了日志文件路径 /var/log/nginx/access.log 并使用 main 日志格式。

自定义日志格式

假设你希望添加一些额外的信息,例如响应时间:

http {
    # 定义带有响应时间的日志格式
    log_format custom '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" '
                      '$request_time';

    # 设置访问日志
    access_log /var/log/nginx/custom_access.log custom;

    server {
        listen 80;
        server_name example.com;

        location / {
            root /var/www/html;
            index index.html index.htm;
        }
    }
}

在这个例子中:

  • log_format 定义了一个名为 custom 的日志格式,增加了 $request_time 变量来记录每个请求的处理时间。
  • access_log 指令指定了日志文件路径 /var/log/nginx/custom_access.log 并使用 custom 日志格式。

条件日志记录

假设你希望仅记录非 2xx 和 3xx 状态码的请求:

http {
    # 定义日志格式
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    # 使用 map 定义条件变量
    map $status $loggable {
        ~^[23] 0;  # 不记录 2xx 和 3xx 状态码的请求
        default 1;
    }

    # 设置访问日志并应用条件
    access_log /var/log/nginx/access.log main if=$loggable;

    server {
        listen 80;
        server_name example.com;

        location / {
            root /var/www/html;
            index index.html index.htm;
        }
    }
}

在这个例子中:

  • map 指令定义了一个名为 $loggable 的变量,根据 $status 的值决定是否记录日志。如果状态码以 2 或 3 开头,则 $loggable 的值为 0,否则为 1。
  • access_log 指令使用了 if=$loggable 参数,只有当 $loggable 为 1 时才会记录日志。

缓冲日志

为了减少磁盘 I/O 操作,可以启用日志缓冲:

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 buffer=32k flush=1m;

    server {
        listen 80;
        server_name example.com;

        location / {
            root /var/www/html;
            index index.html index.htm;
        }
    }
}

在这个例子中:

  • buffer=32k 表示每次写入日志时缓冲 32KB 的数据。
  • flush=1m 表示每分钟将缓冲区中的日志刷新到磁盘一次。

注意事项

  • 日志轮转:为了避免日志文件过大,建议使用日志轮转工具(如 logrotate)定期压缩和归档旧日志文件。

  • 性能优化:对于高并发环境,考虑使用日志缓冲和异步日志记录机制,减少对主进程的影响。

  • 日志安全:确保日志文件的权限设置正确,防止未经授权的访问。通常,日志文件应由 Web 服务器用户(如 www-data)拥有。

  • 日志格式:合理设计日志格式,确保记录的信息既足够详细又不会过于冗长。常用的字段包括客户端 IP 地址、请求时间、请求行、状态码、发送字节数、来源页面、用户代理和转发地址等。

2.31.1 指令列表
access_log

access_log 指令用于指定访问日志的路径、格式和其他选项。

Syntax:	access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default:	access_log logs/access.log combined;
Context:	http, server, location, if in location, limit_except
  • path:指定访问日志的存储路径。
  • format:指定日志格式,默认为 combined
  • buffer=size:指定日志缓冲区大小。
  • gzip[=level]:启用日志压缩,并可指定压缩级别。
  • flush=time:指定日志刷新间隔时间。
  • if=condition:指定日志记录的条件。

案例

基本用法

最简单的 access_log 用法是指定日志的存储路径和格式:

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

        # 设置访问日志路径和格式
        access_log /var/log/nginx/example_access.log combined;

        location / {
            root /var/www/html;
        }
    }
}

在这个例子中:

  • 访问日志将存储在 /var/log/nginx/example_access.log 文件中,使用 combined 格式。

使用缓冲和压缩

你可以启用日志缓冲和压缩来优化性能:

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

        # 设置访问日志路径、格式、缓冲和压缩
        access_log /var/log/nginx/example_access.log combined buffer=32k gzip=1;

        location / {
            root /var/www/html;
        }
    }
}

在这个例子中:

  • 日志缓冲区大小设置为 32k,并启用了 gzip 压缩,压缩级别为 1

条件性日志记录

你可以根据条件记录日志:

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

        # 条件性日志记录
        access_log /var/log/nginx/example_access.log combined if=$request_method != 'HEAD';

        location / {
            root /var/www/html;
        }
    }
}

在这个例子中:

  • 只有当请求方法不是 HEAD 时才会记录日志。

注意事项

  • 日志路径:确保日志文件路径正确,并且 Nginx 进程有权限写入该路径。
  • 日志格式:根据实际需求选择合适的日志格式,并确保格式字符串正确。
  • 性能优化:通过启用日志缓冲和压缩可以减少 I/O 开销,提高性能。
  • 调试和监控:如果你遇到日志记录问题,可以检查以下几点:
    • 确保日志路径和格式设置正确。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
log_format

log_format 指令用于定义日志格式,允许你自定义访问日志的输出内容。

Syntax:	log_format name [escape=default|json|none] string ...;
Default:	log_format combined "...";
Context:	http
  • name:指定日志格式的名称。
  • escape=default|json|none:指定转义规则,默认为 default
  • string:指定日志格式字符串。

案例

基本用法

最简单的 log_format 用法是定义一个自定义日志格式:

http {
    # 定义自定义日志格式
    log_format custom '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    server {
        listen 80;
        server_name example.com;

        # 使用自定义日志格式
        access_log /var/log/nginx/example_access.log custom;

        location / {
            root /var/www/html;
        }
    }
}

在这个例子中:

  • 定义了一个名为 custom 的日志格式,并在 access_log 中使用该格式。

使用 JSON 转义

你可以使用 JSON 转义规则来生成 JSON 格式的日志:

http {
    # 定义 JSON 格式的日志格式
    log_format json escape=json '{"remote_addr": "$remote_addr", '
                               '"time_local": "$time_local", '
                               '"request": "$request", '
                               '"status": $status, '
                               '"body_bytes_sent": $body_bytes_sent, '
                               '"http_referer": "$http_referer", '
                               '"http_user_agent": "$http_user_agent"}';

    server {
        listen 80;
        server_name example.com;

        # 使用 JSON 格式的日志格式
        access_log /var/log/nginx/example_access.json json;

        location / {
            root /var/www/html;
        }
    }
}

在这个例子中:

  • 定义了一个名为 json 的日志格式,并启用了 JSON 转义规则,生成 JSON 格式的日志。

注意事项

  • 格式字符串:确保格式字符串正确,并包含所需的所有字段。
  • 转义规则:根据实际需求选择合适的转义规则,特别是当你需要生成 JSON 格式的日志时。
  • 调试和监控:如果你遇到日志格式问题,可以检查以下几点:
    • 确保日志格式字符串正确,并且所有字段都存在。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
open_log_file_cache

open_log_file_cache 指令用于配置Nginx的日志文件句柄缓存,以提高日志写入性能。这对于频繁写入日志的场景特别有用,可以减少打开和关闭文件的操作次数。

Syntax:	open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
Default:	open_log_file_cache off;
Context:	http, server, location
  • max=N:指定缓存中可以存储的最大文件描述符数量。
  • inactive=time(可选):指定如果在指定时间内没有访问某个文件描述符,则将其从缓存中移除。默认值是10秒。
  • min_uses=N(可选):指定一个文件描述符在被缓存之前必须被使用的最少次数。默认值是1。
  • valid=time(可选):指定检查文件描述符是否仍然有效的间隔时间。默认值是60秒。
  • off:禁用日志文件句柄缓存。

案例

基本用法

假设我们希望缓存最多100个日志文件描述符,并且每个描述符在60秒内未使用则被移除:

http {
    open_log_file_cache max=100 inactive=60s;

    server {
        listen 80;
        server_name example.com;

        access_log /var/log/nginx/access.log;
    }
}

使用所有参数

如果我们希望更精细地控制缓存行为,例如设置最小使用次数为2次,有效验证时间为30秒:

http {
    open_log_file_cache max=100 inactive=60s min_uses=2 valid=30s;

    server {
        listen 80;
        server_name example.com;

        access_log /var/log/nginx/access.log;
    }
}

禁用缓存

如果我们不希望使用日志文件句柄缓存:

http {
    open_log_file_cache off;

    server {
        listen 80;
        server_name example.com;

        access_log /var/log/nginx/access.log;
    }
}

注意事项

  • 性能优化:合理设置缓存参数可以显著提高日志写入性能,特别是在高并发环境下。
  • 资源管理:确保缓存大小和超时设置不会导致过多的内存占用或无效的文件描述符。

2.32 ngx_http_map_module

ngx_http_map_module 是 Nginx 的一个模块,用于创建变量之间的映射关系。通过这个模块,你可以根据一个变量的值动态地设置另一个变量的值。这在需要根据不同条件动态调整配置时非常有用,例如根据请求头、URI 参数或其他变量来决定某些行为。

主要功能

  • 变量映射:基于某个变量的值,动态生成另一个变量的值。
  • 灵活条件处理:可以使用正则表达式或精确匹配来定义映射规则。
  • 高效性能:映射表在配置加载时被编译为哈希表,因此在运行时查找非常高效。

常用指令

以下是 ngx_http_map_module 中一些常用的指令及其说明:

  • map: 定义变量之间的映射关系。语法如下:

    map $source_variable $result_variable {
        default value;
        match1 result1;
        match2 result2;
        ...
    }
    

    其中 $source_variable 是源变量,$result_variable 是目标变量,match 是匹配条件,result 是对应的值。

  • map_hash_bucket_size: 设置映射表的桶大小,默认是 64 或 128 字节。如果映射表过大,可能需要调整此参数以避免内存不足错误。

  • map_hash_max_size: 设置映射表的最大尺寸,默认是 2048。如果映射表过大,可以增加此值以容纳更多的条目。

使用示例

以下是一些具体的配置示例,展示了如何使用 ngx_http_map_module 来实现不同的映射需求:

根据请求头设置变量

假设你想根据请求头 User-Agent 的值来设置一个变量 $is_mobile,以区分移动设备和桌面设备:

http {
    # 根据 User-Agent 头设置 is_mobile 变量
    map $http_user_agent $is_mobile {
        default 0;
        "~*iphone" 1;
        "~*android" 1;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            # 根据 is_mobile 变量选择不同的根目录
            if ($is_mobile) {
                set $root_path /var/www/mobile;
            }
            if ($is_mobile = 0) {
                set $root_path /var/www/desktop;
            }

            root $root_path;
            index index.html;
        }
    }
}

在这个例子中:

  • map $http_user_agent $is_mobile 根据 User-Agent 请求头的内容设置 $is_mobile 变量。如果包含 iphoneandroid,则将其设置为 1,否则设置为 0
  • location / 块中,根据 $is_mobile 变量的值选择不同的根目录。

根据 URI 参数设置变量

假设你想根据请求 URI 中的参数 lang 来设置语言变量 lang_code

http {
    # 根据 URI 参数 lang 设置 lang_code 变量
    map $arg_lang $lang_code {
        default "en";
        "zh" "zh-CN";
        "fr" "fr-FR";
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            # 使用 lang_code 变量设置 Content-Language 头
            add_header Content-Language $lang_code;

            # 根目录设置
            root /var/www/html;
            index index.html;
        }
    }
}

在这个例子中:

  • map $arg_lang $lang_code 根据 URI 参数 lang 的值设置 $lang_code 变量。如果没有提供 lang 参数或其值不在映射表中,则默认为 "en"
  • location / 块中,使用 $lang_code 变量设置响应头 Content-Language

注意事项

  • 性能优化:映射表在配置加载时会被编译为哈希表,因此在运行时查找非常高效。然而,如果映射表过大,可能会导致内存不足问题。可以通过调整 map_hash_bucket_sizemap_hash_max_size 来优化性能。
  • 正则表达式匹配:当使用正则表达式进行匹配时,确保正则表达式的编写正确且高效。复杂的正则表达式可能会影响性能。
  • 测试验证:在部署之前进行全面测试,确保所有配置按预期工作,并检查是否有任何潜在的问题(如映射不准确、逻辑错误等)。
2.32.1 指令列表
map

map 指令用于创建变量映射表,根据输入变量的值动态设置另一个变量的值。这对于条件路由、请求头修改等非常有用。

Syntax:	map string $variable { ... }
Default:	—
Context:	http
  • string:定义映射表的输入变量或字符串。
  • $variable:定义映射表输出的目标变量。

案例

基本用法

假设我们希望根据用户代理(User-Agent)设置一个变量 $device_type,并将其值设为 mobiledesktop

http {
    map $http_user_agent $device_type {
        default "desktop";
        "~*iphone|android" "mobile";
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            add_header X-Device-Type $device_type;
            proxy_pass http://backend;
        }
    }
}

在这个例子中:

  • 如果用户代理包含 iphoneandroid,则 $device_type 被设置为 mobile
  • 否则,默认情况下 $device_type 被设置为 desktop

复杂映射

我们可以创建更复杂的映射表,例如根据请求路径设置不同的响应头:

http {
    map $request_uri $custom_header {
        default "default_value";
        ~*/api/ "api_value";
        ~*/static/ "static_value";
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            add_header X-Custom-Header $custom_header;
            proxy_pass http://backend;
        }
    }
}

在这个例子中:

  • 如果请求路径包含 /api/,则 $custom_header 被设置为 api_value
  • 如果请求路径包含 /static/,则 $custom_header 被设置为 static_value
  • 否则,默认情况下 $custom_header 被设置为 default_value

注意事项

  • 灵活性map 提供了极大的灵活性,可以根据各种条件动态设置变量。
  • 维护性:保持映射表的简洁和易维护性,避免过于复杂的嵌套结构。
map_hash_bucket_size

map_hash_bucket_size 指令用于设置哈希表桶的大小,以优化 map 指令生成的哈希表的性能。

Syntax:	map_hash_bucket_size size;
Default:	map_hash_bucket_size 32|64|128;
Context:	http
  • size:指定哈希表桶的大小,单位是字节。常见的值包括32、64和128字节。

案例

基本用法

假设我们希望将哈希表桶的大小设置为64字节:

http {
    map_hash_bucket_size 64;

    map $http_user_agent $device_type {
        default "desktop";
        "~*iphone|android" "mobile";
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            add_header X-Device-Type $device_type;
            proxy_pass http://backend;
        }
    }
}

注意事项

  • 性能优化:合理的桶大小可以提高哈希表查找效率,尤其是在大映射表的情况下。
  • 内存使用:较大的桶大小会增加内存使用,因此需要根据实际情况进行调整。
map_hash_max_size

map_hash_max_size 指令用于设置哈希表的最大尺寸,以优化 map 指令生成的哈希表的性能。

Syntax:	map_hash_max_size size;
Default:	map_hash_max_size 2048;
Context:	http
  • size:指定哈希表的最大尺寸,通常是一个较大的数值。

案例

基本用法

假设我们希望将哈希表的最大尺寸设置为4096:

http {
    map_hash_max_size 4096;
    map_hash_bucket_size 64;

    map $http_user_agent $device_type {
        default "desktop";
        "~*iphone|android" "mobile";
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            add_header X-Device-Type $device_type;
            proxy_pass http://backend;
        }
    }
}

注意事项

  • 性能优化:较大的哈希表尺寸可以减少冲突,提高查找效率。
  • 内存使用:较大的哈希表尺寸会增加内存使用,因此需要根据实际情况进行调整。

2.33 ngx_http_memcached_module

ngx_http_memcached_module 是 Nginx 的一个模块,它允许你从 Memcached 缓存服务器中获取数据。这个模块可以显著提高响应速度,特别是在高并发场景下,通过减少对后端服务器的请求来减轻其负载。

主要功能

  • 缓存读取:直接从 Memcached 服务器读取数据,并将其作为响应返回给客户端。
  • 灵活配置:支持多种方式指定 Memcached 键值,以及在不同上下文中应用缓存逻辑。

常用指令

以下是与 ngx_http_memcached_module 模块相关的常用配置指令及其简要说明:

  • memcached_pass:指定 Memcached 服务器的地址和端口,或使用 Unix 域套接字路径。

  • set:设置 Memcached 中的键值对(通常用于写入操作,但该模块主要关注读取)。

  • memcached_key:定义用于查找 Memcached 数据的键。可以通过变量动态生成键值。

  • error_page:处理 Memcached 未命中或错误的情况,例如将请求转发给后端服务器。

使用示例

以下是一些具体的配置示例,展示如何利用 ngx_http_memcached_module 来从 Memcached 获取数据。

基本配置

假设你想从 Memcached 服务器中获取静态页面数据,并在未命中时回退到后端服务器:

  1. 配置 Memcached 服务器:

    http {
        upstream memcached_backend {
            server 127.0.0.1:11211;
            keepalive 32;
        }
    
        server {
            listen 80;
            server_name example.com;
    
            location / {
                # 定义 Memcached 键值,这里使用请求 URI 作为键
                set $memcached_key $request_uri;
                
                # 将请求转发到 Memcached 服务器
                memcached_pass memcached_backend;
    
                # 如果 Memcached 未命中或发生错误,返回 404 或者重定向到后端服务器
                error_page 404 = @fallback;
            }
    
            location @fallback {
                # 回退到后端服务器处理请求
                proxy_pass http://backend_server;
            }
        }
    }
    

在这个例子中:

  • upstream memcached_backend 定义了一个 Memcached 服务器池,默认情况下只有一个 Memcached 实例。
  • set $memcached_key $request_uri; 使用请求的 URI 作为 Memcached 键。
  • memcached_pass memcached_backend; 将请求转发给 Memcached 服务器。
  • error_page 404 = @fallback; 当 Memcached 未命中或发生错误时,将请求转发给名为 @fallback 的位置块进行处理。
  • location @fallback 定义了当 Memcached 未命中时的回退机制,将请求转发给后端服务器。

动态键值

你可以根据不同的条件动态生成 Memcached 键值。例如,基于用户会话信息或请求参数:

http {
    upstream memcached_backend {
        server 127.0.0.1:11211;
        keepalive 32;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            # 根据请求参数动态生成 Memcached 键值
            set $memcached_key "prefix:$arg_session_id";
            
            memcached_pass memcached_backend;

            error_page 404 = @fallback;
        }

        location @fallback {
            proxy_pass http://backend_server;
        }
    }
}

在这个例子中:

  • set $memcached_key "prefix:$arg_session_id"; 使用请求参数 session_id 作为 Memcached 键的一部分,确保每个用户的会话都有独立的缓存。

处理多个 Memcached 服务器

如果你有多个 Memcached 服务器,可以通过 upstream 指令进行负载均衡:

http {
    upstream memcached_backend {
        server 192.168.1.1:11211;
        server 192.168.1.2:11211;
        keepalive 32;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            set $memcached_key $request_uri;
            
            memcached_pass memcached_backend;

            error_page 404 = @fallback;
        }

        location @fallback {
            proxy_pass http://backend_server;
        }
    }
}

在这个例子中:

  • upstream memcached_backend 定义了两个 Memcached 服务器实例,Nginx 会在这两个服务器之间进行负载均衡。

设置缓存过期时间

虽然 ngx_http_memcached_module 主要用于读取缓存,但你可以结合其他模块(如 proxy_cache)来设置缓存过期时间。不过,Memcached 本身也支持设置过期时间,你可以在插入缓存时指定:

# 示例代码(需要在应用层插入缓存时设置过期时间)
$memcached->set($key, $data, 3600); // 数据在 Memcached 中保留 3600 秒

在 Nginx 配置中,无法直接设置 Memcached 中的数据过期时间,因此你需要在应用层(如 PHP、Python 等)中处理这一点。

注意事项

  • 性能考虑

    • 确保 Memcached 服务器有足够的内存和处理能力来应对高并发请求。
    • 使用 keepalive 参数保持连接池,以减少每次请求建立新连接的开销。
  • 安全性

    • 确保 Memcached 服务器的安全性,避免未经授权的访问。可以通过防火墙或其他安全措施限制访问来源。
    • 对缓存中的敏感数据进行加密存储和传输。
  • 日志记录

    • 合理配置日志级别和格式,便于监控和故障排查。特别是注意记录缓存未命中和错误情况的日志。
  • 缓存一致性

    • 确保缓存数据的一致性,特别是在数据更新频繁的情况下。可以结合 TTL(Time To Live)等机制来管理缓存的有效期。
2.33.1 指令列表
memcached_bind

memcached_bind 指令用于指定 Memcached 服务器绑定的地址和可选的透明模式。这使得 Nginx 可以通过特定的网络接口与 Memcached 服务器通信。

Syntax:	memcached_bind address [transparent] | off;
Default: —
Context: http, server, location
This directive appeared in version 0.8.22.
  • address:要绑定的 IP 地址。
  • [transparent]:可选参数,启用透明模式,允许绑定到任意地址。
  • off:禁用绑定。

案例

基本用法

最简单的 memcached_bind 用法是指定一个绑定地址:

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

        location /memcached_example/ {
            # 绑定到特定的 IP 地址
            memcached_bind 192.168.1.10;

            # 其他配置
        }
    }
}

在这个例子中:

  • 当用户访问 /memcached_example/ 路径时,Nginx 将通过 IP 地址 192.168.1.10 与 Memcached 服务器通信。

使用透明模式

你可以启用透明模式来绑定到任意地址:

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

        location /transparent_memcached/ {
            # 启用透明模式并绑定到任意地址
            memcached_bind 192.168.1.10 transparent;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /transparent_memcached/ 路径时,Nginx 将通过透明模式绑定到 IP 地址 192.168.1.10,允许绑定到任意地址。

禁用绑定

你也可以选择禁用绑定:

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

        location /no_binding/ {
            # 禁用绑定
            memcached_bind off;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /no_binding/ 路径时,Nginx 不会绑定到任何特定地址,使用默认行为。

注意事项

  • 权限问题:透明模式通常需要较高的权限(如 root 权限),确保你的 Nginx 配置具有足够的权限来执行此操作。
  • 网络配置:确保绑定的地址在网络配置中是有效的,并且不会导致连接问题。
memcached_buffer_size

memcached_buffer_size 指令用于设置 Memcached 缓冲区的大小。这影响了 Nginx 与 Memcached 服务器之间数据传输的效率。

Syntax:	memcached_buffer_size size;
Default: memcached_buffer_size 4k|8k;
Context: http, server, location
  • size:缓冲区大小,默认值为 4k 或 8k,具体取决于系统配置。

案例

基本用法

最简单的 memcached_buffer_size 用法是指定缓冲区大小:

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

        location /memcached_example/ {
            # 设置 Memcached 缓冲区大小为 8k
            memcached_buffer_size 8k;

            # 其他配置
        }
    }
}

在这个例子中:

  • 当用户访问 /memcached_example/ 路径时,Nginx 将使用 8k 的缓冲区与 Memcached 服务器通信。

自定义缓冲区大小

你可以根据需要调整缓冲区大小:

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

        location /large_buffer/ {
            # 设置较大的缓冲区大小为 16k
            memcached_buffer_size 16k;

            # 其他配置
        }

        location /small_buffer/ {
            # 设置较小的缓冲区大小为 2k
            memcached_buffer_size 2k;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /large_buffer/ 路径时,Nginx 将使用 16k 的缓冲区与 Memcached 服务器通信。
  • 访问 /small_buffer/ 路径时,Nginx 将使用 2k 的缓冲区与 Memcached 服务器通信。

注意事项

  • 性能优化:较大的缓冲区可以减少数据传输次数,但会占用更多内存。需根据实际需求进行调整。
  • 内存管理:确保有足够的内存来支持设定的缓冲区大小,特别是在高并发场景下。
memcached_connect_timeout

memcached_connect_timeout 指令用于设置与 Memcached 服务器建立连接的超时时间。这有助于防止长时间等待无效或不可达的 Memcached 服务器。

Syntax:	memcached_connect_timeout time;
Default: memcached_connect_timeout 60s;
Context: http, server, location
  • time:超时时间,默认值为 60 秒。

案例

基本用法

最简单的 memcached_connect_timeout 用法是指定超时时间:

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

        location /memcached_example/ {
            # 设置连接超时时间为 30 秒
            memcached_connect_timeout 30s;

            # 其他配置
        }
    }
}

在这个例子中:

  • 当用户访问 /memcached_example/ 路径时,Nginx 将在 30 秒内尝试与 Memcached 服务器建立连接。如果超时,则放弃连接。

自定义超时时间

你可以根据需要调整超时时间:

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

        location /short_timeout/ {
            # 设置较短的连接超时时间为 10 秒
            memcached_connect_timeout 10s;

            # 其他配置
        }

        location /long_timeout/ {
            # 设置较长的连接超时时间为 120 秒
            memcached_connect_timeout 120s;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /short_timeout/ 路径时,Nginx 将在 10 秒内尝试与 Memcached 服务器建立连接。
  • 访问 /long_timeout/ 路径时,Nginx 将在 120 秒内尝试与 Memcached 服务器建立连接。

注意事项

  • 超时设置:较短的超时时间可以快速响应失败情况,但可能导致频繁的重试;较长的超时时间可以提高连接成功率,但可能增加延迟。
  • 错误处理:确保在超时情况下有适当的错误处理机制,以避免用户体验受到影响。
memcached_gzip_flag

memcached_gzip_flag 指令用于设置 Memcached 存储的数据是否经过 gzip 压缩的标志位。这使得 Nginx 可以识别和处理压缩的数据。

Syntax:	memcached_gzip_flag flag;
Default: —
Context: http, server, location
This directive appeared in version 1.3.6.
  • flag:标识数据是否经过 gzip 压缩的标志位。

案例

基本用法

最简单的 memcached_gzip_flag 用法是指定标志位:

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

        location /memcached_gzip_example/ {
            # 设置 gzip 标志位为 1
            memcached_gzip_flag 1;

            # 其他配置
        }
    }
}

在这个例子中:

  • 当用户访问 /memcached_gzip_example/ 路径时,Nginx 将检查存储在 Memcached 中的数据是否有 gzip 标志位 1,如果有,则认为数据是经过 gzip 压缩的。

使用不同的标志位

你可以根据需要设置不同的标志位:

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

        location /gzip_compressed_data/ {
            # 设置 gzip 标志位为 7
            memcached_gzip_flag 7;

            # 其他配置
        }

        location /plain_data/ {
            # 设置 gzip 标志位为 0(表示未压缩)
            memcached_gzip_flag 0;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /gzip_compressed_data/ 路径时,Nginx 将检查存储在 Memcached 中的数据是否有 gzip 标志位 7,如果有,则认为数据是经过 gzip 压缩的。
  • 访问 /plain_data/ 路径时,Nginx 将检查存储在 Memcached 中的数据是否有 gzip 标志位 0,如果没有,则认为数据是未压缩的。

注意事项

  • 一致性:确保在存储和读取数据时使用相同的 gzip 标志位,以避免混淆和错误处理。
  • 性能考虑:虽然 gzip 压缩可以减少存储空间,但在高并发场景下可能会增加 CPU 负载。需权衡压缩带来的好处和性能开销。
memcached_next_upstream

memcached_next_upstream 用于定义在何种情况下将请求传递给下一个 Memcached 服务器。这有助于提高系统的容错能力和可靠性,尤其是在 Memcached 集群环境中。

Syntax:	memcached_next_upstream error | timeout | invalid_response | not_found | off ...;
Default: memcached_next_upstream error timeout;
Context: http, server, location
  • error:当与 Memcached 服务器的连接发生错误时,尝试下一个服务器。
  • timeout:当与 Memcached 服务器的连接超时时,尝试下一个服务器。
  • invalid_response:当从 Memcached 服务器接收到无效响应时,尝试下一个服务器。
  • not_found:当 Memcached 服务器返回未找到(NOT_FOUND)响应时,尝试下一个服务器。
  • off:禁用尝试下一个服务器的功能。

案例

基本用法

最简单的 memcached_next_upstream 用法是指定哪些情况会触发尝试下一个服务器:

server {
    listen 80;
    server_name example.com;

    location /memcached/ {
        memcached_pass 127.0.0.1:11211;
        memcached_next_upstream error timeout;  # 默认行为,仅在发生错误或超时时尝试下一个服务器
    }
}

在这个例子中,设置了 memcached_next_upstream error timeout,这意味着 Nginx 将在发生错误或超时时尝试下一个 Memcached 服务器。

调整触发条件

根据实际需求调整触发尝试下一个服务器的条件:

server {
    listen 80;
    server_name example.com;

    upstream memcached_servers {
        server 192.168.1.10:11211;
        server 192.168.1.11:11211;
    }

    location /strict_memcached/ {
        memcached_pass memcached_servers;
        memcached_next_upstream error timeout invalid_response;  # 在更多情况下尝试下一个服务器
    }

    location /lenient_memcached/ {
        memcached_pass memcached_servers;
        memcached_next_upstream not_found;  # 仅在未找到数据时尝试下一个服务器
    }
}

在这个例子中:

  • 对于 /strict_memcached/ 路径下的请求,在发生错误、超时或接收到无效响应时,尝试下一个 Memcached 服务器。
  • 对于 /lenient_memcached/ 路径下的请求,仅在未找到数据时尝试下一个 Memcached 服务器。

注意事项

  • 故障转移策略:合理配置触发条件可以提高系统的容错能力,但过多的重试可能会增加延迟。
  • 性能优化:确保上游 Memcached 服务器的健康状态,避免不必要的重试。
memcached_next_upstream_timeout

memcached_next_upstream_timeout 用于设置尝试下一个 Memcached 服务器的超时时间。这有助于控制重试的时间窗口,以避免长时间等待。

Syntax:	memcached_next_upstream_timeout time;
Default: memcached_next_upstream_timeout 0;
Context: http, server, location
This directive appeared in version 1.7.5.
  • time:指定超时时间,默认为 0(表示没有超时限制)。

案例

基本用法

最简单的 memcached_next_upstream_timeout 用法是指定尝试下一个服务器的超时时间:

server {
    listen 80;
    server_name example.com;

    location /memcached/ {
        memcached_pass 127.0.0.1:11211;
        memcached_next_upstream error timeout;
        memcached_next_upstream_timeout 1s;  # 设置超时时间为 1 秒
    }
}

在这个例子中,设置了 memcached_next_upstream_timeout 1s,这意味着 Nginx 将在尝试下一个 Memcached 服务器时最多等待 1 秒。

调整超时时间

根据实际需求调整尝试下一个服务器的超时时间:

server {
    listen 80;
    server_name example.com;

    upstream memcached_servers {
        server 192.168.1.10:11211;
        server 192.168.1.11:11211;
    }

    location /fast_retry_memcached/ {
        memcached_pass memcached_servers;
        memcached_next_upstream error timeout;
        memcached_next_upstream_timeout 500ms;  # 设置较短的超时时间,适用于快速响应场景
    }

    location /slow_retry_memcached/ {
        memcached_pass memcached_servers;
        memcached_next_upstream error timeout;
        memcached_next_upstream_timeout 3s;  # 设置较长的超时时间,适用于慢速响应场景
    }
}

在这个例子中:

  • 对于 /fast_retry_memcached/ 路径下的请求,设置了较短的超时时间(500 毫秒),适用于需要快速响应的场景。
  • 对于 /slow_retry_memcached/ 路径下的请求,设置了较长的超时时间(3 秒),适用于允许较长等待时间的场景。

注意事项

  • 响应时间:合理的超时时间可以平衡响应速度和可靠性,过短的超时可能导致频繁失败,过长的超时可能增加延迟。
  • 负载均衡:结合其他负载均衡配置,如 upstreamkeepalive,以优化整体性能。
memcached_next_upstream_tries

memcached_next_upstream_tries 用于设置尝试下一个 Memcached 服务器的最大次数。这有助于控制重试次数,避免无限重试。

Syntax:	memcached_next_upstream_tries number;
Default: memcached_next_upstream_tries 0;
Context: http, server, location
This directive appeared in version 1.7.5.
  • number:指定最大重试次数,默认为 0(表示不限制重试次数)。

案例

基本用法

最简单的 memcached_next_upstream_tries 用法是指定尝试下一个服务器的最大次数:

server {
    listen 80;
    server_name example.com;

    location /memcached/ {
        memcached_pass 127.0.0.1:11211;
        memcached_next_upstream error timeout;
        memcached_next_upstream_tries 2;  # 最多尝试 2 次
    }
}

在这个例子中,设置了 memcached_next_upstream_tries 2,这意味着 Nginx 在遇到错误或超时时最多尝试 2 次下一个 Memcached 服务器。

调整重试次数

根据实际需求调整尝试下一个服务器的最大次数:

server {
    listen 80;
    server_name example.com;

    upstream memcached_servers {
        server 192.168.1.10:11211;
        server 192.168.1.11:11211;
    }

    location /limited_retry_memcached/ {
        memcached_pass memcached_servers;
        memcached_next_upstream error timeout;
        memcached_next_upstream_tries 3;  # 最多尝试 3 次,适用于高可用性要求的场景
    }

    location /no_retry_memcached/ {
        memcached_pass memcached_servers;
        memcached_next_upstream error timeout;
        memcached_next_upstream_tries 1;  # 只尝试一次,适用于低延迟要求的场景
    }
}

在这个例子中:

  • 对于 /limited_retry_memcached/ 路径下的请求,设置了最多尝试 3 次,适用于对高可用性有较高要求的场景。
  • 对于 /no_retry_memcached/ 路径下的请求,只尝试一次,适用于对低延迟有较高要求的场景。

注意事项

  • 系统稳定性:合理的重试次数可以提高系统的稳定性和可靠性,但过多的重试可能会导致资源浪费。
  • 性能优化:结合其他指令,如 memcached_next_upstream_timeout,以优化整体性能。
memcached_pass

memcached_pass 用于指定 Memcached 服务器的地址,Nginx 将通过该地址与 Memcached 服务器进行交互。这个指令通常与 upstream 结合使用,以实现负载均衡和高可用性。

Syntax:	memcached_pass address;
Default: —
Context: location, if in location
  • address:Memcached 服务器的地址,可以是 IP 地址和端口号,也可以是一个定义好的 upstream 名称。

案例

基本用法

最简单的 memcached_pass 用法是指定 Memcached 服务器的地址:

server {
    listen 80;
    server_name example.com;

    location /memcached/ {
        memcached_pass 127.0.0.1:11211;  # 直接指定 Memcached 服务器的地址
    }
}

在这个例子中,指定了 Memcached 服务器的地址为 127.0.0.1:11211,这意味着 Nginx 将直接与该地址的 Memcached 服务器进行通信。

使用 upstream 实现负载均衡

结合 upstream 实现负载均衡和高可用性:

http {
    upstream memcached_backend {
        server 192.168.1.10:11211;
        server 192.168.1.11:11211;
        server 192.168.1.12:11211;
    }

    server {
        listen 80;
        server_name example.com;

        location /memcached_balanced/ {
            memcached_pass memcached_backend;  # 使用定义好的 upstream 进行负载均衡
            memcached_next_upstream error timeout;
            memcached_next_upstream_tries 2;
            memcached_next_upstream_timeout 1s;
        }
    }
}

在这个例子中:

  • 定义了一个名为 memcached_backendupstream,包含三个 Memcached 服务器。
  • /memcached_balanced/ 路径下,使用 memcached_pass memcached_backend 来实现负载均衡,并结合其他指令来控制重试行为。

注意事项

  • 负载均衡策略:可以通过 upstream 中的配置(如权重、备份服务器等)来进一步优化负载均衡策略。
  • 健康检查:结合健康检查机制,确保上游 Memcached 服务器的可用性,避免将请求发送到不可用的服务器。
memcached_read_timeout

memcached_read_timeout 指令用于设置从 Memcached 服务器读取数据的超时时间。这个指令帮助控制请求的响应时间,确保不会因为长时间等待而阻塞服务器资源。

Syntax:	memcached_read_timeout time;
Default:	memcached_read_timeout 60s;
Context:	http, server, location
  • time:指定超时时间,单位可以是秒(s)、毫秒(ms)等,默认值为 60s

案例

基本用法

最简单的 memcached_read_timeout 用法是指定一个具体的超时时间:

http {
    upstream memcached_backend {
        server 127.0.0.1:11211;
    }

    server {
        listen 80;
        server_name example.com;

        location /memcached/ {
            # 设置从 Memcached 读取数据的超时时间为 30 秒
            memcached_read_timeout 30s;

            memcached_pass memcached_backend;
        }
    }
}

在这个例子中:

  • 设置了 memcached_read_timeout 30s,这意味着Nginx将等待最多30秒来从Memcached服务器读取数据。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的超时时间:

server {
    listen 80;
    server_name example.com;

    location /fast_data/ {
        # 设置较短的读取超时时间,适合快速响应的服务
        memcached_read_timeout 10s;

        memcached_pass memcached_backend;
    }

    location /slow_data/ {
        # 设置较长的读取超时时间,适合需要更多处理时间的服务
        memcached_read_timeout 90s;

        memcached_pass memcached_backend;
    }
}

在这个例子中:

  • 对于 /fast_data/ 路径,设置了 memcached_read_timeout 10s,适合快速响应的服务。
  • 对于 /slow_data/ 路径,设置了 memcached_read_timeout 90s,适合需要更多处理时间的服务。

注意事项

  • 性能影响:较短的超时时间可以减少服务器资源的占用,但可能导致更多的请求失败。较长的超时时间则相反。根据实际应用场景选择合适的超时时间,以平衡响应时间和资源使用。
  • 适用场景:适用于需要通过Memcached进行缓存的应用场景。例如,在高并发应用、缓存系统等环境中使用。
  • 调试和监控:如果你遇到超时问题,可以检查以下几点:
    • 确保超时时间设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
memcached_send_timeout

memcached_send_timeout 指令用于设置向 Memcached 服务器发送数据的超时时间。这个指令帮助控制请求的响应时间,确保不会因为长时间等待而阻塞服务器资源。

Syntax:	memcached_send_timeout time;
Default:	memcached_send_timeout 60s;
Context:	http, server, location
  • time:指定超时时间,单位可以是秒(s)、毫秒(ms)等,默认值为 60s

案例

基本用法

最简单的 memcached_send_timeout 用法是指定一个具体的超时时间:

http {
    upstream memcached_backend {
        server 127.0.0.1:11211;
    }

    server {
        listen 80;
        server_name example.com;

        location /memcached/ {
            # 设置向 Memcached 发送数据的超时时间为 30 秒
            memcached_send_timeout 30s;

            memcached_pass memcached_backend;
        }
    }
}

在这个例子中:

  • 设置了 memcached_send_timeout 30s,这意味着Nginx将等待最多30秒来向Memcached服务器发送数据。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的超时时间:

server {
    listen 80;
    server_name example.com;

    location /small_data/ {
        # 设置较短的发送超时时间,适合小数据量的服务
        memcached_send_timeout 5s;

        memcached_pass memcached_backend;
    }

    location /large_data/ {
        # 设置较长的发送超时时间,适合大数据量的服务
        memcached_send_timeout 120s;

        memcached_pass memcached_backend;
    }
}

在这个例子中:

  • 对于 /small_data/ 路径,设置了 memcached_send_timeout 5s,适合小数据量的服务。
  • 对于 /large_data/ 路径,设置了 memcached_send_timeout 120s,适合大数据量的服务。

注意事项

  • 性能影响:较短的超时时间可以减少服务器资源的占用,但可能导致更多的请求失败。较长的超时时间则相反。根据实际应用场景选择合适的超时时间,以平衡响应时间和资源使用。
  • 适用场景:适用于需要通过Memcached进行缓存的应用场景。例如,在高并发应用、缓存系统等环境中使用。
  • 调试和监控:如果你遇到超时问题,可以检查以下几点:
    • 确保超时时间设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
memcached_socket_keepalive

memcached_socket_keepalive 指令用于启用或禁用与 Memcached 服务器之间的TCP连接保持活动状态的功能。这个指令有助于减少网络延迟和提高连接的稳定性。

Syntax:	memcached_socket_keepalive on | off;
Default:	memcached_socket_keepalive off;
Context:	http, server, location
This directive appeared in version 1.15.6.
  • on:启用TCP连接保持活动状态。
  • off:禁用TCP连接保持活动状态(默认值)。

案例

基本用法

最简单的 memcached_socket_keepalive 用法是指定是否启用TCP连接保持活动状态:

http {
    upstream memcached_backend {
        server 127.0.0.1:11211;
    }

    server {
        listen 80;
        server_name example.com;

        location /memcached/ {
            # 启用TCP连接保持活动状态
            memcached_socket_keepalive on;

            memcached_pass memcached_backend;
        }
    }
}

在这个例子中:

  • 设置了 memcached_socket_keepalive on,这意味着Nginx将启用与Memcached服务器之间的TCP连接保持活动状态。

动态设置不同配置

你可以根据不同的路径或条件动态设置是否启用TCP连接保持活动状态:

server {
    listen 80;
    server_name example.com;

    location /stable_connection/ {
        # 在需要稳定连接的路径上启用TCP连接保持活动状态
        memcached_socket_keepalive on;

        memcached_pass memcached_backend;
    }

    location /temporary_connection/ {
        # 在临时连接的路径上禁用TCP连接保持活动状态
        memcached_socket_keepalive off;

        memcached_pass memcached_backend;
    }
}

在这个例子中:

  • 对于 /stable_connection/ 路径,设置了 memcached_socket_keepalive on,适合需要稳定连接的场景。
  • 对于 /temporary_connection/ 路径,设置了 memcached_socket_keepalive off,适合临时连接的场景。

注意事项

  • 性能影响:启用TCP连接保持活动状态可以减少连接建立的时间和开销,但在某些情况下可能会增加服务器的负担。根据实际应用场景选择合适的设置。
  • 适用场景:适用于需要与Memcached服务器保持长期连接的应用场景。例如,在高并发应用、缓存系统等环境中使用。
  • 调试和监控:如果你遇到TCP连接保持活动状态问题,可以检查以下几点:
    • 确保TCP连接保持活动状态设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。

2.34 ngx_http_mirror_module

ngx_http_mirror_module 是 Nginx 的一个模块,用于实现请求镜像(mirroring)。通过这个模块,你可以将接收到的请求复制并发送到另一个服务器或一组服务器,而不会影响原始请求的处理。这在测试、调试和监控场景中非常有用,因为它允许你在不影响生产环境的情况下对请求进行分析或实验。

主要功能

  • 请求镜像:将接收到的请求复制并发送到指定的目标服务器。
  • 透明性:原始请求的处理不受镜像请求的影响,客户端不会感知到请求被镜像。
  • 灵活配置:可以为不同的 location 或 server 配置不同的镜像目标。

常用指令

  • mirror

  • 用途:定义镜像请求的目标 URI。通常在 location 块中使用。

  • 示例

    location /api/ {
        mirror /mirror;
    }
    
    location /mirror {
        internal;
        proxy_pass http://backend_mirror;
    }
    
  • mirror_request_body

  • 用途:控制是否镜像请求体。默认情况下,请求体也会被镜像。

  • 示例

    location /api/ {
        mirror /mirror;
        mirror_request_body off;  # 禁用请求体镜像
    }
    

使用示例

以下是一些简化的配置示例,展示了如何使用 ngx_http_mirror_module 来实现请求镜像。

基本请求镜像

假设你希望将所有对 /api/ 路径下的请求镜像到一个备用后端服务:

http {
    upstream backend_main {
        server 192.168.1.101:8080;
    }

    upstream backend_mirror {
        server 192.168.1.102:8080;
    }

    server {
        listen 80;
        server_name example.com;

        location /api/ {
            # 镜像请求到 /mirror
            mirror /mirror;

            # 处理原始请求
            proxy_pass http://backend_main;
        }

        location /mirror {
            # 内部位置,防止外部直接访问
            internal;

            # 将镜像请求代理到备用后端
            proxy_pass http://backend_mirror;
        }
    }
}

在这个例子中:

  • 当用户访问 http://example.com/api/resource 时,Nginx 会将该请求同时发送给 backend_mainbackend_mirror
  • mirror 指令指定了镜像请求的目标路径 /mirror
  • /mirror 被标记为内部位置(internal),防止外部直接访问,并代理到 backend_mirror

禁用请求体镜像

假设你希望只镜像请求头而不镜像请求体:

http {
    upstream backend_main {
        server 192.168.1.101:8080;
    }

    upstream backend_mirror {
        server 192.168.1.102:8080;
    }

    server {
        listen 80;
        server_name example.com;

        location /api/ {
            # 镜像请求到 /mirror
            mirror /mirror;

            # 禁用请求体镜像
            mirror_request_body off;

            # 处理原始请求
            proxy_pass http://backend_main;
        }

        location /mirror {
            # 内部位置,防止外部直接访问
            internal;

            # 将镜像请求代理到备用后端
            proxy_pass http://backend_mirror;
        }
    }
}

在这个例子中:

  • mirror_request_body off; 禁用了请求体的镜像,只有请求头会被镜像到 backend_mirror

条件镜像

假设你希望仅在特定条件下镜像请求,例如仅当请求包含某个特定头信息时:

http {
    upstream backend_main {
        server 192.168.1.101:8080;
    }

    upstream backend_mirror {
        server 192.168.1.102:8080;
    }

    map $http_x_mirror_request $should_mirror {
        default 0;
        "~^true$" 1;
    }

    server {
        listen 80;
        server_name example.com;

        location /api/ {
            if ($should_mirror) {
                mirror /mirror;
            }

            # 处理原始请求
            proxy_pass http://backend_main;
        }

        location /mirror {
            # 内部位置,防止外部直接访问
            internal;

            # 将镜像请求代理到备用后端
            proxy_pass http://backend_mirror;
        }
    }
}

在这个例子中:

  • map 指令根据请求头 X-Mirror-Request 的值设置 $should_mirror 变量。如果该头信息的值为 "true",则 $should_mirror 的值为 1,否则为 0。
  • location /api/ 中,使用 if 判断 $should_mirror 的值来决定是否启用镜像。

注意事项

  • 性能影响:虽然镜像请求是异步处理的,但仍然会对系统资源产生一定影响,尤其是在高并发环境中。确保你的服务器有足够的资源来处理额外的镜像请求。

    worker_processes auto;
    worker_connections 1024;
    
  • 日志记录:为了方便调试和监控,建议在镜像请求的目标服务器上启用详细的日志记录。

    access_log /var/log/nginx/mirror_access.log main;
    
  • 安全性:确保镜像请求的目标服务器的安全性,防止敏感数据泄露。可以通过限制访问或加密传输来增强安全性。

    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;
    
  • 避免滥用:不要过度使用镜像功能,特别是在生产环境中。镜像主要用于测试和调试目的,应谨慎使用。

2.34.1 指令列表
mirror

mirror 指令用于创建请求的镜像副本并将其发送到另一个URI。这个指令帮助实现请求的复制和转发,常用于日志记录、调试和流量分析等场景。

Syntax:	mirror uri | off;
Default:	mirror off;
Context:	http, server, location
  • uri:指定镜像请求的目标URI。
  • off:禁用镜像功能(默认值)。

案例

基本用法

最简单的 mirror 用法是指定一个目标URI来创建请求的镜像副本:

server {
    listen 80;
    server_name example.com;

    location /api/ {
        # 创建请求的镜像副本并发送到 /log_mirror
        mirror /log_mirror;

        proxy_pass http://backend_api;
    }

    location = /log_mirror {
        internal;
        proxy_pass http://logging_server;
    }
}

在这个例子中:

  • 设置了 mirror /log_mirror,这意味着Nginx将创建请求的镜像副本并将其发送到 /log_mirror URI。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的镜像目标:

server {
    listen 80;
    server_name example.com;

    location /api_v1/ {
        # 将API v1请求的镜像副本发送到专门的日志服务器
        mirror /v1_log_mirror;

        proxy_pass http://backend_v1;
    }

    location /api_v2/ {
        # 将API v2请求的镜像副本发送到另一个日志服务器
        mirror /v2_log_mirror;

        proxy_pass http://backend_v2;
    }

    location = /v1_log_mirror {
        internal;
        proxy_pass http://logging_server_v1;
    }

    location = /v2_log_mirror {
        internal;
        proxy_pass http://logging_server_v2;
    }
}

在这个例子中:

  • 对于 /api_v1/ 路径,设置了 mirror /v1_log_mirror,适合API v1请求。
  • 对于 /api_v2/ 路径,设置了 mirror /v2_log_mirror,适合API v2请求。

注意事项

  • 性能影响:镜像请求会增加额外的网络开销和服务器负载。根据实际应用场景选择合适的镜像策略,避免不必要的性能开销。
  • 适用场景:适用于需要记录或分析请求的应用场景。例如,在日志记录、流量分析、调试等环境中使用。
  • 调试和监控:如果你遇到镜像请求问题,可以检查以下几点:
    • 确保镜像目标URI设置正确,并且目标URI对应的配置有效。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
mirror_request_body

mirror_request_body 指令用于控制是否镜像请求体到镜像服务器。

Syntax:	mirror_request_body on | off;
Default:	mirror_request_body on;
Context:	http, server, location
  • on:启用请求体镜像。
  • off:禁用请求体镜像。

案例

基本用法

最简单的 mirror_request_body 用法是指定是否启用请求体镜像:

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

        location /api/ {
            # 启用请求体镜像
            mirror /mirror;
            mirror_request_body on;

            proxy_pass http://backend.example.com;
        }

        location /mirror {
            internal;
            proxy_pass http://mirror-server;
        }
    }
}

在这个例子中:

  • 当客户端请求 /api/ 路径时,请求体将被镜像到 mirror-server

禁用请求体镜像

你可以禁用请求体镜像:

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

        location /api/ {
            # 禁用请求体镜像
            mirror /mirror;
            mirror_request_body off;

            proxy_pass http://backend.example.com;
        }

        location /mirror {
            internal;
            proxy_pass http://mirror-server;
        }
    }
}

在这个例子中:

  • 请求体不会被镜像到 mirror-server

注意事项

  • 性能影响:镜像请求体会增加网络带宽和服务器负载,特别是在高并发场景下。根据实际需求合理使用此功能。
  • 调试和监控:如果你遇到请求体镜像问题,可以检查以下几点:
    • 确保镜像服务器路径正确,并且服务器有权限接收镜像请求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。

2.35 ngx_http_mp4_module

ngx_http_mp4_module 是 Nginx 的一个模块,用于提供对 MP4 文件的高效流媒体支持。这个模块允许你从 MP4 文件的任意位置开始播放,并支持拖动进度条进行快进或快退操作。这对于视频点播服务非常有用,因为它可以显著改善用户体验。

主要功能

  • 随机访问:支持从 MP4 文件的任意时间点开始播放。
  • 范围请求处理:处理 HTTP 范围请求,使得客户端可以从文件的特定位置开始下载。
  • 带宽自适应:可以根据客户端的网络状况动态调整传输速率(需要配合其他技术如 HLS 或 DASH)。

常用指令

以下是 ngx_http_mp4_module 中一些常用的指令及其说明:

  • mp4: 启用 MP4 流媒体支持。通常在 location 块中使用。

    location /videos/ {
        mp4;
    }
    
  • mp4_buffer_size: 设置用于读取 MP4 文件的缓冲区大小,默认为 512K。较大的缓冲区可以提高性能,但会增加内存使用量。

  • mp4_max_buffer_size: 设置最大缓冲区大小,默认为 10M。如果文件较大,可能需要调整此值。

  • mp4_start_key_frame: 控制是否从关键帧开始播放,默认为开启。开启后可以确保视频播放时画面质量不受影响。

  • mp4_limit_rate: 设置视频流的最大比特率(bps),可用于控制客户端的下载速度,避免过载。

使用示例

以下是一个简单的配置示例,展示了如何使用 ngx_http_mp4_module 来提供 MP4 视频流媒体服务:

server {
    listen 80;
    server_name example.com;

    location /videos/ {
        # 启用 MP4 流媒体支持
        mp4;

        # 设置缓冲区大小
        mp4_buffer_size 1m;
        mp4_max_buffer_size 10m;

        # 设置最大比特率以限制下载速度
        mp4_limit_rate 500k;

        # 根目录设置
        root /var/www/videos;

        # 可选:设置日志级别
        mp4_limit_rate_after 60s;
    }
}

在这个例子中:

  • mp4; 启用了 MP4 流媒体支持,这意味着当用户访问 /videos/ 目录下的 MP4 文件时,Nginx 将支持从任意时间点开始播放。
  • mp4_buffer_size 1m;mp4_max_buffer_size 10m; 设置了读取 MP4 文件的缓冲区大小,以优化性能和内存使用。
  • mp4_limit_rate 500k; 设置了最大比特率为 500kbps,这可以帮助控制客户端的下载速度,避免服务器过载。
  • root /var/www/videos; 指定了存放 MP4 文件的根目录。

高级功能

动态时间偏移

你可以通过 URL 参数来指定从哪个时间点开始播放视频。例如,假设你的 MP4 文件名为 movie.mp4,可以通过以下 URL 访问并从第 60 秒开始播放:

http://example.com/videos/movie.mp4?start=60

Nginx 会自动处理这个请求,并从指定的时间点开始传输视频数据。

处理大文件

对于较大的 MP4 文件,建议适当调整缓冲区大小以确保性能:

location /large_videos/ {
    mp4;
    mp4_buffer_size 2m;
    mp4_max_buffer_size 20m;
    root /var/www/large_videos;
}

注意事项

  • 文件格式要求:为了确保最佳的流媒体体验,MP4 文件应包含 moov atom(元数据)位于文件开头。可以使用工具如 ffmpeg 来重新组织 MP4 文件:

    ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4
    

    这将把 moov atom 移动到文件开头,从而允许更快地开始播放。

  • 缓存和 CDN:为了进一步提升性能,建议结合使用缓存机制(如 proxy_cache)和内容分发网络(CDN)。这样可以减少服务器负载,并加快全球用户的访问速度。

  • 测试验证:在部署之前进行全面测试,确保所有配置按预期工作,并检查是否有任何潜在的问题(如播放卡顿、无法跳转等)。

2.35.1 指令列表
mp4

mp4 指令用于启用对 MP4 文件的伪流式传输支持。

Syntax:	mp4;
Default:	—
Context:	location

案例

基本用法

最简单的 mp4 用法是启用 MP4 伪流式传输:

server {
    listen 80;
    server_name example.com;

    location /videos/ {
        # 启用 MP4 伪流式传输
        mp4;

        root /var/www/videos;
    }
}

在这个例子中:

  • 当用户请求 /videos/ 路径下的 MP4 文件时,Nginx 将启用伪流式传输支持。

注意事项

  • 文件格式:确保所有要传输的 MP4 文件都符合伪流式传输的要求(例如,包含 moov atom)。
  • 性能优化:对于大文件和高并发场景,考虑调整缓冲区大小以优化性能。
  • 调试和监控:如果你遇到 MP4 伪流式传输问题,可以检查以下几点:
    • 确保文件路径正确,并且文件可访问。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
mp4_buffer_size

mp4_buffer_size 指令用于设置 MP4 文件伪流式传输的初始缓冲区大小。

Syntax:	mp4_buffer_size size;
Default:	mp4_buffer_size 512K;
Context:	http, server, location
  • size:指定初始缓冲区大小,默认值为 512K

案例

基本用法

最简单的 mp4_buffer_size 用法是指定一个特定的缓冲区大小:

server {
    listen 80;
    server_name example.com;

    location /videos/ {
        # 启用 MP4 伪流式传输并设置缓冲区大小
        mp4;
        mp4_buffer_size 1M;

        root /var/www/videos;
    }
}

在这个例子中:

  • 初始缓冲区大小设置为 1M,这意味着 Nginx 将使用 1MB 的缓冲区来处理 MP4 文件。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的缓冲区大小:

server {
    listen 80;
    server_name example.com;

    location /small_videos/ {
        # 设置较小的 MP4 缓冲区大小,适合小视频
        mp4;
        mp4_buffer_size 256K;

        root /var/www/small_videos;
    }

    location /large_videos/ {
        # 设置较大的 MP4 缓冲区大小,适合大视频
        mp4;
        mp4_buffer_size 2M;

        root /var/www/large_videos;
    }
}

在这个例子中:

  • 对于 /small_videos/ 路径,设置了 mp4_buffer_size 256K,适合小视频。
  • 对于 /large_videos/ 路径,设置了 mp4_buffer_size 2M,适合大视频。

注意事项

  • 性能影响:较大的缓冲区可以提高大文件的读取效率,但会占用更多的内存资源。较小的缓冲区则相反。根据实际应用场景选择合适的缓冲区大小,以平衡内存使用和读取效率。
  • 适用场景:适用于需要处理大视频文件并通过伪流式传输的应用场景。例如,在视频点播平台、在线教育网站等环境中使用。
  • 调试和监控:如果你遇到 MP4 缓冲区大小问题,可以检查以下几点:
    • 确保缓冲区大小设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
mp4_max_buffer_size

mp4_max_buffer_size 指令用于设置 MP4 文件伪流式传输的最大缓冲区大小。

Syntax:	mp4_max_buffer_size size;
Default:	mp4_max_buffer_size 10M;
Context:	http, server, location
  • size:指定最大缓冲区大小,默认值为 10M

案例

基本用法

最简单的 mp4_max_buffer_size 用法是指定一个特定的最大缓冲区大小:

server {
    listen 80;
    server_name example.com;

    location /videos/ {
        # 启用 MP4 伪流式传输并设置最大缓冲区大小
        mp4;
        mp4_max_buffer_size 20M;

        root /var/www/videos;
    }
}

在这个例子中:

  • 最大缓冲区大小设置为 20M,这意味着 Nginx 将使用最多 20MB 的缓冲区来处理 MP4 文件。

动态设置不同配置

你可以根据不同的路径或条件动态设置不同的最大缓冲区大小:

server {
    listen 80;
    server_name example.com;

    location /small_videos/ {
        # 设置较小的 MP4 最大缓冲区大小,适合小视频
        mp4;
        mp4_max_buffer_size 5M;

        root /var/www/small_videos;
    }

    location /large_videos/ {
        # 设置较大的 MP4 最大缓冲区大小,适合大视频
        mp4;
        mp4_max_buffer_size 30M;

        root /var/www/large_videos;
    }
}

在这个例子中:

  • 对于 /small_videos/ 路径,设置了 mp4_max_buffer_size 5M,适合小视频。
  • 对于 /large_videos/ 路径,设置了 mp4_max_buffer_size 30M,适合大视频。

注意事项

  • 性能影响:较大的最大缓冲区可以提高大文件的读取效率,但会占用更多的内存资源。较小的最大缓冲区则相反。根据实际应用场景选择合适的最大缓冲区大小,以平衡内存使用和读取效率。
  • 适用场景:适用于需要处理大视频文件并通过伪流式传输的应用场景。例如,在视频点播平台、在线教育网站等环境中使用。
  • 调试和监控:如果你遇到 MP4 最大缓冲区大小问题,可以检查以下几点:
    • 确保最大缓冲区大小设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
mp4_limit_rate

mp4_limit_rate 指令用于控制MP4视频流的传输速率,以防止客户端因过快下载而导致服务器负载过高或带宽占用过多。这对于优化视频流媒体服务非常有用。

Syntax:	mp4_limit_rate on | off | factor;
Default:	mp4_limit_rate off;
Context:	http, server, location
  • on:启用限速功能,并使用默认的限速因子。
  • off(默认):禁用限速功能。
  • factor:指定一个自定义的限速因子,数值越大,限速越严格。

案例

基本用法

假设我们希望启用MP4视频流的限速功能:

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

        location /videos/ {
            mp4;
            mp4_limit_rate on;  # 启用限速功能
        }
    }
}

使用自定义限速因子

如果我们希望设置一个更严格的限速因子:

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

        location /videos/ {
            mp4;
            mp4_limit_rate 2.5;  # 设置限速因子为2.5
        }
    }
}

禁用限速功能

如果我们不希望对视频流进行限速:

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

        location /videos/ {
            mp4;
            mp4_limit_rate off;  # 禁用限速功能
        }
    }
}

注意事项

  • 性能优化:合理设置限速因子可以平衡用户体验和服务器负载,避免因过快下载导致的服务器压力过大。
  • 用户体验:确保限速设置不会显著影响视频播放的流畅性。
mp4_limit_rate_after

mp4_limit_rate_after 指令用于设置在开始限制视频流传输速率之前允许下载的时长。这对于提供初始快速加载体验特别有用。

Syntax:	mp4_limit_rate_after time;
Default:	mp4_limit_rate_after 60s;
Context:	http, server, location
  • time:指定在开始限制速率之前允许下载的时间长度。常见的单位包括秒(s)、分钟(m)等。

案例

基本用法

假设我们希望在开始限制速率之前允许下载120秒的内容:

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

        location /videos/ {
            mp4;
            mp4_limit_rate on;
            mp4_limit_rate_after 120s;  # 在开始限速前允许下载120秒的内容
        }
    }
}

使用默认值

如果我们希望使用默认的60秒:

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

        location /videos/ {
            mp4;
            mp4_limit_rate on;
            # 默认情况下,mp4_limit_rate_after 是60秒
        }
    }
}

注意事项

  • 用户体验:较长的初始下载时间可以提供更好的启动体验,但可能会增加初始带宽消耗。
  • 资源管理:确保初始下载时间不会导致服务器资源过度消耗。
mp4_start_key_frame

mp4_start_key_frame 指令用于控制是否从关键帧开始播放MP4视频流。这对于确保视频流的无缝播放非常重要,特别是在跳转到特定时间点时。

Syntax:	mp4_start_key_frame on | off;
Default:	mp4_start_key_frame off;
Context:	http, server, location
This directive appeared in version 1.21.4.
  • on:启用从关键帧开始播放的功能。
  • off(默认):禁用从关键帧开始播放的功能。

基本用法

假设我们希望启用从关键帧开始播放的功能:

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

        location /videos/ {
            mp4;
            mp4_start_key_frame on;  # 启用从关键帧开始播放
        }
    }
}

禁用从关键帧开始播放

如果我们不希望从关键帧开始播放:

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

        location /videos/ {
            mp4;
            mp4_start_key_frame off;  # 禁用从关键帧开始播放
        }
    }
}

注意事项

  • 播放质量:从关键帧开始播放可以确保视频流的无缝性和稳定性,特别是在跳转到特定时间点时。
  • 性能影响:启用此功能可能会稍微增加服务器处理的复杂度,但在大多数情况下是值得的。

2.36 ngx_http_perl_module

ngx_http_perl_module 是 Nginx 的一个模块,它允许在 Nginx 配置中嵌入和执行 Perl 脚本。这个模块扩展了 Nginx 的功能,使得你可以在请求处理的不同阶段(如重写、访问控制、日志记录等)中使用 Perl 代码进行更复杂的逻辑处理。

主要功能

  • 动态处理:在 Nginx 请求处理的各个阶段执行 Perl 代码,实现更复杂的逻辑。
  • 灵活配置:通过 Perl 编写自定义的逻辑,而不仅仅依赖于 Nginx 的配置指令。
  • 增强功能:可以用于日志处理、请求重写、响应修改等多种场景。

常用指令

以下是与 ngx_http_perl_module 模块相关的常用配置指令及其简要说明:

  • perl_modules:指定包含 Perl 模块的目录路径。

  • perl_require:加载指定的 Perl 模块。

  • perl_set:设置一个 Nginx 变量,并将其值由 Perl 函数计算得出。

  • perl:在不同的请求处理阶段执行 Perl 代码。

使用示例

以下是一些具体的配置示例,展示如何利用 ngx_http_perl_module 来增强 Nginx 的功能。

基本配置

首先,确保你的 Nginx 已经编译并启用了 ngx_http_perl_module。你可以通过以下命令检查是否已启用该模块:

nginx -V 2>&1 | grep -- '--with-http_perl_module'

如果输出中包含 --with-http_perl_module,则表示已启用该模块。

设置变量

假设你想根据客户端的 IP 地址设置一个自定义变量,可以通过 Perl 实现:

  1. 创建一个 Perl 文件 example.pm,内容如下:

    # example.pm
    package Example;
    use strict;
    use warnings;
    
    sub get_custom_value {
        my ($r) = @_;
        my $ip = $r->connection->remote_addr;
        if ($ip =~ /^192\.168/) {
            return "internal";
        } else {
            return "external";
        }
    }
    
    1;
    
  2. 在 Nginx 配置中引用该 Perl 文件,并设置一个变量:

    http {
        perl_modules /path/to/perl/modules;
        perl_require example.pm;
    
        server {
            listen 80;
            server_name example.com;
    
            perl_set $custom_value 'Example::get_custom_value';
    
            location / {
                add_header X-Custom-Value $custom_value;
                proxy_pass http://backend;
            }
        }
    }
    

在这个例子中:

  • perl_modules /path/to/perl/modules; 指定了包含 Perl 模块的目录路径。
  • perl_require example.pm; 加载了名为 example.pm 的 Perl 模块。
  • perl_set $custom_value 'Example::get_custom_value'; 设置了一个名为 $custom_value 的 Nginx 变量,并将其值由 Perl 函数 Example::get_custom_value 计算得出。
  • add_header X-Custom-Value $custom_value; 将计算出的值添加到响应头中。

动态生成响应内容

你可以使用 perl 指令让 Perl 函数生成整个响应内容:

  1. 创建一个 Perl 文件 dynamic_response.pm,内容如下:

    # dynamic_response.pm
    package DynamicResponse;
    use strict;
    use warnings;
    
    sub generate_response {
        my ($r) = @_;
        $r->send_http_header("text/plain");
        $r->print("Hello from Perl in Nginx!");
        return OK;
    }
    
    1;
    
  2. 在 Nginx 配置中引用该 Perl 文件,并设置 perl

    http {
        perl_modules /path/to/perl/modules;
        perl_require dynamic_response.pm;
    
        server {
            listen 80;
            server_name example.com;
    
            location /perl-response {
                perl 'DynamicResponse::generate_response';
            }
        }
    }
    

在这个例子中:

  • 当用户访问 /perl-response 路径时,Nginx 会调用 DynamicResponse::generate_response 函数生成响应内容,并返回给客户端。

访问控制

你可以在访问阶段使用 Perl 代码进行访问控制:

  1. 创建一个 Perl 文件 access_control.pm,内容如下:

    # access_control.pm
    package AccessControl;
    use strict;
    use warnings;
    
    sub check_access {
        my ($r) = @_;
        my $ip = $r->connection->remote_addr;
        if ($ip =~ /^192\.168/) {
            return DECLINED;  # 允许访问
        } else {
            return HTTP_FORBIDDEN;  # 禁止访问
        }
    }
    
    1;
    
  2. 在 Nginx 配置中引用该 Perl 文件,并设置访问控制:

    http {
        perl_modules /path/to/perl/modules;
        perl_require access_control.pm;
    
        server {
            listen 80;
            server_name example.com;
    
            perl_access_handler 'AccessControl::check_access';
    
            location / {
                proxy_pass http://backend;
            }
        }
    }
    

在这个例子中:

  • perl_access_handler 'AccessControl::check_access'; 在访问阶段调用 AccessControl::check_access 函数,决定是否允许访问。
  • 如果客户端 IP 地址以 192.168 开头,则允许访问;否则禁止访问。

修改响应头和体

你可以使用 perl 指令在响应头和响应体过滤阶段执行 Perl 代码,修改响应内容:

  1. 创建一个 Perl 文件 modify_response.pm,内容如下:

    # modify_response.pm
    package ModifyResponse;
    use strict;
    use warnings;
    
    sub modify_headers {
        my ($r) = @_;
        $r->header_out('X-Custom-Header', 'Modified by Perl');
        return DECLINED;
    }
    
    sub modify_body {
        my ($r) = @_;
        my $content = $r->filter_register('MODIFY_BODY');
        while ($content->read(my $buf, 1024)) {
            $buf .= "\n";
            $content->write($buf);
        }
        $content->done();
        return OK;
    }
    
    1;
    
  2. 在 Nginx 配置中引用该 Perl 文件,并设置响应过滤:

    http {
        perl_modules /path/to/perl/modules;
        perl_require modify_response.pm;
    
        server {
            listen 80;
            server_name example.com;
    
            location / {
                proxy_pass http://backend;
    
                perl 'ModifyResponse::modify_headers';
                perl 'ModifyResponse::modify_body';
            }
        }
    }
    

在这个例子中:

  • perl 'ModifyResponse::modify_headers'; 在响应头过滤阶段调用 ModifyResponse::modify_headers 函数,修改响应头。
  • perl 'ModifyResponse::modify_body'; 在响应体过滤阶段调用 ModifyResponse::modify_body 函数,修改响应体内容。

注意事项

  • 性能考虑

    • Perl 代码的执行会影响性能,尤其是在高并发场景下。尽量保持 Perl 代码简洁高效。
    • 如果有大量复杂的业务逻辑,考虑将这些逻辑移到后端服务中处理。
  • 安全性

    • 确保 Perl 代码的安全性,避免引入潜在的安全漏洞。
    • 对输入数据进行适当的验证和清理,防止注入攻击。
  • 调试

    • 使用日志记录和调试工具来帮助排查问题。可以在 Perl 代码中使用 warn()error_log() 输出日志信息。
2.36.1 指令列表
perl

perl 指令用于在Nginx配置中嵌入Perl代码,以实现更复杂的逻辑和动态内容生成。这对于需要高度定制化功能的应用程序非常有用。

Syntax:	perl module::function|'sub { ... }';
Default:	—
Context:	location, limit_except
  • module::function:指定要执行的Perl模块中的函数。
  • sub { ... }:直接在配置文件中定义匿名子程序(即内联Perl代码块)。

案例

基本用法

假设我们有一个名为 MyModule 的Perl模块,并且该模块中有一个名为 handleRequest 的函数,我们可以这样配置:

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

        location /dynamic {
            perl MyModule::handleRequest;  # 执行 Perl 模块中的函数
        }
    }
}

内联Perl代码

如果希望直接在配置文件中定义Perl代码:

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

        location /dynamic {
            perl 'sub { 
                my $r = shift;
                $r->send_http_header("text/plain");
                $r->print("Hello, World!");
            }';  # 直接定义匿名子程序
        }
    }
}

在这个例子中,我们定义了一个匿名子程序,它发送HTTP头并打印 “Hello, World!”。

注意事项

  • 安全性:确保嵌入的Perl代码是安全的,避免引入潜在的安全漏洞。
  • 维护性:保持嵌入代码的简洁和易维护性,避免过于复杂的嵌套结构。
perl_modules

perl_modules 指令用于指定包含 Perl 模块的目录路径。这使得 Nginx 可以加载和使用这些模块中的函数和功能。

Syntax:	perl_modules path;
Default: —
Context: http
  • path:包含 Perl 模块的目录路径。

案例

基本用法

最简单的 perl_modules 用法是指定一个包含 Perl 模块的目录路径:

http {
    # 指定包含 Perl 模块的目录路径
    perl_modules /usr/local/nginx/perl;

    server {
        listen 80;
        server_name example.com;

        location /use_perl_module/ {
            # 使用 Perl 模块中的函数处理请求
            perl_set $my_variable MyModule::get_value;

            # 其他配置
        }
    }
}

在这个例子中:

  • Nginx 将从 /usr/local/nginx/perl 目录加载 Perl 模块,并可以在后续配置中使用这些模块中的函数。

注意事项

  • 路径正确性:确保指定的路径是正确的,并且该路径下的 Perl 模块文件具有适当的权限。
  • 模块依赖性:如果模块有依赖关系,确保所有依赖项都已安装并且可以被 Nginx 找到。
perl_require

perl_require 指令用于指定需要加载的 Perl 模块名称。这使得 Nginx 可以在启动时自动加载并初始化指定的模块。

Syntax:	perl_require module;
Default: —
Context: http
  • module:要加载的 Perl 模块名称。

案例

基本用法

最简单的 perl_require 用法是指定一个需要加载的 Perl 模块名称:

http {
    # 指定包含 Perl 模块的目录路径
    perl_modules /usr/local/nginx/perl;

    # 加载特定的 Perl 模块
    perl_require MyModule;

    server {
        listen 80;
        server_name example.com;

        location /use_required_module/ {
            # 使用 Perl 模块中的函数处理请求
            perl_set $my_variable MyModule::get_value;

            # 其他配置
        }
    }
}

在这个例子中:

  • Nginx 在启动时将加载名为 MyModule 的 Perl 模块,并可以在后续配置中使用该模块中的函数。

多个模块

你可以指定多个需要加载的模块:

http {
    # 指定包含 Perl 模块的目录路径
    perl_modules /usr/local/nginx/perl;

    # 加载多个 Perl 模块
    perl_require MyModule;
    perl_require AnotherModule;

    server {
        listen 80;
        server_name example.com;

        location /use_multiple_modules/ {
            # 使用第一个 Perl 模块中的函数处理请求
            perl_set $my_variable MyModule::get_value;

            # 使用第二个 Perl 模块中的函数处理请求
            perl_set $another_variable AnotherModule::get_another_value;

            # 其他配置
        }
    }
}

在这个例子中:

  • 访问 /use_multiple_modules/ 路径时,Nginx 将使用 MyModuleAnotherModule 中的函数来处理请求。

注意事项

  • 模块可用性:确保指定的模块存在于指定的路径中,并且没有语法错误或依赖问题。
  • 命名冲突:避免不同模块之间出现命名冲突,特别是在使用多个模块时。
perl_set

perl_set 指令用于定义一个 Nginx 变量,并将其值设置为由 Perl 模块中的函数或匿名子程序返回的结果。这使得可以在 Nginx 配置中动态生成变量值。

Syntax:	perl_set $variable module::function|'sub { ... }';
Default: —
Context: http
  • $variable:要定义的 Nginx 变量名。
  • module::function:Perl 模块中的函数名。
  • 'sub { ... }':匿名子程序(即内联 Perl 代码)。

案例

使用 Perl 模块中的函数

最简单的 perl_set 用法是使用 Perl 模块中的函数来设置变量值:

http {
    # 指定包含 Perl 模块的目录路径
    perl_modules /usr/local/nginx/perl;

    # 加载特定的 Perl 模块
    perl_require MyModule;

    server {
        listen 80;
        server_name example.com;

        # 定义变量并设置其值为 Perl 模块中的函数返回结果
        perl_set $dynamic_value MyModule::generate_value;

        location /use_perl_function/ {
            # 使用动态生成的变量值
            default_type text/plain;
            return 200 "The dynamic value is: $dynamic_value";
        }
    }
}

在这个例子中:

  • 当用户访问 /use_perl_function/ 路径时,Nginx 将调用 MyModule::generate_value 函数生成 $dynamic_value 的值,并将其返回给客户端。

使用匿名子程序

你也可以使用匿名子程序来设置变量值:

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

        # 定义变量并设置其值为匿名子程序返回结果
        perl_set $current_time 'sub { my ($r) = @_; return scalar localtime(); }';

        location /use_anonymous_subroutine/ {
            # 使用动态生成的变量值
            default_type text/plain;
            return 200 "The current time is: $current_time";
        }
    }
}

在这个例子中:

  • 访问 /use_anonymous_subroutine/ 路径时,Nginx 将调用匿名子程序生成 $current_time 的值,并将其返回给客户端。

注意事项

  • 性能影响:频繁调用复杂的 Perl 函数可能会对性能产生影响,特别是在高并发场景下。尽量保持函数简洁高效。
  • 错误处理:确保在 Perl 函数中正确处理错误,以避免意外行为或崩溃。
  • 安全性考虑:确保 Perl 函数不会暴露敏感信息或引入安全漏洞。

你可能感兴趣的:(nginx,nginx,http,运维)