Nginx是一款高性能的Web服务器和反向代理服务器,以高性能、高并发、低资源消耗著称。掌握Nginx反向代理和负载均衡是后端程序员和运维的必备技能。今天就来分享Nginx反向代理与负载均衡的实战经验。

1. 反向代理基础

反向代理是指代理服务器接收客户端的请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给客户端。

反向代理的作用:

  • 隐藏后端服务器,提高安全性
  • 负载均衡,分发请求到多台服务器
  • 缓存静态内容,减轻后端压力
  • 统一入口,方便管理和扩展
  • SSL终止,统一处理HTTPS

基本配置:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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指令:

  • proxy_pass:指定后端服务器地址
  • proxysetheader:设置转发给后端的请求头
  • proxyconnecttimeout:连接后端超时时间
  • proxyreadtimeout:读取后端响应超时时间
  • proxysendtimeout:发送请求到后端超时时间
  • proxy_buffering:是否开启响应缓冲

2. 负载均衡

Nginx的负载均衡通过upstream模块实现,支持多种负载均衡算法。

轮询(默认):

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;
    }
}

加权轮询:

upstream backend {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=2;
    server 192.168.1.12:8080 weight=1;
}

IP哈希(ip_hash): 同一客户端IP的请求始终分发到同一台后端服务器,实现会话保持。

upstream backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

最少连接(least_conn): 请求分发到当前连接数最少的后端服务器。

upstream backend {
    least_conn;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

健康检查:

upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 backup;
}
  • max_fails:允许请求失败的次数
  • fail_timeout:失败后暂停服务的时间
  • backup:备份服务器,其他服务器都不可用时启用
  • down:标记服务器永久不可用

3. 静态资源缓存

Nginx可以缓存静态资源,减轻后端服务器压力,提高访问速度。

# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|eot)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
}

# 代理缓存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g 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_pass http://backend;
    }
}

4. HTTPS配置

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    location / {
        proxy_pass http://backend;
    }
}

# HTTP重定向到HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

5. 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/xhtml+xml
    application/x-font-ttf
    application/x-font-opentype
    image/svg+xml
    image/x-icon;

6. 安全加固

# 隐藏Nginx版本号
server_tokens off;

# 禁止访问敏感文件
location ~ /\.(git|svn|htaccess|htpasswd) {
    deny all;
}

# 限制请求体大小
client_max_body_size 10m;

# 防止DDoS
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
    location / {
        limit_req zone=one burst=20 nodelay;
        limit_conn addr 10;
        proxy_pass http://backend;
    }
}

7. 完整配置示例

upstream backend {
    least_conn;
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 backup;
}

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;

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

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    server_tokens off;
    client_max_body_size 10m;

    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
        root /var/www/html;
    }

    location / {
        proxy_cache my_cache;
        proxy_cache_valid 200 10m;
        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;
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
    }
}

总结

Nginx反向代理和负载均衡是高可用Web架构的重要组成部分。通过反向代理可以隐藏后端服务器、统一入口、处理HTTPS,通过负载均衡可以将请求分发到多台服务器,提高系统的可用性和扩展性。

掌握Nginx配置是后端程序员和运维的必备技能,希望这篇文章能帮助大家更好地理解和使用Nginx。