优化 OpenResty 的性能

上代码,本站和众多站长用的都是类似的优化,大家可以根据自己的需求稍微改一改。


一、基础架构与配置优化

1. 进程模型与I/O优化

worker_processes auto;  # 自动匹配CPU核心数
worker_cpu_affinity auto;  # CPU亲和性,减少上下文切换
worker_rlimit_nofile 65535;  # 提升单进程文件描述符限制

events {
    worker_connections 16384;  # 高并发连接数
    use epoll;  # Linux下高性能I/O模型
    multi_accept on;  # 一次性接受所有连接
}

2. HTTP协议与传输优化

http {
    sendfile on;  # 零拷贝文件传输
    tcp_nopush on;  # 优化数据包发送(需配合sendfile)
    tcp_nodelay on;  # 禁用Nagle算法,降低延迟
    keepalive_timeout 65s;  # 长连接超时
    keepalive_requests 1000;  # 单个连接最大请求数
    client_body_buffer_size 128k;  # 请求体缓冲区
    client_max_body_size 100m;  # 最大请求体大小
    server_tokens off;  # 隐藏Nginx版本信息
}

3. 内核参数调优

修改/etc/sysctl.conf后执行sysctl -p生效:

fs.file-max = 1000000  # 系统级文件描述符限制
net.ipv4.tcp_tw_reuse = 1  # 复用TIME_WAIT连接
net.ipv4.tcp_keepalive_time = 600  # TCP保活时间
net.ipv4.tcp_fin_timeout = 30  # FIN_WAIT_2状态超时

二、Lua脚本与性能敏感操作

1. 内存与变量管理

-- 避免全局变量,使用局部变量
local re_find = ngx.re.find  -- 预编译正则表达式
local ok, err = re_find("pattern", "text", "jo")  -- 'j'标志启用缓存

-- 高效字符串拼接
local parts = {"a", "b", "c"}
local result = table.concat(parts)  -- 优于"a".."b".."c"

2. 模块化与响应时间监控

封装响应时间计算模块(timer.lua):

local timer = {}
function timer.get_execution_time(start_time, end_time)
    return string.format("%.2f", (end_time - start_time) * 1000)  -- 毫秒级
end
return timer

使用示例:

local timer = require "timer"
local start_time = ngx.now()
-- 业务逻辑
local end_time = ngx.now()
ngx.header["X-Execution-Time"] = timer.get_execution_time(start_time, end_time) .. "ms"

三、多级缓存与数据层优化

1. 共享内存缓存

http {
    lua_shared_dict cache 100m;  # 100MB共享内存
}

Lua 操作示例:

local cache = ngx.shared.cache
local value = cache:get("key")
if not value then
    value = generate_data()  -- 动态生成数据
    cache:set("key", value, 60)  -- 缓存60秒
end

2. Redis连接池与异步操作

local redis = require "resty.redis"
local red = redis:new()
red:set_timeouts(1000, 2000, 3000)  -- 连接/发送/读取超时(毫秒)
local ok, err = red:connect("127.0.0.1", 6379)
if ok then
    red:set_keepalive(10000, 100)  -- 连接池复用
end

3. MySQL查询优化

结合lua-resty-mysql实现非阻塞查询:

local mysql = require "resty.mysql"
local db = mysql:new()
db:set_timeout(2000)  -- 2秒超时
local res, err = db:query("SELECT * FROM banners WHERE status=1")  -- 轮播图查询示例

四、异步编程与动态控制

1. 动态黑名单(共享内存+Redis)

http {
    lua_shared_dict blacklist 10m;  # 10MB共享内存
    init_worker_by_lua_block {
        local delay = 5  -- 5秒同步一次Redis黑名单
        local function update_blacklist()
            local red = redis:new()
            red:connect("127.0.0.1", 6379)
            local keys = red:smembers("blacklist_keys")
            ngx.shared.blacklist:flush_all()
            for _, key in ipairs(keys) do
                ngx.shared.blacklist:set(key, true)
            end
        end
        local ok, err = ngx.timer.every(delay, update_blacklist)
    end
}

访问控制:

if ngx.shared.blacklist:get(ngx.var.remote_addr) then
    ngx.exit(ngx.HTTP_FORBIDDEN)  -- 拦截黑名单IP
end

2. Cosocket非阻塞调用

local sock = ngx.socket.tcp()
sock:settimeouts(1000, 2000, 3000)  -- 连接/发送/读取超时
local ok, err = sock:connect("backend.com", 80)
if ok then
    sock:send("GET /api HTTP/1.1\r\nHost: backend.com\r\n\r\n")
    local data, err = sock:receive("*a")
    sock:close()
end

五、完整配置模板(nginx.conf)

worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 16384;
    use epoll;
    multi_accept on;
}

http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65s;
    keepalive_requests 1000;
    client_body_buffer_size 128k;
    client_max_body_size 100m;
    server_tokens off;

    # 共享内存
    lua_shared_dict cache 100m;
    lua_shared_dict blacklist 10m;

    # Lua模块路径
    lua_package_path "/usr/local/openresty/lualib/?.lua;;";
    lua_package_cpath "/usr/local/openresty/lualib/?.so;;";

    # 初始化脚本
    init_worker_by_lua_file /path/to/init_blacklist.lua;

    server {
        listen 80;
        location /api {
            access_by_lua_block {
                -- 黑名单检查
                if ngx.shared.blacklist:get(ngx.var.remote_addr) then
                    ngx.exit(ngx.HTTP_FORBIDDEN)
                end
            }
            content_by_lua_file /path/to/api_handler.lua;
        }
    }
}

六、性能监控与调优建议

  1. 指标监控

    • 通过X-Execution-Time响应头跟踪 API 耗时

    • 使用 Prometheus 插件(如 APISIX)监控 QPS 和延迟

  2. 压测工具

    • wrkab模拟高并发请求,调整参数至最优

  3. 持续调优

    • 根据业务场景动态调整超时时间(如 Redis 查询从 1 秒放宽至 2 秒)

    • 定期分析error_logaccess_log优化异常请求

实际部署时需结合业务需求微调参数。

下面是我自己的服务器的配置参数:

server {
    listen 443 ssl http2 ; 
    listen 443 quic ; 
    listen [::]:443 ssl http2 ; 
    listen [::]:443 quic ; 
    server_name uniomo.com www.uniomo.com; 
    index index.php index.html index.htm default.php default.htm default.html; 
    access_log /www/sites/uniomo/log/access.log main; 
    error_log /www/sites/uniomo/log/error.log; 

    # 安全防护:隐藏版本号
    server_tokens off ;
  
    location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md) {
        return 404; 
    }
    location ^~ /.well-known/acme-challenge {
        allow all; 
        root /usr/share/nginx/html; 
    }
    location / {
        proxy_set_header Host $host; 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header X-Forwarded-Host $server_name; 
        proxy_set_header X-Real-IP $remote_addr; 
        proxy_set_header X-Forwarded-Proto $scheme; 
        proxy_set_header Connection upgrade; 
        proxy_set_header Upgrade $http_upgrade; 
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 65s;
        client_max_body_size 50M;
        proxy_http_version 1.1; 
        proxy_pass http://127.0.0.1:8090; 
    }
    http2 on; 
    if ($scheme = http) {
        return 301 https://$host$request_uri; 
    }
    ssl_certificate /www/sites/uniomo/ssl/fullchain.pem; 
    ssl_certificate_key /www/sites/uniomo/ssl/privkey.pem; 
    ssl_protocols TLSv1.3 TLSv1.2; 
    ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-SM2-SM4-GCM-SM3:ECDHE-ECDSA-AES256-GCM-SHA384:X25519MLKEM768:SecP256r1MLKEM768:ML-DSA-65:SLH-DSA-SHAKE-256; 
    ssl_prefer_server_ciphers on; 
    ssl_session_cache shared:SSL:10m; 
    ssl_session_timeout 10m;
    ssl_stapling on;  # 启用OCSP装订加速证书验证
    ssl_stapling_verify on;
    error_page 497 https://$host$request_uri; 
    proxy_set_header X-Forwarded-Proto https; 
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; 
    limit_conn perserver 30000; 
    limit_conn perip 300; 
    limit_rate 51200k; 
    add_header Alt-Svc 'h3=":443"; ma=2592000'; 
    real_ip_recursive on; 
    set_real_ip_from 0.0.0.0/0; 
    set_real_ip_from ::/0; 
    real_ip_header X-Forwarded-For; 
    # HTTP/3与Alt-Svc通告优化
    add_header Alt-Svc 'h3=":443"; h3-29=":443"; ma=2592000';  # 明确支持HTTP/3草案版本
    # 连接限制与速率控制(调整参数)
    location ~ .*\.(js|css|png|jpg|jpeg|gif|webp|webm|avif|ico|bmp|swf|eot|svg|ttf|woff|woff2)$ {
        expires 30d; 
        access_log off; 
        log_not_found off; 
        proxy_set_header Host $host; 
        proxy_set_header X-Real-IP $remote_addr; 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_pass http://127.0.0.1:8090; 
    }
    add_header Access-Control-Allow-Origin * always; 
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS,PUT,DELETE always; 
    if ( $request_method = 'OPTIONS' ) {
        return 204; 
    }
}


优化 OpenResty 的性能
https://uniomo.com/archives/openresty-de-ji-zhi-you-hua-fang-an
作者
雨落秋垣
发布于
2025年12月05日
许可协议