7.9.6 性能优化与故障排查

围绕 OpenResty 的性能优化与故障排查,应从请求链路、Lua 执行、网络与系统资源、模块配置四个维度建立方法论。目标是降低延迟、提升吞吐、控制资源占用并提高可观测性与可恢复性。

原理草图(请求链路与关键耗时点):

文章图片

一、性能优化要点(含配置示例与命令)#

1. 连接与事件模型#

关键目标:提高并发能力,减少连接排队。

配置示例(/etc/nginx/nginx.conf):

worker_processes auto;
worker_rlimit_nofile 200000;

events {
    worker_connections  65535;
    use epoll;
    multi_accept on;
    accept_mutex off;
}

http {
    keepalive_timeout 30s;
    keepalive_requests 10000;
    upstream backend {
        server 10.0.0.11:8080 max_fails=2 fail_timeout=5s;
        server 10.0.0.12:8080 max_fails=2 fail_timeout=5s;
        keepalive 256;
    }
}

命令解释与预期:

# 查看当前进程打开文件数限制
ulimit -n
# 预期:>= 100000(与 worker_rlimit_nofile 匹配)

# 查看实际 worker 进程数与连接数
ps -ef | grep nginx
ss -lntp | grep nginx

2. Lua 运行时优化#

关键目标:减少 Lua 内存分配与阻塞。

示例(/etc/nginx/conf.d/lua_opt.conf):

server {
    listen 8080;
    location /lua {
        content_by_lua_block {
            local ngx = ngx
            local say = ngx.say
            local t = ngx.now()
            -- 避免频繁创建表,缓存函数引用
            say("time=", t)
        }
    }
}

Lua 调试与基准测试:

# 使用 resty 验证脚本
resty -e 'local ngx=ngx; ngx.say("ok")'
# 预期:输出 ok

3. 共享字典与缓存#

关键目标:提升热点数据命中率,减少回源。

示例:

lua_shared_dict hot_cache 100m;

server {
    listen 8080;
    location /cache {
        content_by_lua_block {
            local dict = ngx.shared.hot_cache
            local v = dict:get("key")
            if not v then
                v = "value_from_backend"
                dict:set("key", v, 5) -- TTL 5s
            end
            ngx.say(v)
        }
    }
}

监控共享字典:

# 查看共享字典使用情况
grep "lua_shared_dict" -n /etc/nginx/nginx.conf
# 通过自定义日志或指标输出 used/evictions(见监控部分)

4. I/O 与阻塞控制#

关键目标:避免同步阻塞导致 worker 堵塞。

示例(超时配置):

lua_socket_connect_timeout 1000ms;
lua_socket_read_timeout 2000ms;
proxy_connect_timeout 1s;
proxy_read_timeout 2s;

5. 静态资源优化#

关键目标:减少系统调用与 TCP 交互。

location /static/ {
    root /data/www;
    sendfile on;
    tcp_nopush on;
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
}

二、故障排查路径(含命令与日志)#

1. 高延迟#

排查步骤:
1) 查看错误日志是否出现超时

tail -f /var/log/nginx/error.log
# 关注:upstream timed out, lua socket read timeout

2) 分析请求耗时字段

# 自定义日志格式包含 request_time/upstream_response_time
grep "request_time" /var/log/nginx/access.log | tail

3) 验证上游 RTT

ping -c 3 10.0.0.11
curl -w "%{time_total}\n" -o /dev/null -s http://10.0.0.11:8080/health

2. 502/504#

排查步骤:

# 查看上游健康状态
curl http://10.0.0.11:8080/health
# 检查 upstream 连接
ss -s

可能原因:
- 上游实例不可用
- DNS 解析失败
- 连接耗尽

3. QPS 下降#

排查步骤:

# 查看进程是否频繁 reload
grep "reload" /var/log/nginx/error.log

# 查看 CPU/内存
top -H -p $(pidof nginx | tr ' ' ,)

4. 内存增长#

排查步骤:

# 进程内存观察
pmap -x $(pidof nginx | awk '{print $1}')
# 检查 lua_shared_dict 变化(需要自定义埋点/监控)

5. 连接耗尽#

排查步骤:

ss -ant state time-wait | wc -l
ss -ant state syn-recv | wc -l
sysctl net.core.somaxconn

三、监控与可观测性(示例)#

1. stub_status#

location /nginx_status {
    stub_status;
    allow 127.0.0.1;
    deny all;
}

2. 自定义访问日志格式#

log_format main '$remote_addr $request '
                'rt=$request_time urt=$upstream_response_time '
                'status=$status';
access_log /var/log/nginx/access.log main;

四、常见排错工具安装与使用#

# CentOS/RHEL
yum install -y htop sysstat lsof strace

# Ubuntu/Debian
apt-get install -y htop sysstat lsof strace

工具说明:
- pidstat -p <pid> 1:查看 CPU/IO 使用
- strace -p <pid>:分析系统调用阻塞点
- lsof -p <pid>:查看文件/连接占用

五、回滚与恢复策略(操作示例)#

# 1) 检查配置
nginx -t

# 2) 备份配置
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%F)

# 3) 平滑重载
nginx -s reload

# 4) 快速回滚
cp /etc/nginx/nginx.conf.bak.2024-01-01 /etc/nginx/nginx.conf
nginx -s reload

六、练习题#

1) 在 OpenResty 中配置 stub_status 并用 curl 获取连接状态,解释 Active/Reading/Writing/Waiting 含义。
2) 使用 log_format 增加 request_timeupstream_response_time,观察是否存在高延迟请求。
3) 配置 lua_shared_dict 并实现一个 5 秒 TTL 的缓存示例。
4) 模拟上游超时(将 proxy_read_timeout 调小),观察 error.log 中错误信息并解释原因。
5) 使用 ss -s 分析连接状态,判断是否存在连接耗尽风险。