Nginx反向代理与负载均衡实战教程 – wiki基地

Nginx 反向代理与负载均衡实战教程

1. 引言

在现代 Web 应用程序架构中,高可用性、高性能和可伸缩性是至关重要的目标。Nginx 作为一款高性能的 HTTP 和反向代理服务器,以及一个邮件代理服务器,因其卓越的稳定性、丰富的功能集、简单的配置和较低的资源消耗而广受欢迎。它不仅能够处理静态文件,更在反向代理和负载均衡方面发挥着核心作用,是构建可靠、可伸缩 Web 服务的基石。

本文将深入探讨 Nginx 的反向代理和负载均衡功能,通过实战配置示例,帮助您理解其工作原理,并掌握如何在生产环境中应用这些强大的特性。

2. Nginx 基础回顾

在深入了解反向代理和负载均衡之前,我们先简单回顾一下 Nginx 的基本概念。

什么是 Nginx?

Nginx(发音为 “engine-x”)是一个开源的、高性能的 Web 服务器,也可以用作反向代理、负载均衡器和 HTTP 缓存。它以其事件驱动的异步架构而闻名,能够处理大量并发连接,使其非常适合高流量网站。

Nginx 的安装(以 CentOS/Ubuntu 为例)

CentOS:

bash
sudo yum install epel-release
sudo yum install nginx
sudo systemctl start nginx
sudo systemctl enable nginx

Ubuntu:

bash
sudo apt update
sudo apt install nginx
sudo systemctl start nginx
sudo systemctl enable nginx

安装完成后,您可以通过浏览器访问服务器的 IP 地址,看到 Nginx 的欢迎页面,表示安装成功。

Nginx 配置文件的基本结构

Nginx 的主配置文件通常位于 /etc/nginx/nginx.conf。它由多个上下文(context)组成,包括:

  • main:全局配置,影响所有 Nginx 进程。
  • events:配置 Nginx 和用户之间的连接。
  • http:配置 HTTP 服务器的行为。
    • upstream:定义后端服务器组,用于负载均衡。
    • server:定义虚拟主机,监听特定端口和域名。
      • location:根据请求 URI 匹配并处理请求。

“`nginx

全局配置

user nginx;
worker_processes auto; # 自动设置工作进程数量

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024; # 每个工作进程的最大连接数
}

http {
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"';

access_log  /var/log/nginx/access.log  main;

sendfile        on;
#tcp_nopush     on;

keepalive_timeout  65;

#gzip  on;

include /etc/nginx/conf.d/*.conf; # 引入其他配置文件

}
“`

通常,我们会将具体的 server 块配置放在 conf.d/ 目录下(如 /etc/nginx/conf.d/your_app.conf),这样可以保持主配置文件整洁,并方便管理多个虚拟主机。

3. 反向代理 (Reverse Proxy)

什么是反向代理?

反向代理服务器接收客户端的请求,然后将请求转发给后端服务器(如应用服务器、API 服务器),并将后端服务器的响应返回给客户端。对于客户端而言,它只知道与反向代理服务器交互,并不知道后端服务器的存在。

Nginx Reverse Proxy Diagram
示意图:Nginx 反向代理

正向代理 vs 反向代理

  • 正向代理(如 VPN、Shadowsocks):代理客户端去访问目标服务器。客户端知道目标服务器的地址,但目标服务器不知道真实客户端的地址。主要用于客户端访问外部资源。
  • 反向代理:代理服务器接收请求后转发给后端服务器。客户端不知道后端服务器的真实地址。主要用于保护和管理后端服务器。

为什么使用反向代理?

  1. 安全性增强:隐藏后端服务器的真实 IP 地址和端口,保护后端服务器免受直接攻击。
  2. 负载均衡:将客户端请求分发到多个后端服务器,提高系统处理能力和可用性(本文后续会详细讲解)。
  3. SSL/TLS 终止:在 Nginx 层面处理 SSL/TLS 加密和解密,减轻后端服务器的负担,简化后端配置。
  4. 动静分离:Nginx 可以高效地处理静态资源(图片、CSS、JS),而将动态请求转发给后端应用服务器。
  5. 缓存:Nginx 可以缓存后端服务器的响应,减少对后端服务器的请求,提高响应速度。
  6. URL 重写与过滤:根据规则修改请求 URL 或过滤恶意请求。

Nginx 反向代理配置

Nginx 中最核心的反向代理指令是 proxy_pass

示例:将所有请求代理到后端应用服务器

假设我们有一个运行在 http://127.0.0.1:8080 上的 Web 应用程序。我们希望通过 Nginx 监听 80 端口,并将所有请求代理到这个后端服务。

/etc/nginx/conf.d/app.conf 文件中添加以下内容:

“`nginx

/etc/nginx/conf.d/app.conf

server {
listen 80;
server_name your_domain.com www.your_domain.com; # 您的域名或IP地址

location / {
    proxy_pass http://127.0.0.1:8080; # 代理的目标地址
    proxy_set_header Host $host; # 转发原始请求的Host头
    proxy_set_header X-Real-IP $remote_addr; # 转发客户端真实IP
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 记录代理链
    proxy_set_header X-Forwarded-Proto $scheme; # 转发原始请求协议(http/https)
}

# 可以添加其他 location 块,例如处理静态文件
# location ~* \.(css|js|gif|jpe?g|png)$ {
#     root /path/to/static/files;
#     expires 30d;
# }

}
“`

配置说明:

  • listen 80;:Nginx 监听 80 端口。
  • server_name your_domain.com;:指定虚拟主机的域名。
  • location /:匹配所有请求。
  • proxy_pass http://127.0.0.1:8080;:将请求代理到 http://127.0.0.1:8080
  • proxy_set_header:这些指令用于设置转发给后端服务器的请求头。它们确保后端服务器能够获取到正确的客户端信息(如原始请求的 Host、客户端真实 IP)。
    • Host: 转发客户端请求的 Host 头。
    • X-Real-IP: 记录客户端的真实 IP 地址。
    • X-Forwarded-For: 如果请求经过多层代理,这个头会记录所有代理的 IP 地址链。
    • X-Forwarded-Proto: 记录客户端请求的原始协议(HTTP 或 HTTPS)。

修改配置后,务必检查语法并重新加载 Nginx:

bash
sudo nginx -t # 检查配置文件语法
sudo nginx -s reload # 重新加载 Nginx 配置

4. 负载均衡 (Load Balancing)

什么是负载均衡?

负载均衡是将客户端请求有效、公平地分发到一组后端服务器(通常称为“服务器池”或“上游服务器”)的技术。其目的是避免单一服务器过载,提高应用程序的响应速度、可靠性和伸缩性。

Nginx Load Balancing Diagram
示意图:Nginx 负载均衡

Nginx 负载均衡策略

Nginx 通过 upstream 模块提供多种负载均衡策略:

  1. round_robin (轮询):默认策略。按时间顺序将请求依次分发到后端服务器。简单且有效。

    nginx
    upstream backend_servers {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
    }

  2. weight (权重):为每个服务器指定一个权重值,权重越高的服务器接收的请求越多。适用于后端服务器性能不一致的场景。

    nginx
    upstream backend_servers {
    server 192.168.1.10:8080 weight=5; # 接收5倍请求
    server 192.168.1.11:8080 weight=1; # 接收1倍请求
    }

  3. ip_hash (IP 哈希):根据客户端 IP 地址的哈希值将请求分发到特定的后端服务器。这确保了来自同一客户端 IP 的请求始终发送到同一台服务器,适用于需要会话保持的场景。

    nginx
    upstream backend_servers {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    }

  4. least_conn (最少连接):将请求发送到当前活动连接数最少的后端服务器。适用于请求处理时间不一致的场景,确保负载更均匀。

    nginx
    upstream backend_servers {
    least_conn;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    }

上游服务器参数

upstream 块中,除了 IP 地址和端口,还可以为 server 指令指定其他参数:

  • down:标记服务器永久离线,不参与负载均衡。
  • backup:标记服务器为备用服务器。当主服务器都不可用时,才将请求发送给它。
  • max_fails=N:在 fail_timeout 时间内,如果服务器失败 N 次,则标记为不可用。默认 max_fails=1
  • fail_timeout=时间:服务器被标记为不可用状态的时间(默认为 10 秒),以及 max_fails 失败计数器重置的时间。
  • max_conns=N:限制 Nginx 与上游服务器建立的最大并发连接数。

nginx
upstream backend_servers {
server 192.168.1.10:8080 weight=5 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 backup; # 备用服务器
server 192.168.1.12:8080 down; # 离线服务器
}

5. 实战配置示例:反向代理与负载均衡结合

现在,我们将反向代理和负载均衡结合起来,构建一个更强大的配置。
假设我们有三个后端应用服务器,运行在 192.168.1.10:8080192.168.1.11:8081192.168.1.12:8082。我们希望 Nginx 能够将请求均衡地分发到这些服务器。

/etc/nginx/conf.d/my_app_lb.conf 文件中:

“`nginx

/etc/nginx/conf.d/my_app_lb.conf

1. 定义上游服务器组 (upstream block)

upstream my_app_backend {
# 负载均衡策略:这里使用最少连接数,也可以是 round_robin, ip_hash, weight
least_conn;

# 后端服务器列表
# max_fails=3: 在 30 秒内如果失败 3 次,则认为服务器宕机
# fail_timeout=30s: 服务器宕机后,30 秒后 Nginx 会再次尝试连接
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8081 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8082 max_fails=3 fail_timeout=30s;

# 可以添加一个备用服务器
# server 192.168.1.13:8083 backup;

}

2. 定义虚拟主机 (server block)

server {
listen 80; # 监听 HTTP 请求
server_name www.example.com example.com; # 您的域名

# 3. 配置反向代理
location / {
    proxy_pass http://my_app_backend; # 将请求代理到上面定义的上游服务器组

    # 重要的 proxy_set_header 配置,用于将客户端真实信息传递给后端
    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_send_timeout 10s;
    proxy_read_timeout 10s;

    # 可选:缓冲设置
    # proxy_buffering on;
    # proxy_buffers 4 32k;
    # proxy_buffer_size 64k;
}

# 可选:处理静态文件请求,Nginx 直接提供服务,不转发给后端
# location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
#     root /var/www/my_static_files; # 静态文件根目录
#     expires 30d; # 浏览器缓存 30 天
#     log_not_found off; # 不记录 404 错误到日志
# }

# 错误页面配置
error_page 500 502 503 504 /50x.html;
location = /50x.html {
    root /usr/share/nginx/html; # Nginx 默认错误页面路径
}

}
“`

保存配置后,执行 sudo nginx -t 检查语法,然后 sudo nginx -s reload 重新加载 Nginx。现在,当客户端访问 www.example.com 时,Nginx 会根据 least_conn 策略将请求分发到三个后端应用服务器中的一个。

6. 高级特性与优化

SSL/TLS 终止 (HTTPS)

在 Nginx 层处理 SSL/TLS 加密和解密,是推荐的做法。这可以减轻后端服务器的计算负担,并集中管理证书。

“`nginx
server {
listen 443 ssl; # 监听 HTTPS 端口
server_name www.example.com;

ssl_certificate /etc/nginx/ssl/www.example.com.crt; # 您的证书文件
ssl_certificate_key /etc/nginx/ssl/www.example.com.key; # 您的私钥文件

# 推荐的 SSL/TLS 配置
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3;

location / {
    proxy_pass http://my_app_backend;
    # ... (其他 proxy_set_header 配置同上)
}

}

可选:将 HTTP 请求重定向到 HTTPS

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

缓存 (proxy_cache)

Nginx 可以缓存后端服务器的响应,显著提高静态内容或不经常变化内容的访问速度。

“`nginx
http {
# … 其他 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 www.example.com;

    location / {
        proxy_cache my_cache; # 启用缓存
        proxy_cache_valid 200 302 10m; # 200 和 302 状态码缓存 10 分钟
        proxy_cache_valid 404 1m; # 404 状态码缓存 1 分钟
        proxy_cache_min_uses 1; # 首次请求后缓存
        add_header X-Cache-Status $upstream_cache_status; # 添加缓存状态头

        proxy_pass http://my_app_backend;
        # ... (其他 proxy_set_header 配置)
    }
}

}
“`

Gzip 压缩

启用 Gzip 压缩可以减少传输数据量,从而加快页面加载速度。

nginx
http {
# ...
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}

7. 总结

Nginx 的反向代理和负载均衡功能是构建现代高并发、高可用 Web 架构不可或缺的工具。通过本文的实战教程,您应该已经掌握了:

  • Nginx 的基本安装和配置结构。
  • 反向代理的工作原理和配置方法,以及 proxy_set_header 的重要性。
  • 负载均衡的基本概念和 upstream 模块的不同策略(轮询、权重、IP 哈希、最少连接)。
  • 如何将反向代理和负载均衡结合应用于实际场景。
  • 以及 SSL/TLS 终止、缓存和 Gzip 压缩等高级优化技巧。

熟练运用这些功能,将使您能够构建出更健壮、更高效、更安全的 Web 服务。当然,Nginx 的功能远不止这些,建议您继续探索其官方文档,以挖掘更多强大的特性。

滚动至顶部