目录
- 简介
- 系统要求
- 目录结构与日志配置
- 安装步骤(官方仓库/源码/Docker)
- 常用命令(systemctl/CLI/日志/OPM)
- 核心配置说明与最佳实践
- 性能优化与生产参数建议
- 安全加固与限流
- 常见问题与故障排查
- 常用实例(反向代理/负载均衡/缓存/CORS/WebSocket/gRPC)
- JWT 认证完整示例(签发/验证/刷新)
- 升级、卸载与维护
- 参考资源
简介
OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
OpenResty 通过汇聚各种设计精良的 Nginx 模块,从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,开发人员和系统工程师可以使用 Lua 编程语言对 Nginx 核心以及现有的各种 Nginx C 模块进行脚本编程,构建出具备复杂业务逻辑的高性能 Web 应用。
系统要求
本教程适用于以下操作系统:
- Ubuntu 24.04 LTS (当前环境)
- Ubuntu 22.04 LTS
- Ubuntu 20.04 LTS
- CentOS 7/8
- Debian 10/11
硬件要求:
- 最小 1GB RAM
- 至少 2GB 可用磁盘空间
- 支持 x86_64 架构
目录结构与日志配置
在生产环境中,合理的目录结构和日志配置对于系统维护和问题排查非常重要。
推荐的目录结构
/usr/local/openresty/├── nginx/│ ├── conf/│ │ ├── nginx.conf # 主配置文件│ │ └── conf.d/ # 站点/服务拆分配置│ ├── logs/ # 默认日志目录(access.log / error.log)│ └── html/ # 默认静态根目录└── bin/openresty # openresty 可执行文件日志配置
在高性能场景下,合理的日志配置可以减少 I/O 压力并提供有用的调试信息:
# 通用日志格式,包含上游状态与耗时log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '"$upstream_addr" "$upstream_status" ' '"$upstream_response_time" "$request_time" "$request_id"';access_log /usr/local/openresty/nginx/logs/access.log main buffer=32k flush=5s;error_log /usr/local/openresty/nginx/logs/error.log warn;日志轮转配置
为了避免日志文件过大,建议配置日志轮转:
# 创建 logrotate 配置文件(Ubuntu/Debian 示例)sudo tee /etc/logrotate.d/openresty <<'EOF'/usr/local/openresty/nginx/logs/*.log { daily missingok rotate 52 compress delaycompress notifempty create 0644 www-data www-data sharedscripts postrotate [ -f /usr/local/openresty/nginx/logs/nginx.pid ] && \ kill -USR1 "$(cat /usr/local/openresty/nginx/logs/nginx.pid)" endscript}EOF安装步骤(官方仓库/源码/Docker)
方法一:通过官方仓库安装(推荐)
1. 添加 OpenResty 仓库
首先,添加 OpenResty 的官方仓库到您的系统:
# 安装必要的依赖包sudo apt-get updatesudo apt-get -y install wget gnupg ca-certificates# 导入 GPG 密钥wget -O - https://openresty.org/package/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/openresty.gpg# 添加官方 APT 仓库echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list# 更新本地APT缓存sudo apt-get update2. 安装 OpenResty
# 安装 OpenRestysudo apt-get -y install openresty# 安装 resty CLI 工具(可选)sudo apt-get -y install openresty-restyRHEL/CentOS 添加仓库与安装
# 安装必要工具sudo yum install -y yum-utils ca-certificates# 添加官方 YUM 仓库(CentOS/RHEL)sudo tee /etc/yum.repos.d/openresty.repo <<'EOF'[openresty]name=Official OpenResty Repositorybaseurl=https://openresty.org/package/centos/$releasever/$basearchgpgcheck=1enabled=1gpgkey=https://openresty.org/package/pubkey.gpgEOF# 安装 OpenResty 及 resty CLI(可选)sudo yum install -y openresty openresty-resty3. 验证安装
# 创建软链,方便使用ln -s /usr/local/openresty/nginx/sbin/nginx /usr/bin/openrestyln -s /usr/local/openresty/nginx/sbin/nginx /usr/bin/nginx# 检查 OpenResty 版本openresty -v# 查看编译参数与模块openresty -V# 启动 OpenResty 服务sudo systemctl start openresty# 设置开机自启sudo systemctl enable openresty# 检查运行状态sudo systemctl status openresty默认情况下,OpenResty 会监听 80 端口。您可以通过访问服务器 IP 地址来验证是否安装成功。
方法二:从源代码编译安装
如果您需要特定的模块或最新功能,可以从源代码编译安装:
1. 安装编译依赖
sudo apt-get updatesudo apt-get -y install build-essential libpcre3-dev libssl-dev zlib1g-dev2. 下载并解压源码
# 创建工作目录mkdir ~/openresty-build && cd ~/openresty-build# 下载最新版本的 OpenRestywget https://openresty.org/download/openresty-1.21.4.1.tar.gztar -xzvf openresty-1.21.4.1.tar.gzcd openresty-1.21.4.13. 配置和编译
# 配置编译选项./configure \ --prefix=/usr/local/openresty \ --with-http_ssl_module \ --with-http_realip_module \ --with-http_stub_status_module \ --with-http_v2_module \ --with-stream \ --with-stream_ssl_module \ --with-pcre-jit# 编译和安装make -j$(nproc)sudo make install4. 创建系统服务
创建 systemd 服务文件:
sudo tee /etc/systemd/system/openresty.service <<-'EOF'[Unit]Description=OpenResty Web ServerAfter=network.target[Service]Type=forkingExecStart=/usr/local/openresty/bin/openrestyExecReload=/usr/local/openresty/bin/openresty -s reloadExecStop=/usr/local/openresty/bin/openresty -s quitPIDFile=/usr/local/openresty/nginx/logs/nginx.pidPrivateTmp=true[Install]WantedBy=multi-user.targetEOF# 重新加载 systemd 并启动服务sudo systemctl daemon-reloadsudo systemctl start openrestysudo systemctl enable openresty方法三:使用 Docker 安装
对于开发测试环境,也可以使用 Docker 运行 OpenResty:
# 拉取官方镜像docker pull openresty/openresty:latest# 运行容器docker run -d --name openresty -p 80:80 -p 443:443 openresty/openresty:latest# 挂载本地配置与静态文件(按需)# docker run -d --name openresty \# -p 80:80 -p 443:443 \# -v $(pwd)/conf:/usr/local/openresty/nginx/conf \# -v $(pwd)/html:/usr/local/openresty/nginx/html \# openresty/openresty:latest常用命令(systemctl/CLI/日志/OPM)
服务管理命令
# 启动 OpenRestysudo systemctl start openresty# 停止 OpenRestysudo systemctl stop openresty# 重启 OpenRestysudo systemctl restart openresty# 查看运行状态sudo systemctl status openresty# 设置开机自启sudo systemctl enable openresty# 禁止开机自启sudo systemctl disable openrestyOpenResty 控制命令
# 测试配置文件语法openresty -t# 重新加载配置(热更新)openresty -s reload# 快速关闭openresty -s stop# 正常关闭openresty -s quit# 指定配置文件启动openresty -c /path/to/nginx.conf日志查看命令
# 查看错误日志tail -f /usr/local/openresty/nginx/logs/error.log# 查看访问日志tail -f /usr/local/openresty/nginx/logs/access.log# 查看系统 journal 日志journalctl -u openresty -fOPM 包管理与 resty 快速脚手架
# 搜索并安装 OPM 包(例如 lua-resty-jwt)opm search jwtopm get SkyLothar/lua-resty-jwt# 卸载 OPM 包opm remove SkyLothar/lua-resty-jwt# 使用 resty 运行一段 Lua 代码(无须写入文件)resty -e 'ngx.say("Hello from OpenResty!")'# 创建示例项目结构(使用 resty)resty --new myapp不使用 systemd 的系统下的使用方法
在一些较老的系统或者不使用 systemd 的发行版(如使用 SysVinit 或 Upstart 的系统)中,你需要使用不同的方式来管理 OpenResty 服务。
直接使用命令行管理
你可以直接使用 OpenResty 提供的命令来管理服务:
# 启动 OpenResty(前台运行)/usr/local/openresty/nginx/sbin/nginx# 启动 OpenResty(后台运行)/usr/local/openresty/nginx/sbin/nginx -c /usr/local/openresty/nginx/conf/nginx.conf# 测试配置文件语法/usr/local/openresty/nginx/sbin/nginx -t# 重新加载配置(热更新)/usr/local/openresty/nginx/sbin/nginx -s reload# 快速关闭/usr/local/openresty/nginx/sbin/nginx -s stop# 正常关闭/usr/local/openresty/nginx/sbin/nginx -s quit创建 init.d 脚本
对于使用 SysVinit 的系统,你可以创建一个 init.d 脚本来管理 OpenResty 服务:
sudo tee /etc/init.d/openresty <<-'EOF'#!/bin/bash## openresty - this script starts and stops the openresty daemon## chkconfig: - 85 15# description: OpenResty is a scalable web platform by extending \# the Nginx web server with Lua.# processname: openresty# config: /usr/local/openresty/nginx/conf/nginx.conf# pidfile: /usr/local/openresty/nginx/logs/nginx.pid# Source function library.. /lib/lsb/init-functions# Check that networking is up.[ "$NETWORKING" = "no" ] && exit 0openresty="/usr/local/openresty/nginx/sbin/nginx"prog=$(basename $openresty)NGINX_CONF_FILE="/usr/local/openresty/nginx/conf/nginx.conf"lockfile=/var/lock/subsys/openrestystart() { [ -x $openresty ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 echo -n $"Starting $prog: " daemon $openresty -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval}stop() { echo -n $"Stopping $prog: " killproc $prog -QUIT retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval}restart() { configtest || return $? stop sleep 1 start}reload() { configtest || return $? echo -n $"Reloading $prog: " killproc $openresty -HUP RETVAL=$? echo}force_reload() { restart}configtest() { $openresty -t -c $NGINX_CONF_FILE}rh_status() { status $prog}rh_status_q() { rh_status >/dev/null 2>&1}case "$1" in start) rh_status_q && exit 0 $1 ;; stop) rh_status_q || exit 0 $1 ;; restart|configtest) $1 ;; reload) rh_status_q || exit 7 $1 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" exit 2esacEOF# 设置执行权限sudo chmod +x /etc/init.d/openresty# 添加到系统服务sudo chkconfig --add openrestysudo chkconfig openresty on# 启动服务sudo service openresty start使用 supervisor 管理
另一种选择是使用 supervisor 来管理 OpenResty 进程:
- 安装 supervisor:
# Ubuntu/Debiansudo apt-get install supervisor# CentOS/RHELsudo yum install supervisor- 创建 supervisor 配置文件:
sudo tee /etc/supervisor/conf.d/openresty.conf <<-'EOF'[program:openresty]command=/usr/local/openresty/nginx/sbin/nginx -g "daemon off;"directory=/usr/local/openresty/nginxuser=rootautostart=trueautorestart=truestdout_logfile=/var/log/supervisor/openresty.logstderr_logfile=/var/log/supervisor/openresty.error.logEOF- 启动 supervisor 并管理 OpenResty:
# 启动 supervisorsudo service supervisor start# 重新加载配置sudo supervisorctl rereadsudo supervisorctl update# 启动 OpenRestysudo supervisorctl start openresty# 查看状态sudo supervisorctl status openresty# 重启 OpenRestysudo supervisorctl restart openresty# 停止 OpenRestysudo supervisorctl stop openresty设置开机自启(不使用 systemd)
对于不使用 systemd 的系统,你可以通过以下方式设置 OpenResty 开机自启:
- 编辑 /etc/rc.local 文件:
sudo nano /etc/rc.local- 在 exit 0 行之前添加:
# 启动 OpenResty/usr/local/openresty/nginx/sbin/nginx- 确保 /etc/rc.local 文件具有执行权限:
sudo chmod +x /etc/rc.local通过以上方法,即使在不支持 systemd 的系统上也能正常管理和运行 OpenResty。
核心配置说明与最佳实践
OpenResty 的主配置文件通常位于 /usr/local/openresty/nginx/conf/nginx.conf(源码/二进制安装)或 /etc/openresty/nginx.conf(某些仓库安装)。下方提供一个推荐的生产基础模板,便于按需扩展:
# 用户与进程user www-data; # 与系统中运行站点的用户保持一致worker_processes auto; # 自动匹配 CPU 核心数worker_rlimit_nofile 65535;# 日志与 PIDerror_log /usr/local/openresty/nginx/logs/error.log warn;pid /usr/local/openresty/nginx/logs/nginx.pid;# 事件模型events { use epoll; # Linux 推荐 epoll worker_connections 65535; # 结合 ulimit 调整 multi_accept on; accept_mutex off;}# HTTP 全局配置http { include /usr/local/openresty/nginx/conf/mime.types; default_type application/octet-stream; # 标准日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '"$upstream_addr" "$upstream_status" ' '"$upstream_response_time" "$request_time"'; access_log /usr/local/openresty/nginx/logs/access.log main buffer=32k flush=5s; # 连接与性能参数 sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 60; keepalive_requests 1000; # 请求体限制 client_max_body_size 50m; # 压缩 gzip on; gzip_vary on; gzip_min_length 1024; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/xml; # 默认虚拟主机(拒绝未知域名访问) server { listen 80 default_server; server_name _; return 444; # 丢弃连接 } # 站点拆分管理 include /usr/local/openresty/nginx/conf/conf.d/*.conf;}高性能配置优化
为了满足大流量高并发的需求,可以对 OpenResty 进行以下优化配置:
# 用户和工作进程配置user www-data;worker_processes auto;worker_rlimit_nofile 65535;# 错误日志配置error_log /usr/local/openresty/nginx/logs/error.log warn;# 进程ID文件pid /usr/local/openresty/nginx/logs/nginx.pid;# 工作进程连接数配置events { use epoll; worker_connections 65535; multi_accept on; accept_mutex off;}http { # 基础配置 include /usr/local/openresty/nginx/conf/mime.types; default_type application/octet-stream; # 通用日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '"$upstream_addr" "$upstream_status" ' '"$upstream_response_time" "$request_time" "$request_id"'; # 访问日志配置 access_log /usr/local/openresty/nginx/logs/access.log main buffer=32k flush=5s; # 性能优化配置 sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 60; keepalive_requests 1000; client_header_timeout 60; client_body_timeout 60; send_timeout 60; # 请求体相关配置 client_body_buffer_size 32k; client_max_body_size 50m; client_header_buffer_size 4k; large_client_header_buffers 8 16k; # 输出缓冲区配置 output_buffers 1 32k; postpone_output 1460; # Gzip压缩配置 gzip on; gzip_vary on; gzip_min_length 1024; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/xml; gzip_buffers 16 8k; gzip_http_version 1.1; # 限流配置 limit_req_zone $binary_remote_addr zone=general:10m rate=100r/s; limit_req_zone $binary_remote_addr zone=login:10m rate=10r/s; # 连接数限制 limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m; # 隐藏版本号 server_tokens off; # SSL优化配置(如果需要HTTPS) ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # 代理配置(如果需要反向代理) proxy_buffering on; proxy_buffer_size 16k; proxy_buffers 32 16k; proxy_busy_buffers_size 32k; proxy_temp_file_write_size 64k; proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $http_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; proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; # 默认服务器配置 server { listen 80; server_name _; return 444; } include /usr/local/openresty/nginx/conf/conf.d/*.conf;}Lua 配置示例
在 OpenResty 中使用 Lua 脚本:
server { listen 80; server_name localhost; location /lua { default_type text/html; content_by_lua_block { ngx.say("<p>Hello, OpenResty!</p>") }}}实例5:反向代理缓存(proxy_cache)
``nginx http { proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:100m max_size=10g inactive=60m use_temp_path=off;
server { listen 80; server_name cache.example.com; location / { proxy_cache my_cache; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; add_header X-Proxy-Cache $upstream_cache_status; proxy_pass http://backend; }}}
### 实例6:CORS 跨域支持(简单场景)``nginxserver { listen 80; server_name api.example.com; # 预检请求(OPTIONS) if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; add_header 'Access-Control-Allow-Headers' '*'; add_header 'Access-Control-Max-Age' 3600; return 204; } location / { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; proxy_pass http://backend; }}实例7:WebSocket 反向代理
``nginx server { listen 80; server_name ws.example.com;
location /ws/ { proxy_pass http://backend_ws; # 后端需支持 WebSocket proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 60s;}}
### 实例8:gRPC 反向代理``nginxupstream grpc_backend { server 127.0.0.1:50051;}server { listen 80 http2; # gRPC 需要 HTTP/2 server_name grpc.example.com; location / { grpc_pass grpc://grpc_backend; }}常见问题与故障排查
1. 端口被占用
如果遇到端口被占用的问题:
# 查找占用 80 端口的进程sudo lsof -i :80# 杀死相关进程sudo kill -9 <PID>2. 权限不足
确保 OpenResty 相关目录有正确的权限:
# 修改目录所有者sudo chown -R nobody:nobody /usr/local/openresty/nginx/# 设置适当权限sudo chmod -R 755 /usr/local/openresty/nginx/3. 配置文件语法错误
使用测试命令检查配置文件:
# 测试配置文件语法openresty -t# 如果有错误,根据提示修复后重新加载openresty -s reload4. 启动失败
查看详细错误信息:
# 查看错误日志tail -f /usr/local/openresty/nginx/logs/error.log# 查看系统 journal 日志journalctl -u openresty5. LuaJIT 相关问题
如果遇到 LuaJIT 相关问题,可能需要调整内存限制:
# 在 nginx.conf 的 http 块中添加http { lua_max_running_timers 256; lua_max_pending_timers 128; lua_shared_dict my_cache 128m;}6. SSL/TLS 证书问题
当配置 HTTPS 时,可能会遇到证书相关问题:
server { listen 443 ssl; server_name example.com; # 证书文件路径 ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/cert.key; # SSL 安全配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512; ssl_prefer_server_ciphers off; location / { root /var/www/html; index index.html; }}常见证书问题及解决方案:
- 检查证书路径是否正确
- 确保证书文件权限正确(通常为 600)
- 确保证书文件格式正确(PEM 格式)
- 检查证书链是否完整
7. upstream 连接超时
当配置反向代理时,可能会遇到 upstream 超时问题:
upstream backend { server 192.168.1.10:8080; server 192.168.1.11:8080; # 调整超时设置 keepalive 32;}server { listen 80; server_name example.com; location / { proxy_pass http://backend; # 设置超时时间 proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; # 设置缓冲区 proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; }}8. 内存不足问题
OpenResty 在处理大量并发连接时可能会遇到内存不足问题:
worker_processes auto;events { # 根据内存情况调整连接数 worker_connections 1024; # 启用多路复用 use epoll; multi_accept on;}http { # 调整客户端缓冲区大小 client_body_buffer_size 16K; client_header_buffer_size 1k; client_max_body_size 8m; large_client_header_buffers 2 1k; # 输出缓冲区设置 output_buffers 1 32k; postpone_output 1460;}9. Lua 脚本执行错误
当 Lua 脚本执行出错时,可以在错误日志中看到详细信息:
-- 添加错误处理local success, result = pcall(function() -- 你的 Lua 代码 return some_function()end)if not success then ngx.log(ngx.ERR, "Lua error: ", result) ngx.status = 500 ngx.say("Internal Server Error") ngx.exit(500)end10. 日志文件过大
OpenResty 的日志文件可能会快速增长,需要定期清理或轮转:
# 在 nginx.conf 中配置日志轮转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=5m;error_log /var/log/nginx/error.log warn;配置 logrotate:
# 创建 logrotate 配置文件sudo tee /etc/logrotate.d/openresty <<-'EOF'/usr/local/openresty/nginx/logs/*.log { daily missingok rotate 52 compress delaycompress notifemptycreate 0640 www-data www-data sharedscripts postrotate [ -f /usr/local/openresty/nginx/logs/nginx.pid ] && kill -USR1 `cat /usr/local/openresty/nginx/logs/nginx.pid` endscript}EOF11. 性能调优问题
如果遇到性能问题,可以从以下几个方面进行调优:
# CPU 亲和性设置worker_processes auto;worker_cpu_affinity 0101 1010; # 示例:根据核心数制定掩码(按需调整)events { # 提高并发连接数 worker_connections 10240; # 使用 epoll 模型 use epoll; # 批量接受连接 multi_accept on;}http { # 启用 sendfile sendfile on; # 禁用 tcp_nopush(除非需要) tcp_nopush on; # 启用 tcp_nodelay tcp_nodelay on; # 调整 keepalive 超时 keepalive_timeout 65; # 启用 gzip 压缩 gzip on; gzip_vary on; gzip_min_length 1024; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;}12. 跨域问题(CORS)
当配置 API 服务时,可能会遇到跨域问题:
server { listen 80; server_name api.example.com; location / { # 添加 CORS 头 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"; # 处理预检请求 if ($request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"; add_header Access-Control-Max-Age 86400; add_header Content-Length 0; add_header Content-Type text/plain; return 204; } proxy_pass http://backend; }}13. 缓存相关问题
配置缓存时可能会遇到各种问题:
http { # 创建共享缓存区 proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { listen 80; server_name example.com; location / { proxy_pass http://backend; # 启用缓存 proxy_cache my_cache; proxy_cache_valid 200 1h; proxy_cache_valid 404 1m; # 缓存相关头部 proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_lock on; # 添加缓存状态头部 add_header X-Cache-Status $upstream_cache_status; } # 清除缓存的位置 location ~ /purge(/.*) { proxy_cache_purge my_cache $scheme$request_method$host$1$is_args$args; } }}安全加固与限流(基础版)
加强 OpenResty 的安全性:
server { listen 80; server_name example.com; # 隐藏版本信息 server_tokens off; # 限制请求方法 if ($request_method !~ ^(GET|POST|HEAD)$ ) { return 405; } # 限制请求大小 client_max_body_size 1M; # 防止图片盗链 location ~* \.(jpg|jpeg|png|gif|ico|svg)$ { valid_referers none blocked server_names *.example.com; if ($invalid_referer) { return 403; } } # 限制请求频率(基础版) limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; location /api/ { limit_req zone=api burst=20 nodelay; proxy_pass http://backend; }}常用实例
实例1:反向代理配置
server { listen 80; server_name example.com; location / { proxy_pass http://backend_server; 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; }}实例2:负载均衡配置
upstream backend { server 192.168.1.10:8080; server 192.168.1.11:8080; server 192.168.1.12:8080;}server { listen 80; server_name example.com; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }}实例3:静态文件服务器
server { listen 80; server_name static.example.com; root /var/www/static; index index.html; location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 1y; add_header Cache-Control "public, immutable"; } location / { try_files $uri $uri/ =404; }}实例4:API 限流
http { lua_shared_dict my_limit_req_store 100m; server { listen 80; server_name api.example.com; location /api/ { access_by_lua_block { local limit_req = require "resty.limit.req" local lim, err = limit_req.new("my_limit_req_store", 10, 2) if not lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err) return ngx.exit(500) end local key = ngx.var.binary_remote_addr local delay, err = lim:incoming(key, true) if not delay then if err == "rejected" then return ngx.exit(503) end ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500) end if delay >= 0.001 then local excess = err ngx.sleep(delay) end } proxy_pass http://backend; } }}JWT 认证完整示例(签发/验证/刷新)
推荐使用社区维护的模块 lua-resty-jwt,避免自行实现签名与解析造成安全隐患。
1. 安装依赖(OPM)
opm install SkyLothar/lua-resty-jwtopm install openresty/lua-resty-string如需刷新令牌方案,可选:
opm install bungle/lua-resty-session2. 签发与验证示例(HS256)
在 conf.d/jwt.conf 中加入:
server { listen 80; server_name api.example.com; # 登录:签发 JWT location = /login { content_by_lua_block { local cjson = require "cjson.safe" local jwt = require "resty.jwt" ngx.req.read_body() local args = ngx.req.get_post_args() or {} local username = args.username local password = args.password if username == "admin" and password == "password" then local token = jwt:sign("your-secret-key-here", { header = { kid = "v1" }, payload = { sub = username, role = "admin", iat = ngx.time(), exp = ngx.time() + 3600, iss = "example.com", aud = "example-client" } }) ngx.header.content_type = "application/json" ngx.say(cjson.encode({ token = token })) else ngx.status = 401 ngx.header.content_type = "application/json" ngx.say(cjson.encode({ error = "invalid credentials" })) end } } # 受保护资源:验证 JWT location = /protected { access_by_lua_block { local jwt = require "resty.jwt" local cjson = require "cjson.safe" local auth = ngx.var.http_Authorization if not auth then return ngx.exit(401) end local token = auth:match("Bearer%s+(.+)") if not token then return ngx.exit(401) end local jwt_obj = jwt:verify("your-secret-key-here", token) if not jwt_obj.verified then ngx.status = 401 ngx.header.content_type = "application/json" ngx.say(cjson.encode({ error = jwt_obj.reason })) return ngx.exit(401) end -- 验证通过,继续到内容阶段 } content_by_lua_block { ngx.header.content_type = "application/json" ngx.say('{"message":"ok"}') } }}3. 刷新令牌(Refresh Token)思路
- 登录时同时签发短期访问令牌(Access Token,1h)与长期刷新令牌(Refresh Token,7d)。
- 刷新令牌仅在 /token/refresh 端点使用,验证后重新签发 Access Token。
- 刷新令牌应存储在 Httponly cookie 或服务端(结合 session)并绑定设备与 IP。
4. 安全实践
- 使用强随机密钥并分版本管理(kid)。
- Access Token 短期有效,Refresh Token 长期有效并可撤销。
- 对登录与刷新端点增加更严格的限流与验证码。
- 对生产环境启用 HTTPS 并启用 HSTS。
性能优化建议
1. 工作进程调优
# 设置工作进程数等于 CPU 核心数worker_processes auto;# 绑定工作进程到特定 CPU 核心(适用于多核系统)worker_cpu_affinity 0101 1010; # 示例:根据核心数制定掩码(按需调整)# 增加每个工作进程的最大文件描述符数worker_rlimit_nofile 65535;在高并发场景下,合理的进程配置可以显著提升性能:
- worker_processes 设置为 CPU 核心数可以获得最佳性能
- worker_cpu_affinity 可以将工作进程绑定到特定 CPU 核心,减少进程切换开销
- worker_rlimit_nofile 设置每个工作进程能打开的最大文件描述符数
2. 连接和缓冲区优化
events { # 单个工作进程的最大连接数 worker_connections 65535; # 使用 epoll 模型(Linux) use epoll; # 接收尽可能多的连接 multi_accept on; # 关闭互斥锁,提高性能(在高负载下) accept_mutex off;}http { # 客户端请求缓冲区大小 client_body_buffer_size 32k; # 客户端请求头缓冲区大小 client_header_buffer_size 4k; # 大请求头缓冲区大小 large_client_header_buffers 8 16k; # 输出缓冲区设置 output_buffers 1 32k; postpone_output 1460; # 超时设置 client_header_timeout 60; client_body_timeout 60; send_timeout 60; keepalive_timeout 60; keepalive_requests 1000;}3. 启用高效传输模式
http { # 开启高效文件传输模式 sendfile on; # 减少网络报文段数量 tcp_nopush on; # 提高I/O性能 tcp_nodelay on;}这些传输模式优化可以显著提高文件传输效率:
- sendfile 启用高效文件传输模式,直接在内核空间传输数据
- tcp_nopush 防止网络阻塞,积极减少网络报文段的数量
- tcp_nodelay 禁用 Nagle 算法,提高 I/O 性能
4. 启用压缩
gzip on;gzip_vary on;gzip_min_length 1024;gzip_comp_level 6;gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;5. 缓存优化
# 静态文件缓存location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|bmp|swf|flv|mp4)$ { expires 7d; add_header Cache-Control "public, immutable"; access_log off;}# 动态内容缓存http { # 创建共享缓存区 proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=365d use_temp_path=off; server { location / { proxy_pass http://backend; # 启用缓存 proxy_cache my_cache; proxy_cache_valid 200 304 365d; proxy_cache_valid any 10m; # 缓存状态头部 add_header X-Cache-Status $upstream_cache_status; } }}缓存状态说明:
- MISS: 未命中缓存
- HIT: 命中缓存
- EXPIRED: 缓存过期
- STALE: 命中了陈旧缓存
- RevalIDDATED: Nginx验证陈旧缓存依然有效
- UPDATING: 内容陈旧,但正在更新
- BYPASS: 响应从原始服务器获取
6. 安全优化
server { # 隐藏版本信息 server_tokens off; # 限制请求方法 if ($request_method !~ ^(GET|POST|HEAD)$ ) { return 405; } # 限制请求大小 client_max_body_size 50m; # 防止图片盗链 location ~* \.(jpg|jpeg|png|gif|ico|svg)$ { valid_referers none blocked server_names *.example.com; if ($invalid_referer) { return 403; } } # 禁止访问敏感文件 location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md) { return 404; } # 限制请求频率 limit_req_zone $binary_remote_addr zone=general:10m rate=100r/s; limit_req_zone $binary_remote_addr zone=login:10m rate=10r/s; # 限制连接数 limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m; location / { # 应用频率限制 limit_req zone=general burst=200 nodelay; # 应用连接数限制 limit_conn conn_limit_per_ip 10; proxy_pass http://backend; } # 登录接口特殊限制 location /login { limit_req zone=login burst=5 nodelay; proxy_pass http://backend; }}7. SSL/TLS 优化
server { listen 443 ssl http2; server_name example.com; # SSL 证书配置 ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/cert.key; # SSL 安全配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384; ssl_prefer_server_ciphers off; # SSL 会话缓存 ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # OCSP 装订 ssl_stapling on; ssl_stapling_verify on; # HSTS 头部 add_header Strict-Transport-Security "max-age=31536000"; location / { root /var/www/html; index index.html; }}8. 反向代理优化
http { # 代理缓冲区设置 proxy_buffering on; proxy_buffer_size 16k; proxy_buffers 32 16k; proxy_busy_buffers_size 32k; proxy_temp_file_write_size 64k; # 超时设置 proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; # HTTP 版本和头部设置 proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $http_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; # 跨域设置 add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' '*'; server { location / { proxy_pass https://backend_server; proxy_ssl_verify off; # 设置头部信息 proxy_set_header Host "backend.example.com"; proxy_set_header Origin "https://backend.example.com"; proxy_set_header Referer "https://backend.example.com/"; } }}9. Linux 系统优化
调节系统参数可以进一步提升 Nginx 性能(请谨慎评估对业务的影响):
# 连接积压队列上限(结合应用层监听 backlog)net.core.somaxconn=65535# SYN 防护(启用 cookie 防护)net.ipv4.tcp_syncookies=1# TIME_WAIT 重用(仅在作为客户端发起大量出站连接的场景谨慎启用)net.ipv4.tcp_tw_reuse=1# 超时与保活net.ipv4.tcp_fin_timeout=30net.ipv4.tcp_keepalive_time=1200# TIME_WAIT 桶上限(避免过度增长)net.ipv4.tcp_max_tw_buckets=5000注意:tcp_tw_recycle 已在新内核版本中移除且会导致 NAT/负载均衡环境下的连接异常,切勿启用。实际参数应结合内核版本、网络拓扑(是否有 NAT/反向代理)和业务连接模式评估。将这些参数写入 /etc/sysctl.conf 并执行 sysctl -p 生效。
通过以上优化配置,OpenResty 可以在高并发场景下提供更好的性能表现。需要注意的是,具体的配置参数应该根据实际的硬件资源和业务需求进行调整。
升级、卸载与维护
升级(仓库安装)
sudo apt-get update && sudo apt-get -y upgrade openresty# 或 RHEL/CentOSsudo yum update -y openresty升级前建议:
- 先在灰度/测试环境验证新版本;
- 备份 /usr/local/openresty/nginx/conf 与自定义 Lua/OPM 包;
- 查看兼容性变更(例如 OpenSSL、HTTP/2、stream 模块)。
卸载
# Debian/Ubuntusudo apt-get -y remove --purge openresty openresty-resty# RHEL/CentOSsudo yum remove -y openresty openresty-resty# 清理残留(按需执行)sudo rm -rf /usr/local/openresty维护建议
- 使用 systemd 管理启动与重载,优先使用 openresty -t 检查配置后再 reload;
- 接入 logrotate,避免日志无限增长;
- 定期回顾限流/连接与缓存参数,结合业务峰值调整;
- 使用 Prometheus + ngx_status 或自定义日志指标进行监控与告警。
参考资源
- OpenResty 官方文档:https://openresty.org/en/
- OpenResty 包管理(OPM):https://opm.openresty.org/
- lua-resty-jwt:https://github.com/SkyLothar/lua-resty-jwt
- Nginx 官方文档(指令参考):https://nginx.org/en/docs/

