nginx
nginx
listen
vs server_name
| The listen
directive can be set to:
- An IP address/port combo.
- A lone IP address which will then listen on the default port 80.
- A lone port which will listen to every interface on that port.
- The path to a Unix socket.
location
location optional_modifier location_match {
. . .
}
- (none): If no modifiers are present, the location is interpreted as a prefix match. This means that the location given will be matched against the beginning of the request URI to determine a match.
- =: If an equal sign is used, this block will be considered a match if the request URI exactly matches the location given.
- ~: If a tilde modifier is present, this location will be interpreted as a case-sensitive regular expression match.
- ~*: If a tilde and asterisk modifier is used, the location block will be interpreted as a case-insensitive regular expression match.
- ~: If a carat and tilde modifier is present, and if this block is selected as the best non-regular expression match, regular expression matching will not take place
Optimizing nginx for high traffic loads
worker_processes 4; # 2 * Number of CPUs
events {
worker_connections 19000; # It's the key to high performance - have a lot of connections available
}
worker_rlimit_nofile 20000; # Each connection needs a filehandle (or 2 if you are proxying)
# Total amount of users you can serve = worker_processes * worker_connections
location
location / {
root /var/www/html; # request file path
index index.php index.html index.htm; # default filename
expires 7d; # static file expire time
try_files $uri $uri/=404; # try_files
}
location /temp {
return 302 http://www.example.com; # 兼容旧版本
}
location /chat {
try_files $uri @chatapp; # redirect to other app
}
location @chatapp {
proxy_pass http://chat.app.com;
}
location /status {
stub_status on; # open nginx status page, default off; # depends on nginx_http_stub_status_module, installation requred
allow 192.168.0.176; # allowed list
deny all; # default deny all
}
location /download {
alias /var/www/download; # assets path, #NOTICE: index attribute not allowed
autoindex on; # turn on inventory index
autoindex_exact_size off; # default on, display exact file size(bytes), OFF display (kB, MB)
autoindex_localtime on; # default off, show GMT time, ON show server time
}
upstream
# default: round-robin
upstream shop {
server 10.24.0.1:8000;
server 10.24.0.1:8001;
server 10.24.0.2:8000;
}
# weighted
upstream shop {
server 10.24.0.1:8000 weight=1;
server 10.24.0.1:8001 weight=2;
server 10.24.0.2:8000 weight=3;
}
# ip_hash
upstream shop {
ip_hash;
server 10.24.0.1:8000;
server 10.24.0.1:8001;
server 10.24.0.2:8000;
}
# least_conn
# cookie
# route
# lean
# ntlm
# least_time
# queue
# stick
# fair
# url_hash
nginx variable
name | description |
---|---|
$remote_add | |
$remote_user | |
$time_local | |
$request | url + method |
$status | |
$body_bytes_sent | |
$http_referer | |
$http_user_agent | |
$request_uri | has search string |
$uri | no search string |
$http_x_forwarded_for | |
$http_x_real_ip | |
$args | $query_string |
$host | |
$scheme | http, https |
$document_uri | |
$document_root |
API Gateway
http {
# 定义后端服务集群(可选,用于负载均衡)
upstream user_service {
server 192.168.1.10:8080; # 用户服务实例1
server 192.168.1.11:8080; # 用户服务实例2
least_conn; # 优先转发到连接数最少的实例
}
upstream order_service {
server 192.168.1.20:8080; # 订单服务实例
}
server {
listen 80;
server_name api.example.com; # API 网关域名
# 转发 /api/v1/user 到用户服务
location /api/v1/user {
# 传递真实客户端 IP 和 Host 到后端
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://user_service; # 转发到 upstream 定义的集群
}
# 转发 /api/v1/order 到订单服务
location /api/v1/order {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://order_service;
}
# URL 重写示例:将 /v2/xxx 转发到新服务,并修改路径
location /v2 {
# 重写路径:/v2/user/123 → /user/123
rewrite ^/v2/(.*)$ /$1 break;
proxy_pass http://new_service;
}
}
}
QPS limit
http {
# 定义限流规则:基于客户端 IP,共享 10MB 内存,限制 10r/s(每秒 10 个请求)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
listen 80;
server_name api.example.com;
location /api {
# 应用限流规则:允许突发 20 个请求,超过的直接拒绝(nodelay)
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend_service;
}
}
}
JWT auth, based on OpenResty + Lua
# 需安装 OpenResty(集成 ngx_lua 和 lua-resty-jwt 库)
http {
lua_package_path "/usr/local/openresty/lualib/?.lua;;"; # 指定 Lua 库路径
server {
listen 80;
server_name api.example.com;
location /api {
# 在请求处理前验证 JWT
access_by_lua_block {
local jwt = require "resty.jwt"
local auth_header = ngx.req.get_headers()["Authorization"]
# 检查 Authorization 头是否存在且格式为 "Bearer <token>"
if not auth_header or not string.find(auth_header, "Bearer ") then
ngx.status = 401
ngx.say('{"error": "Missing or invalid Authorization header"}')
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
# 提取 JWT 令牌(去掉 "Bearer " 前缀)
local token = string.sub(auth_header, 8)
# 验证 JWT(使用签名密钥,需与签发方一致)
local jwt_obj = jwt:verify("your-jwt-secret-key", token)
if not jwt_obj.valid then
ngx.status = 401
ngx.say('{"error": "Invalid JWT token: ' .. jwt_obj.reason .. '"}')
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
}
proxy_pass http://backend_service;
}
}
}
CORS
server {
listen 80;
server_name api.example.com;
location /api {
# 允许的来源(* 表示所有,生产环境建议指定具体域名)
add_header 'Access-Control-Allow-Origin' '*';
# 允许的请求方法
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
# 允许的请求头
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
# 预检请求(OPTIONS)直接返回 204(无内容)
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend_service;
}
}
Page Source