nginx

nginx

listen vs server_name

| The listen directive can be set to:

location

location optional_modifier location_match {

    . . .

}

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