NGINX.COM
Web Server Load Balancing with NGINX Plus

均衡服务器、客户端和代理服务器之间的网络流量是维系客户和优化基础架构的关键。借助 NGINX Plus 高性能的负载均衡器,您的应用可以横向扩展并提供冗余配置,可以启用全局服务器负载均衡 (GSLB)、会话保持和主动健康检查,还可以无需重新启动就进行基础架构的动态再配置。NGINX Plus 不仅可以做到 HTTP 流量的负载均衡,TCP 和 UDP 的负载均衡也不例外。

NGINX Plus 负载均衡器:HTTP 负载均衡、TCP 负载均衡、UDP 负载载均衡
使用 NGINX 和 NGINX Plus 负载均衡来扩展您的应用程序

HTTP 负载均衡

在进行 HTTP 流量负载均衡时,NGINX Plus 会先终止每个 HTTP 链接,然后再独立处理每一个 HTTP 连接和请求。您可以根据需求去剥离 SSL/TLS 加密,检查和操控请求内容,通过限制速率对请求进行优先级排列,然后再选择相应的负载均衡策略。

为了提高性能,NGINX Plus 可以自动针对一个 HTTP 事务应用多种的优化策略,包括 HTTP 协议升级、keepalive(长连接)优化,以及对该事务进行像是内容压缩、响应缓存这样的变换。

NGINX Plus 可以轻松进行针对 HTTP 流量的负载均衡:

http {
    upstream my_upstream {
        server server1.example.com;
        server server2.example.com;
    }

    server {
        listen 80;
        location / {
            proxy_set_header Host $host;
            proxy_pass http://my_upstream;
        }
    }
}

首先先使用 server 关键字定义虚拟服务器,然后指定 listen 关键字需要监听的流量端口。接着使用 location 块匹配客户端请求的 URL,再用 proxy_set_header 关键字指定 Host 的 HTTP 请求头,最后用 proxy_pass 关键字将请求转发到 upstream 组 (upstream 块定义了 NGINX Plus 用来均衡流量的服务器)。

欲知更多信息,请查看 NGINX 和 NGINX Plus 的负载均衡使用介绍

TCP 和 UDP 的负载均衡

NGINX Plus 还可以针对 TCP 应用程序(如 MySQL)和 UDP 应用程序(如 DNS 和 RADIUS)进行负载均衡。对于 TCP 应用程序,NGINX Plus 会先终止 TCP 连接,然后再创建到新的连接到系统后端。

stream {
    upstream my_upstream {
        server server1.example.com:1234;
        server server2.example.com:2345;
    }

    server {
        listen 1123 [udp];
        proxy_pass my_upstream;
    }
}

此处的配置和针对 HTTP 的配置很相似:先使用 server 关键字来指定一个虚拟服务器,然后使用 listen 关键字指定需要监听的流量端口,最后再通过 proxy_pass 将请求发送到 upstream 组。

关于 TCP 和 UDP 负载均衡的更多信息,请参阅 NGINX Plus 管理员手册

负载均衡方式

NGINX Plus 为 HTTP、TCP 和 UDP 提供多种负载均衡方式。所有这些方式都能够选择分配到每个上游服务器的流量的权重

  • Round Robin(轮询,默认使用)—— 可按顺序在上游服务器之间分发请求。
  • 最少连接——向活跃连接数最少的服务器转发请求。
  • 最少时间—— 基于响应时间和活跃连接数进行综合计算,将请求转发到负载最小的服务器 —— 这是只有 NGINX Plus 可以提供的独有功能。
  • Hash(哈希)—— 根据特定的键值分发请求(如客户端 IP 地址或请求 URL)。若上游服务器集群发生变化,NGINX Plus 可以通过应用一致的哈希值来尽量减少负载的重新分配。
  • IP Hash(仅限 HTTP)—— 根据客户端 IP 地址的前三个八位字节进行请求分配。
  • Random with Two Choices—— 随机选择两台服务器并将请求转发到活动连接数较少的服务器(即,上方提到的“最少连接”算法)。通过使用 NGINX Plus,还可以通过“最少时间”算法优化使用效果。

利用 NGINX Plus 来限制连接数量

您可以限制 NGINX Plus 与上游 HTTP 或 TCP 服务器建立的连接数,或是与 UDP 服务器的建立的会话数。当与服务器的连接或会话数超过所定的限制时,NGINX Plus 会自动停止建立新的连接或会话。

比如在下面的配置代码中可以看到,webserver1 的连接限制为 250 个,webserver2 的连接限制为 150 个。 而 queue 关键字指定了 NGINX Plus 放在操作系统的监听队列中的最大连接数,每个连接在队列里最多保留 30 秒; 额外的连接请求将会被舍弃。

upstream backend {
    zone backends 64k;
    queue 750 timeout=30s;

    server webserver1 max_conns=250;
    server webserver2 max_conns=150;
}

当服务器的活跃连接数低于自身限制时,NGINX Plus 就会将监听队列中的连接发送给该服务器。限制连接数会有助于保持针对客户端请求的服务的一致性和可预测性——即使是在流量高峰期也是如此。

会话保持

您可通过配置 NGINX Plus 来识别用户会话,并将同一会话中的所有请求发送到同一个上游服务器。当应用服务器将状态存储于本地时,这点至关重要——因为将一个正在进行中的用户会话发送到不同服务器会带来严重的问题。即使应用在集群环境下共享状态信息,会话保持仍有助于提高性能。

NGINX 开源版支持基于哈希值的会话保持算法(即 “Hash”和“IP Hash”两种负载均衡算法)。在此基础上,NGINX Plus 增加了基于 Cookie 的会话保持算法,其中包括了 sticky cookie
NGINX Plus 将会话 cookie 添加在上游组件给特定客户端的第一个响应中,从而可以安全地识别生成响应的服务器。后续的客户端请求都会包含这个 cookie,这样 NGINX Plus 就可以将这些请求都路由至同一个上游服务器:

upstream backend {
    server webserver1;
    server webserver2;

    sticky cookie srv_id expires=1h domain=.example.com path=/;
}

在上方的示例中,NGINX Plus 在客户端最开始的响应中插入了一个名为 srv_id 的 cookie 来标识处理该请求的服务器。当后续再收到包含该 cookie 的请求时,NGINX Plus 就会直接将该请求转发到同一个服务器。

另外,NGINX Plus 还支持粘性学习(sticky learn)和粘性路由(sticky route)会话保持算法。
注:基于 Cookie 的会话保持是 NGINX Plus 独有性能之一。

主动健康检查

默认情况下,NGINX 会对来自上游服务器的响应执行基础检查,并在可能的情况下重试失败的请求。NGINX Plus 添加了带外应用健康检查(也称“合成事务(synthetic transactions)”),还添加了一个慢启动功能,以便优雅地将新的或是恢复的服务器添加到负载均衡组。

这些功能使得 NGINX Plus 能够检测和解决更广泛的问题,从而显著提高 HTTP 和 TCP/UDP 应用的可靠性。

upstream my_upstream {
	zone my_upstream 64k;
	server server1.example.com slow_start=30s;
}

server {
    # ...
    location /health {
        internal;
        health_check interval=5s uri=/test.php match=statusok;
        proxy_set_header Host www.example.com;
        proxy_pass http://my_upstream
    }
}

match statusok {
    # Used for /test.php health check
    status 200;
    header Content-Type = text/html;
    body ~ "Server[0-9]+ is alive";
}

在以上示例中,NGINX Plus 每 5 秒发就向 /test.php 发出一次请求。针对这些请求的响应必须满足 match 块中所定义的条件——即返回状态代码 200 OK 且 HTTP 响应体中包含 “ServerN is alive” 的文本——上游服务器才会被认为是处于健康状态。

注:主动健康检查为 NGINX Plus 独有性能之一。

使用 DNS 进行服务发现

默认情况下,NGINX Plus 服务器启动时会去解析 DNS 名称,并持久地缓存解析值。例如,当您使用 example.com 来指定上游服务器并配合使用 server 关键字和 resolve 变量时,NGINX Plus 会定期重新解析域名。如果相关联的 IP 地址列表发生了变化,NGINX Plus 会立即开始在新的服务器组之间进行负载均衡。

若想要配置 NGINX Plus 来使用 DNS SRV 记录,需要在 server 关键字中加入 service=http 并包含 resolver 字段,如下所示:

resolver 127.0.0.11 valid=10s;

upstream service1 {
    zone service1 64k;
    server service1 service=http resolve;
}

在上方示例中,NGINX Plus 以 10 秒为单位对 127.0.0.11(即内置 Docker DNS 服务器)进行查询,以刷新对于 service1 的域名解析。

注: 使用 DNS 进行服务发现为 NGINX Plus 独有性能之一。

NGINX Plus API

NGINX Plus 包含一个带有单个 API 端点的 RESTful API,从而能够在零停机时间的条件下动态更新上游配置和键值存储。

以下配置代码包含了 api 关键字从而启用对 /api 端点的读写访问。

upstream backend {
    zone backends 64k;
    server 10.10.10.2:220 max_conns=250;
    server 10.10.10.4:220 max_conns=150;
}

server {
    listen 80;
    server_name www.example.org;

    location /api {
        api write=on;
    }
}

当这个 API 像上面示例一样启用时,就可以使用下面的 curl 命令将新服务器添加到现有的上游组。上面的示例使用了 POST 方法,并通过 JSON 编码将服务器的IP地址设置为 192.168.78.66,权重设置为 200,最大同时连接数设置为 150。(关于代码中的 version 部分,请用参考文档中指定的 API 当前版本号进行替换。)

$ curl -iX POST -d '{"server":"192.168.78.66:80","weight":"200","max_conns":"150"}' http://localhost:80/api/version/http/upstreams/backend/servers/

运行如下代码从而以 JSON 格式来展示所有后端上游服务器的完整配置:

$ curl -s http://localhost:80/api/version/http/upstreams/backend/servers/ | python -m json.tool
	{
      "backup": false,
      "down": false,
      "fail_timeout": "10s",
      "id": 0,
      "max_conns": 250,
      "max_fails": 1,
      "route": "",
      "server": "10.10.10.2:220",
      "slow_start": "0s",
      "weight": 1
      },
      {
      "backup": false,
      "down": false,
      "fail_timeout": "10s",
      "id": 1,
      "max_conns": 150,
      "max_fails": 1,
      "route": "",
      "server": "10.10.10.4:220",
      "slow_start": "0s",
      "weight": 1
      },
      {
      "backup": false,
      "down": false,
      "fail_timeout": "10s",
      "id": 2,
      "max_conns": 200,
      "max_fails": 1,
      "route": "",
      "server": "192.168.78.66:80",
      "slow_start": "0s",
      "weight": 200
      }

要修改现有上游服务器的配置,需要通过内部 ID 进行识别该服务器,内部 ID 为上方代码的输出结果中 id 字段的值。下方示例中的命令是使用 PATCH 方法将 ID 为 2 的服务器进行重新设置,指定 IP 和监听端口为 192.168.78.55:80,权重为 500,最大连接限制数为 350。

$ curl -iX PATCH -d '{"server":"192.168.78.55:80","weight":"500","max_conns":"350"}' http://localhost:80/api/version/http/upstreams/backend/servers/2

您可以在此网址查看 NGINX Plus API 完整 Swagger(OpenAPI 规范)文档:
https://demo.nginx.com/swagger-ui/.

注: NGINX Plus API 为 NGINX Plus 独有性能之一。