概述

Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。其配置文件采用模块化结构,通过不同的指令块来定义各种功能。

配置文件结构

全局配置文件位置

  • Linux: /etc/nginx/nginx.conf
  • Windows: conf/nginx.conf
  • macOS (Homebrew): /usr/local/etc/nginx/nginx.conf

配置文件基本结构

# 全局配置
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    # 事件模块配置
}

http {
    # HTTP模块配置
    
    server {
        # 服务器配置
        
        location {
            # 位置配置
        }
    }
}

stream {
    # Stream模块配置(TCP/UDP代理)
}

全局配置指令

# 指定运行Nginx的用户和用户组
user nginx;                    # 或 user www-data www-data;
user nobody;                   # 以nobody用户运行

# 工作进程数量
worker_processes auto;         # 自动检测CPU核心数
worker_processes 4;            # 指定4个工作进程
worker_processes 1;            # 单进程模式(调试用)

# 错误日志配置
error_log /var/log/nginx/error.log warn;    # 警告级别及以上
error_log /var/log/nginx/error.log notice;  # 通知级别及以上
error_log /var/log/nginx/error.log info;    # 信息级别及以上
error_log /var/log/nginx/error.log debug;   # 调试级别

# PID文件位置
pid /var/run/nginx.pid;

# 工作进程最大文件描述符数量
worker_rlimit_nofile 65535;

# 加载动态模块
load_module modules/ngx_http_geoip_module.so;

Events 模块

events {
    # 每个工作进程的最大连接数
    worker_connections 1024;           # 默认1024
    worker_connections 4096;           # 高并发设置
    
    # 连接处理方式
    use epoll;                         # Linux推荐
    use kqueue;                        # FreeBSD/macOS推荐
    use select;                        # 兼容性最好,性能较差
    
    # 是否接受多个连接
    multi_accept on;                   # 一次性接受多个连接
    multi_accept off;                  # 默认值
    
    # 是否允许同时接受连接
    accept_mutex on;                   # 防止惊群效应
    accept_mutex_delay 500ms;          # 获取锁的超时时间
    
    # 文件描述符传递
    sendfile on;                       # 高效文件传输
    sendfile_max_chunk 2m;             # 每次传输的最大块大小
    
    # TCP相关选项
    tcp_nopush on;                     # 减少网络包数量
    tcp_nodelay on;                    # 减少网络延迟
}

HTTP 模块

基本HTTP配置

http {
    # MIME类型配置
    include /etc/nginx/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"';
    
    log_format detailed '$remote_addr - $remote_user [$time_local] "$request" '
                       '$status $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for" '
                       'rt=$request_time uct="$upstream_connect_time" '
                       'uht="$upstream_header_time" urt="$upstream_response_time"';
    
    # 访问日志
    access_log /var/log/nginx/access.log main;
    access_log /var/log/nginx/detailed.log detailed;
    
    # 基本设置
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 100;
    
    # 客户端设置
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;
    client_max_body_size 100m;
    client_body_buffer_size 128k;
    client_body_timeout 12;
    client_header_timeout 12;
    
    # Gzip压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/xml+rss
        application/json;
    
    # 包含其他配置文件
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Server 配置块

server {
    # 监听端口和地址
    listen 80;                        # 监听80端口
    listen 443 ssl;                   # 监听443端口并启用SSL
    listen 8080 default_server;      # 默认服务器
    listen [::]:80;                   # IPv6
    listen 127.0.0.1:8080;            # 指定IP和端口
    
    # 服务器名称
    server_name example.com;           # 单个域名
    server_name example.com www.example.com;  # 多个域名
    server_name *.example.com;         # 通配符
    server_name ~^(?<subdomain>.+)\.example\.com$;  # 正则表达式
    server_name _;                     # 匹配所有域名
    
    # 根目录设置
    root /var/www/html;
    index index.html index.htm index.php;
    
    # 字符集
    charset utf-8;
    
    # 错误页面
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    
    # 访问控制
    allow 192.168.1.0/24;              # 允许特定网段
    deny all;                          # 拒绝其他所有
    
    # SSL配置(HTTPS)
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/private.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # 安全头
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
    
    # 重定向
    return 301 https://$server_name$request_uri;
    return 404;
}

Location 配置块

# 精确匹配
location = / {
    # 只有请求URI完全等于"/"时匹配
    root /var/www/html;
}

# 前缀匹配
location /images/ {
    # 匹配以"/images/"开头的URI
    root /var/www;
}

# 正则匹配(区分大小写)
location ~ \.php$ {
    # 匹配以".php"结尾的URI
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

# 正则匹配(不区分大小写)
location ~* \.(jpg|jpeg|png|gif|ico)$ {
    # 匹配图片文件
    expires 30d;
    add_header Cache-Control "public, immutable";
}

# 优先级前缀匹配
location ^~ /admin/ {
    # 匹配以"/admin/"开头,优先级高于正则
    auth_basic "Admin Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

# 命名location
location @fallback {
    # 内部重定向使用
    proxy_pass http://backend;
}

# 常用location配置示例
location / {
    try_files $uri $uri/ =404;
}

location /api/ {
    proxy_pass http://backend;
    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;
}

location /static/ {
    alias /var/www/static/;
    expires 1y;
    add_header Cache-Control "public, immutable";
}

location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

Stream 模块(TCP/UDP代理)

stream {
    # 日志格式
    log_format proxy '$remote_addr [$time_local] '
                    '$protocol $status $bytes_sent $bytes_received '
                    '$session_time "$upstream_addr" '
                    '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
    
    access_log /var/log/nginx/stream_access.log proxy;
    error_log /var/log/nginx/stream_error.log;
    
    # 上游服务器组
    upstream mysql_backend {
        server 192.168.1.10:3306 weight=3 max_fails=3 fail_timeout=30s;
        server 192.168.1.11:3306 weight=2 max_fails=3 fail_timeout=30s;
        server 192.168.1.12:3306 backup;
        
        # 负载均衡策略
        # least_conn;     # 最少连接
        # random;         # 随机
        # hash $remote_addr consistent;  # 一致性哈希
    }
    
    # TCP代理服务器
    server {
        listen 3306;
        proxy_pass mysql_backend;
        proxy_timeout 1s;
        proxy_responses 1;
        proxy_bind 192.168.1.100:3306 transparent;
        
        # 连接限制
        proxy_download_rate 1m;
        proxy_upload_rate 1m;
    }
    
    # UDP代理服务器
    server {
        listen 53 udp;
        proxy_pass dns_backend;
        proxy_timeout 1s;
        proxy_responses 1;
        proxy_bind $remote_addr transparent;
    }
    
    # DNS上游
    upstream dns_backend {
        server 8.8.8.8:53;
        server 8.8.4.4:53;
    }
    
    # 限制连接数
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    
    server {
        listen 8080;
        proxy_pass backend;
        limit_conn addr 10;
    }
}

常用指令详解

反向代理指令

# 基本代理
proxy_pass http://backend;

# 代理到指定路径
proxy_pass http://backend/api/;

# 设置代理头
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;

# 超时设置
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

# 缓冲设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;

# 重试设置
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 30s;

负载均衡指令

upstream backend {
    # 轮询(默认)
    server backend1.example.com;
    server backend2.example.com;
    
    # 权重
    server backend1.example.com weight=3;
    server backend2.example.com weight=1;
    
    # 健康检查
    server backend1.example.com max_fails=3 fail_timeout=30s;
    server backend2.example.com max_fails=3 fail_timeout=30s;
    
    # 备份服务器
    server backup1.example.com backup;
    
    # 负载均衡策略
    # least_conn;     # 最少连接
    # ip_hash;        # IP哈希
    # random;         # 随机
    # hash $request_uri consistent;  # 一致性哈希
}

缓存指令

# 代理缓存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g 
                 inactive=60m use_temp_path=off;

server {
    location / {
        proxy_cache my_cache;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_cache_bypass $http_pragma $http_authorization;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    add_header X-Cache-Status "STATIC";
}

实际应用配置示例

1. 静态网站托管

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.html;
    
    # 启用gzip压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
    
    # 静态资源缓存
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # HTML文件不缓存
    location ~* \.html$ {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
    
    # 错误页面
    error_page 404 /404.html;
}

2. Node.js应用反向代理

upstream nodejs_app {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    keepalive 32;
}

server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://nodejs_app;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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;
        proxy_cache_bypass $http_upgrade;
        proxy_read_timeout 86400;
    }
    
    # WebSocket支持
    location /socket.io/ {
        proxy_pass http://nodejs_app;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
    }
}

3. PHP-FPM应用

server {
    listen 80;
    server_name wordpress.example.com;
    root /var/www/wordpress;
    index index.php index.html;
    
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        
        # PHP优化
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
    }
    
    # 禁止访问敏感文件
    location ~ /\. {
        deny all;
    }
    
    location ~* \.(sql|log|md)$ {
        deny all;
    }
}

4. HTTPS配置

server {
    listen 80;
    server_name secure.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name secure.example.com;
    root /var/www/secure;
    
    # SSL证书
    ssl_certificate /etc/letsencrypt/live/secure.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/secure.example.com/privkey.pem;
    
    # SSL配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_stapling on;
    ssl_stapling_verify on;
    
    # 安全头
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    location / {
        try_files $uri $uri/ =404;
    }
}

5. 负载均衡配置

upstream web_cluster {
    least_conn;
    server 192.168.1.10:80 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:80 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:80 weight=1 max_fails=3 fail_timeout=30s;
    server 192.168.1.13:80 backup;
    
    # 健康检查(需要nginx-plus或第三方模块)
    # health_check;
}

server {
    listen 80;
    server_name lb.example.com;
    
    location / {
        proxy_pass http://web_cluster;
        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;
        
        # 连接保持
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        
        # 超时设置
        proxy_connect_timeout 30s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
    
    # 负载均衡状态页面
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

6. API网关配置

# 用户服务
upstream user_service {
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;
}

# 订单服务
upstream order_service {
    server 127.0.0.1:8003;
    server 127.0.0.1:8004;
}

# 支付服务
upstream payment_service {
    server 127.0.0.1:8005;
}

server {
    listen 80;
    server_name api.example.com;
    
    # API版本控制
    location /api/v1/users/ {
        proxy_pass http://user_service/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # 限流
        limit_req zone=api burst=20 nodelay;
    }
    
    location /api/v1/orders/ {
        proxy_pass http://order_service/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        limit_req zone=api burst=10 nodelay;
    }
    
    location /api/v1/payments/ {
        proxy_pass http://payment_service/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        limit_req zone=api burst=5 nodelay;
    }
    
    # CORS支持
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,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' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
    }
}

# 限流配置
http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
}

7. MySQL TCP代理

stream {
    upstream mysql_cluster {
        least_conn;
        server 192.168.1.10:3306 weight=3 max_fails=3 fail_timeout=30s;
        server 192.168.1.11:3306 weight=2 max_fails=3 fail_timeout=30s;
        server 192.168.1.12:3306 backup;
    }
    
    server {
        listen 3306;
        proxy_pass mysql_cluster;
        proxy_timeout 1s;
        proxy_responses 1;
        proxy_bind 192.168.1.100:3306 transparent;
        
        # 连接日志
        access_log /var/log/nginx/mysql_access.log proxy;
        error_log /var/log/nginx/mysql_error.log;
    }
    
    # 连接限制
    limit_conn_zone $binary_remote_addr zone=mysql_conn:10m;
    
    server {
        listen 3307;
        proxy_pass mysql_cluster;
        limit_conn mysql_conn 10;
    }
}

配置文件管理和维护

配置检查

# 检查配置文件语法
nginx -t
nginx -t -c /etc/nginx/nginx.conf

# 查看编译模块
nginx -V

热重载配置

# 重新加载配置
nginx -s reload
systemctl reload nginx

# 重启服务
nginx -s restart
systemctl restart nginx

日志管理

# 日志轮转配置 /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 640 nginx adm
    sharedscripts
    postrotate
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 `cat /var/run/nginx.pid`
        fi
    endscript
}

性能优化建议

工作进程优化

worker_processes auto;                    # 自动检测CPU核心数
worker_rlimit_nofile 65535;               # 增加文件描述符限制
worker_connections 4096;                  # 增加连接数

缓存优化

# 启用操作系统缓存
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# 客户端缓存
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

网络优化

# Keep-alive连接
keepalive_timeout 65;
keepalive_requests 100;

# 缓冲区优化
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
client_body_buffer_size 128k;
client_max_body_size 100m;

总结

Nginx配置文件采用模块化结构,通过合理配置各个模块可以实现高性能的Web服务、反向代理、负载均衡等功能。在实际应用中,需要根据具体需求选择合适的配置方案,并注意性能优化和安全配置。