Nginx核心架构、配置详解与性能调优实战指南

📅 2026/8/6 5:37:21
Nginx核心架构、配置详解与性能调优实战指南
1. 项目概述为什么每个开发者都应该懂点Nginx如果你在互联网行业待过一段时间无论你是后端开发、运维还是前端大概率都听过或者用过Nginx。它就像一个数字世界的交通警察默默站在你的服务器前面指挥着成千上万的网络请求决定谁该去哪、谁该等、谁该被拒绝。很多人对Nginx的印象停留在“一个高性能的Web服务器”这没错但它能做的远不止于此。从简单的静态文件服务到复杂的负载均衡、反向代理、API网关甚至是安全防护和流量整形Nginx几乎成了现代Web架构中不可或缺的基石。我最早接触Nginx是在一个流量突然暴增的项目里Apache服务器在并发连接数超过几百后就变得异常缓慢页面加载时间从毫秒级飙升到秒级。在几乎绝望的时候团队决定尝试用Nginx替换掉一部分前端流量分发的工作。结果令人震惊同样的硬件配置Nginx轻松扛住了数千的并发连接CPU和内存使用率还低得惊人。自那以后无论是个人项目还是公司系统Nginx都成了我的首选“守门员”。这篇文章我想从一个实践者的角度和你系统地聊聊Nginx。我不会只给你一堆冷冰冰的命令列表那样和看官方手册没什么区别。我会结合我这些年踩过的坑、总结的经验带你理解Nginx的核心设计思想掌握那些真正高频、实用的命令和配置技巧。目标是让你看完后不仅能操作更能明白背后的“为什么”在遇到问题时能有清晰的排查思路而不仅仅是机械地复制粘贴。2. Nginx核心架构与设计哲学在深入命令和配置之前我们必须先理解Nginx的“灵魂”。它的高性能并非偶然而是其独特架构设计的必然结果。理解这一点后续的所有配置和优化行为才会变得有理有据。2.1 事件驱动与非阻塞IO高并发的基石与Apache传统的“多进程/多线程-每连接”模型不同Nginx采用了一种事件驱动的异步非阻塞架构。你可以把它想象成一个极其高效的餐厅服务员Master进程。这个服务员不是一对一地为每张桌子客户端连接服务而是站在餐厅中央时刻关注着所有桌子的状态。当A桌举手要点菜客户端发起请求服务员记下需求后并不等待厨房做完而是立刻转向B桌看看B桌是否需要结账或加水。厨房工作进程做好菜后会发出一个“事件通知”服务员接收到通知再把菜端给A桌。在这个过程中服务员Nginx的线程永远不会因为等待某个慢操作如IO读写、网络传输而阻塞住他永远在处理“已经就绪”的事件。这就是非阻塞IO和事件驱动的精髓。Nginx使用如epollLinux、kqueueBSD这样的系统调用来监听大量文件描述符连接上的事件。当某个连接的数据准备好读写时操作系统会通知NginxNginx才会去处理它。这种模型使得一个Nginx工作进程可以轻松维持数万个并发连接而内存和CPU开销增长却非常平缓。注意这种架构也决定了Nginx在处理动态内容如PHP、Python时的局限性。Nginx本身不擅长执行外部程序它通常将这类请求“代理”给后端的应用服务器如uWSGI、Gunicorn、PHP-FPM处理自己只负责高效的网络调度。所以Nginx强于“转发”和“调度”弱于“执行”。2.2 多进程模型稳定与隔离的保障Nginx启动后会有一个Master进程和多个Worker进程。Master进程以root权限运行负责管理。它不处理任何客户端请求只做三件事读取并验证配置、管理Worker进程的生命周期启动、停止、平滑重启、接收外部命令如重载配置。Worker进程以普通用户如www-data,nginx运行这才是真正处理网络请求、执行业务的“苦力”。多个Worker进程之间相互独立共享监听端口通过SO_REUSEPORT一个进程崩溃不会影响其他进程极大地提高了稳定性。这种设计的优势很明显权限隔离Worker进程以低权限运行即使被攻破危害也相对有限。进程隔离一个Worker进程的异常如内存泄漏、第三方模块崩溃不会波及其他进程。充分利用多核CPU每个Worker进程可以绑定到一个CPU核心减少上下文切换提升性能。通常建议Worker进程数设置为与CPU核心数相等或稍多。2.3 配置文件的上下文与继承关系Nginx的配置文件通常是nginx.conf采用一种分层的、基于上下文的指令系统。理解这个结构是灵活配置的关键。主要上下文有main全局上下文在配置文件最外层。设置影响整个系统的参数如worker进程数、用户、错误日志路径等。events配置事件驱动模型相关的参数如每个Worker进程的最大连接数。http定义所有HTTP服务器相关的配置。这是最常用的上下文。server在http上下文内用于定义一个虚拟主机一个网站或服务。location在server上下文内用于匹配特定的URI请求路径并定义如何处理匹配到的请求。指令的生效范围遵循“子上下文继承父上下文子上下文可覆盖父上下文”的原则。例如在http块中设置的gzip on;会被所有server继承但某个特定的server或location可以将其覆盖为gzip off;。3. 核心配置文件详解与最佳实践默认的nginx.conf文件可能看起来有点复杂但拆开看它是由多个逻辑清晰的块组成的。我们以一个优化后的、生产环境可用的配置骨架为例逐段解析。3.1 全局配置main上下文# 定义运行Nginx的用户和组。出于安全务必使用非root用户。 user nginx; # Worker进程数。最优值通常等于或略多于CPU核心数。 # 可以通过命令 grep processor /proc/cpuinfo | wc -l 获取核心数。 worker_processes auto; # 使用auto让Nginx自动检测。 # 定义错误日志的路径和级别。级别从低到高debug, info, notice, warn, error, crit。 # 生产环境通常用warn或error调试时可用info或debug。 error_log /var/log/nginx/error.log warn; # 存储Master进程ID的文件路径。用于向Nginx发送信号。 pid /var/run/nginx.pid; # 每个Worker进程能打开的最大文件描述符数量。受系统限制。 # 需要与系统的 ulimit -n 值协调。高并发场景下需要调大。 worker_rlimit_nofile 65535;实操心得worker_processes设置为auto是个好习惯。但要注意如果你的服务器上还运行着其他重要服务如数据库可能需要手动设置少一些为其他服务预留CPU资源。3.2 事件模块配置events上下文events { # 每个Worker进程同时处理的最大连接数。 # 这个值乘以worker_processes就是Nginx能处理的总并发连接数上限。 worker_connections 10240; # 使用epoll这种高效的多路复用IO方法Linux特有。 use epoll; # 开启“惊群”问题优化。当有新连接到来时只唤醒一个Worker进程而不是全部。 accept_mutex on; # 设置Worker进程接收新连接的顺序。on为轮流off为争抢。高并发下off性能可能更好。 multi_accept on; }避坑指南worker_connections值不能随意设置得巨大。总连接数上限还受到系统级限制net.core.somaxconn和进程级限制worker_rlimit_nofile的约束。一个常见的误区是只调大了Nginx配置却忘了调整系统参数导致性能瓶颈。3.3 HTTP核心配置http上下文http块是配置的主体内容最多。我们分段来看。3.3.1 基础与优化参数http { # 包含MIME类型映射文件。告诉Nginx不同文件后缀对应的Content-Type。 include /etc/nginx/mime.types; # 默认MIME类型。如果找不到对应类型使用这个通常是二进制流。 default_type application/octet-stream; # 定义日志格式。main是这个格式的名字可以自定义多个。 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; # 核心优化开启高效文件传输模式。 # sendfile允许在内核空间直接完成文件数据拷贝到socket绕过用户空间效率极高。 sendfile on; # 与sendfile配合使用。当数据包小于一定大小时先缓存再发送减少网络报文数量。 tcp_nopush on; # 禁用Nagle算法要求数据立即发送降低延迟。对于高交互性服务很重要。 tcp_nodelay on; # 保持连接的超时时间。客户端在这个时间内没有发起新请求连接将被关闭。 keepalive_timeout 65; # 单个保持连接上允许的最大请求数。 keepalive_requests 100; # 隐藏Nginx版本号增加安全性。 server_tokens off; # 开启Gzip压缩显著减少文本类资源的传输体积。 gzip on; gzip_min_length 1k; # 小于1k的文件不压缩 gzip_comp_level 6; # 压缩级别1-9越高CPU消耗越大通常6是个平衡点 gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript; gzip_vary on; # 告诉代理服务器缓存压缩和非压缩版本 }3.3.2 Server虚拟主机配置这是配置网站的核心部分。一个http块内可以有多个server块。server { # 监听端口和IP。80是HTTP默认端口。listen 80 default_server; 表示这是默认虚拟主机。 listen 80; # 定义该虚拟主机响应的域名。可以写多个用空格隔开。 server_name example.com www.example.com; # 网站根目录。所有相对路径的请求都会基于这个目录查找文件。 root /usr/share/nginx/html; # 默认的索引文件。当请求以/结尾时Nginx会按顺序尝试寻找这些文件。 index index.html index.htm; # 错误页面定制。当发生404错误时返回 /404.html 页面并带上404状态码。 error_page 404 /404.html; location /404.html { internal; # 表示这个location只能被内部重定向访问不能直接通过URL访问。 } # 最重要的配置块location。用于匹配请求的URI。 location / { # try_files 指令非常有用按顺序检查文件或目录是否存在并返回第一个找到的。 # $uri 是请求的路径$uri/ 是将其视为目录。 # 如果都没找到最后可以重定向到一个命名的location或返回错误码。 # 这里如果都没找到会触发上面的 error_page 404。 try_files $uri $uri/ 404; } # 匹配所有以 .php 结尾的请求用于反向代理到PHP应用服务器。 location ~ \.php$ { # 定义后端服务器的地址。这里指向本机9000端口通常是PHP-FPM。 fastcgi_pass 127.0.0.1:9000; # 设置FastCGI的一些默认参数。 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; # 包含一组标准的fastcgi参数配置文件。 } # 禁止访问以点开头的隐藏文件如 .htaccess, .git location ~ /\. { deny all; access_log off; log_not_found off; } # 静态资源缓存配置。匹配图片、字体等。 location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ { expires 30d; # 告诉浏览器缓存30天 add_header Cache-Control public, immutable; # 更精细的缓存控制头 access_log off; # 静态资源访问日志通常可以关闭减少磁盘IO } }配置经验location的匹配规则优先级需要牢记精确匹配 ^~前缀匹配停止正则检查 ~或~*正则匹配区分/不区分大小写 /通用前缀匹配。错误的顺序会导致配置不生效。一个常见的做法是先配置精确匹配和静态文件的正则匹配最后用一个通用的location /来处理动态请求或代理。4. 必备命令行操作与系统管理光会配置还不够日常运维和排查问题离不开命令行。Nginx通过向Master进程发送信号来管理。4.1 启动、停止与重启首先你需要知道Nginx二进制文件的位置通常在/usr/sbin/nginx或通过which nginx查找。测试配置文件语法这是修改配置后必须做的第一步nginx -t或者指定配置文件路径nginx -t -c /path/to/your/nginx.conf输出syntax is ok和test is successful才表示语法正确。启动Nginxnginx或使用系统服务推荐systemctl start nginx # 启动 systemctl enable nginx # 设置开机自启停止Nginx 快速停止立即中断所有正在处理的连接nginx -s stop优雅停止等待Worker进程处理完当前请求后再退出nginx -s quit系统服务方式systemctl stop nginx重新加载配置文件最常用的命令。Master进程检查配置无误后会启动新的Worker进程加载新配置并优雅地关闭旧的Worker进程。实现不停机更新配置。nginx -s reload或systemctl reload nginx重新打开日志文件在日志切割如使用logrotate后需要让Nginx重新打开日志文件以便向新文件写入。nginx -s reopen4.2 进程管理与信号除了-s参数还可以直接使用kill命令向Master进程的PID发送信号实现更精细的控制。PID文件通常位于/var/run/nginx.pid。# 1. 查找Master进程PID cat /var/run/nginx.pid # 或 ps -ef | grep nginx | grep master # 2. 发送信号 kill -QUIT master_pid # 等同于 nginx -s quit (优雅停止) kill -TERM master_pid # 等同于 nginx -s stop (快速停止) kill -HUP master_pid # 等同于 nginx -s reload (重载配置) kill -USR1 master_pid # 等同于 nginx -s reopen (重新打开日志) kill -USR2 master_pid # 平滑升级可执行文件高级操作 kill -WINCH master_pid # 优雅关闭Worker进程用于升级回滚排查技巧当你执行reload失败或者Nginx无响应时直接使用kill -QUIT和kill -TERM可能无法解决问题。这时候可以尝试kill -9强制杀死Master进程然后再启动。但这是最后的手段因为会中断所有正在进行的连接。4.3 信息查询与调试查看版本和编译参数nginx -V这个命令会输出详细的版本信息以及编译时加入的模块。在排查“为什么这个指令不生效”时非常有用因为有些功能需要特定的编译模块支持比如stub_status模块用于状态监控。查看默认的配置文件路径nginx -t 21 | head -n 2在-t测试的输出中第一行会显示测试的配置文件路径。实时查看错误日志调试神器tail -f /var/log/nginx/error.log当你的配置不生效或服务异常时错误日志是第一个要查看的地方。5. 高级配置场景实战解析掌握了基础我们来看几个生产中高频出现的复杂场景配置。理解这些你就能解决80%的Nginx相关问题。5.1 反向代理与负载均衡这是Nginx最核心的用途之一。将客户端的请求转发到后端一组应用服务器并实现负载分发。http { # 1. 定义一个上游服务器组名字叫 backend_servers upstream backend_servers { # 负载均衡算法默认是weighted round-robin加权轮询 # 其他算法least_conn最少连接, ip_hash基于IP哈希保持会话 # hash $request_uri consistent; 基于URI哈希 server 192.168.1.101:8080 weight3 max_fails2 fail_timeout30s; server 192.168.1.102:8080 weight2; server 192.168.1.103:8080 backup; # 备份服务器只有其他都不可用时才启用 # 可选长连接优化与后端服务器保持的连接池大小 keepalive 32; } server { listen 80; server_name api.myapp.com; location / { # 2. 将请求代理到上游服务器组 proxy_pass http://backend_servers; # 3. 设置重要的代理头信息 # 将客户端的真实IP传递给后端否则后端看到的都是Nginx的IP 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_set_header X-Forwarded-Proto $scheme; # 4. 超时与重试配置 proxy_connect_timeout 5s; # 与后端建立连接的超时时间 proxy_send_timeout 60s; # 向后端发送请求的超时时间 proxy_read_timeout 60s; # 从后端读取响应的超时时间 # proxy_next_upstream error timeout http_500 http_502 http_503 http_504; # 当遇到配置的错误时尝试转发给上游组中的下一个服务器 # 5. 缓冲区优化针对大响应或慢客户端 proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; proxy_busy_buffers_size 8k; } } }实操心得proxy_set_header至关重要尤其是X-Real-IP和X-Forwarded-For否则后端应用无法获取用户真实IP会影响日志分析、限流和安全策略。proxy_buffering默认是开启的对于API或文件下载服务开启缓冲区可以提升Nginx性能但会稍微增加响应延迟。对于需要流式传输或Server-Sent Events (SSE)的场景需要将其关闭。5.2 静态资源分离与浏览器缓存优化将静态文件CSS, JS, 图片的请求与动态请求分离是提升网站性能的黄金法则。server { listen 80; server_name www.myapp.com; root /data/www/myapp; location / { proxy_pass http://backend_app; # 动态请求走代理 # ... 其他代理配置 } # 专门处理静态资源的location location /static/ { # 静态资源存放在独立的目录便于管理 alias /data/static_assets/; # 或者使用 root: location /static/ { root /data/; } # 强缓存设置告诉浏览器在过期前直接使用本地缓存不发请求 expires 1y; # 缓存1年 add_header Cache-Control public, immutable; # 关闭日志减少IO压力 access_log off; log_not_found off; # 文件不存在时不转发到后端直接返回404 try_files $uri 404; } # 前端单页应用如Vue, React的History模式支持 # 所有非静态文件、非API的请求都返回index.html由前端路由处理 location / { try_files $uri $uri/ /index.html; } }避坑指南alias和root指令容易混淆。root会将location的路径附加到指定的目录后而alias则会用指定的目录替换location匹配的部分。例如location /i/ { root /data/w3; }请求/i/top.gif会返回/data/w3/i/top.gif。而location /i/ { alias /data/w3/; }请求/i/top.gif会返回/data/w3/top.gif。5.3 安全加固与访问控制Nginx可以作为第一道安全防线。server { # 1. 限制请求方法只允许GET和POST if ($request_method !~ ^(GET|POST|HEAD)$) { return 405; # Method Not Allowed } # 2. 限制特定路径的访问如管理后台 location /admin/ { # 基于IP的访问控制 allow 192.168.1.0/24; # 允许内网网段 allow 203.0.113.1; # 允许某个特定IP deny all; # 拒绝其他所有 # 或者使用HTTP Basic认证 auth_basic Admin Area; auth_basic_user_file /etc/nginx/.htpasswd; # 使用htpasswd命令生成此文件 # ... 其他代理配置 } # 3. 防止常见攻击 # 限制客户端请求体大小防CC攻击 client_max_body_size 10m; # 限制请求速率限流 limit_req_zone $binary_remote_addr zoneapi_limit:10m rate10r/s; location /api/ { limit_req zoneapi_limit burst20 nodelay; # burst是突发请求队列大小nodelay表示不延迟处理突发请求直接拒绝超出的部分 proxy_pass http://backend_api; } # 4. 隐藏敏感信息 # 禁止访问某些文件 location ~* \.(env|log|sh|sql|key)$ { deny all; return 404; # 返回404而不是403隐藏文件存在的信息 } # 5. 添加安全响应头 add_header X-Frame-Options SAMEORIGIN always; # 防点击劫持 add_header X-Content-Type-Options nosniff always; # 防MIME类型嗅探 add_header X-XSS-Protection 1; modeblock always; # 启用XSS过滤器浏览器 # 注意Content-Security-Policy (CSP) 头需要根据你的站点内容仔细配置 }安全经验安全头Security Headers的配置非常重要但add_header指令在Nginx中有继承规则如果当前块如location设置了add_header那么它会覆盖父块如server中同名的头而不是合并。这意味着如果你在server级别设置了安全头但在某个location里设置了其他add_header比如CORS头那么server级别的安全头在这个location里就会失效解决方案是要么在每个需要安全头的location里重复设置要么将不需要安全头的特殊location移到单独的server块中。6. 性能调优与监控排查配置好了如何知道它运行得好不好如何进一步压榨性能6.1 状态监控模块Nginx内置了一个简单的状态模块ngx_http_stub_status_module编译时默认通常已包含。# 在一个单独的server块或内部location中配置 server { listen 8080; # 用一个内部端口 server_name localhost; location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; # 只允许本机访问非常重要 deny all; } }访问http://your-server:8080/nginx_status你会看到类似下面的信息Active connections: 291 server accepts handled requests 16630948 16630948 31070465 Reading: 6 Writing: 179 Waiting: 106Active connections当前活跃客户端连接数。acceptsNginx启动后接受的客户端连接总数。handled成功处理的连接数。通常与accepts非常接近如果差异大说明有些连接在握手阶段就关闭了。requests客户端发起的请求总数。一个连接上可以有多个请求HTTP Keep-Alive。Reading正在读取请求头的连接数。Writing正在向客户端写入响应的连接数。Waiting处于空闲Keep-Alive状态的连接数。这是Active connections减去前两项。6.2 连接数优化与系统调优Nginx的性能瓶颈往往不在自身而在操作系统限制。调整系统文件描述符限制 Nginx的worker_connections受限于单个进程能打开的最大文件数worker_rlimit_nofile而这个值又受系统全局限制。# 临时生效 ulimit -n 65535 # 永久生效编辑 /etc/security/limits.conf添加 * soft nofile 65535 * hard nofile 65535 # 对于Nginx进程用户可以单独设置 nginx soft nofile 65535 nginx hard nofile 65535调整网络内核参数/etc/sysctl.conf# 增加等待连接队列的最大值 net.core.somaxconn 65535 # 加快TIME_WAIT状态的端口回收高并发短连接场景 net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_tw_recycle 1 # 注意在NAT网络环境下此参数可能导致问题Linux 4.12已移除 # 增加系统全局的端口范围 net.ipv4.ip_local_port_range 1024 65000 # 增加TCP SYN backlog队列大小防SYN Flood net.ipv4.tcp_max_syn_backlog 262144 # 增加系统同时保持TIME_WAIT状态套接字的最大数量 net.ipv4.tcp_max_tw_buckets 10000修改后执行sysctl -p生效。6.3 日志分析与问题排查访问日志和错误日志是排查问题的生命线。分析访问日志找到慢请求# 使用awk找出响应时间最长的请求假设日志格式中包含$request_time awk {print $NF, $0} /var/log/nginx/access.log | sort -rn | head -20 # $NF 通常代表最后一个字段在配置了$request_time时就是响应时间实时监控错误日志中的严重错误tail -f /var/log/nginx/error.log | grep -E (emerg|alert|crit|error)查看当前连接状态非常有用# 需要安装 net-tools netstat -an | grep :80 | awk {print $6} | sort | uniq -c | sort -rn这个命令可以统计80端口上各种TCP状态ESTABLISHED, TIME_WAIT等的连接数帮助判断连接池、端口耗尽等问题。一个常见的502 Bad Gateway错误排查流程查Nginx错误日志(error.log): 看是否有connect() failed (111: Connection refused)或upstream timed out等信息。这指向后端服务不可达或响应超时。查后端服务确认后端应用如PHP-FPM, Tomcat是否在运行监听端口是否正确。查网络连通性从Nginx服务器上用telnet或curl测试是否能连接到后端服务的IP和端口。查资源检查后端服务器的CPU、内存、磁盘是否已耗尽。查配置确认Nginx中proxy_connect_timeout,proxy_read_timeout等设置是否合理是否过短。7. 进阶使用OpenResty扩展Nginx能力原生Nginx配置强大但逻辑能力有限。如果你想在请求处理链中嵌入复杂的业务逻辑如JWT验证、自定义限流、请求/响应体修改就需要用到OpenResty。OpenResty不是Nginx的一个分支而是一个“打包”它集成了Nginx核心并内置了LuaJIT虚拟机允许你使用Lua脚本直接操作请求的各个阶段。你可以把它理解为“用Lua编程的Nginx”。一个简单的例子在访问日志中记录请求处理时间并实现一个简单的API鉴权。# 在http块中加载lua模块并声明共享内存字典用于缓存等 http { lua_package_path /usr/local/openresty/lualib/?.lua;;; lua_shared_dict my_cache 10m; # 定义一个10MB的共享字典 server { listen 80; server_name api.advanced.com; # 使用Lua在access阶段记录开始时间 access_by_lua_block { ngx.ctx.start_time ngx.now() -- 将开始时间存入请求上下文 } location /secure { # 在access阶段进行JWT验证 access_by_lua_file /etc/nginx/lua/jwt_auth.lua; # 验证通过后代理到后端 proxy_pass http://backend; } # 在log阶段计算并记录请求耗时 log_by_lua_block { local request_time ngx.now() - (ngx.ctx.start_time or ngx.req.start_time()) ngx.log(ngx.INFO, request_time: , request_time) } } }/etc/nginx/lua/jwt_auth.lua文件内容示例local jwt require resty.jwt local auth_header ngx.var.http_Authorization if auth_header nil then ngx.status ngx.HTTP_UNAUTHORIZED ngx.say({error: Missing Authorization header}) return ngx.exit(ngx.HTTP_UNAUTHORIZED) end -- 提取Bearer Token local _, _, token string.find(auth_header, Bearer%s(.)) if token nil then ngx.status ngx.HTTP_UNAUTHORIZED ngx.say({error: Invalid token format}) return ngx.exit(ngx.HTTP_UNAUTHORIZED) end -- 验证JWT这里需要你的密钥 local secret your-secret-key local jwt_obj jwt:verify(secret, token) if not jwt_obj.verified then ngx.status ngx.HTTP_UNAUTHORIZED ngx.say({error: Invalid or expired token}) return ngx.exit(ngx.HTTP_UNAUTHORIZED) end -- 验证通过可以将payload中的用户信息传递给后端 ngx.req.set_header(X-User-ID, jwt_obj.payload.sub)使用OpenResty的心得它极大地扩展了Nginx的能力边界让你能在网关层做非常多的事情从而减轻后端服务的压力。但引入Lua也增加了复杂性需要团队具备相应的技能。对于简单的逻辑优先考虑用Nginx原生指令解决对于复杂的、需要状态或外部交互的逻辑OpenResty是绝佳选择。记得充分测试Lua代码的性能避免在关键路径上执行耗时的操作。