ngx_http_upstream_module 模块

配置示例
指令
     upstream
     server
     zone
     state
     hash
     ip_hash
     keepalive
     keepalive_requests
     keepalive_time
     keepalive_timeout
     ntlm
     least_conn
     least_time
     queue
     random
     resolver
     resolver_timeout
     sticky
     sticky_cookie_insert
内嵌变量

ngx_http_upstream_module 模块用于定义服务器组,这些服务器组可以通过 proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_passgrpc_pass 指令进行引用。

配置示例

upstream backend {
    server backend1.example.com       weight=5;
    server backend2.example.com:8080;
    server unix:/tmp/backend3;

    server backup1.example.com:8080   backup;
    server backup2.example.com:8080   backup;
}

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

具有定期健康检查功能的动态可配置组作为我们的商业订阅的一部分提供

resolver 10.0.0.1;

upstream dynamic {
    zone upstream_dynamic 64k;

    server backend1.example.com      weight=5;
    server backend2.example.com:8080 fail_timeout=5s slow_start=30s;
    server 192.0.2.1                 max_fails=3;
    server backend3.example.com      resolve;
    server backend4.example.com      service=http resolve;

    server backup1.example.com:8080  backup;
    server backup2.example.com:8080  backup;
}

server {
    location / {
        proxy_pass http://dynamic;
        health_check;
    }
}

指令

语法 upstream name { ... }
默认值
上下文 http

定义一组服务器。服务器可以监听不同的端口。此外,监听 TCP 和 UNIX-域套接字的服务器可以混合使用。

示例

upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080       max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;

    server backup1.example.com  backup;
}

默认情况下,请求使用加权轮询负载均衡方法在服务器之间分发。在上面的示例中,每 7 个请求的分配如下:5 个请求发送到 backend1.example.com,第二个和第三个服务器各发送一个请求。如果在与某个服务器通信期间发生错误,请求将被传递到下一个服务器,依此类推,直到尝试完所有正在工作的服务器。如果无法从任何服务器获得成功响应,客户端将收到与最后一个服务器通信的结果。

语法 server address [parameters];
默认值
上下文 upstream

定义服务器的 address 和其他 parameters。地址可以指定为域名或 IP 地址(带可选端口),也可以指定为带有“unix:”前缀的 UNIX 域套接字路径。如果未指定端口,则使用端口 80。解析为多个 IP 地址的域名会同时定义多个服务器。

可以定义以下参数

weight=number
设置服务器的权重,默认值为 1。
max_conns=number
限制到代理服务器的最大并发活动连接数(1.11.5)。默认值为零,表示没有限制。如果服务器组不住在共享内存中,则限制作用于每个 worker 进程。
如果启用了空闲 keepalive 连接、多个worker 进程共享内存,则到代理服务器的活动连接和空闲连接的总数可能超过 max_conns 值。
自版本 1.5.9 至版本 1.11.5,此参数作为我们的商业订阅的一部分提供。
max_fails=number
设置在 fail_timeout 参数设置的持续时间内与服务器通信的失败尝试次数,达到该次数后服务器将被视为在 fail_timeout 参数设置的持续时间内不可用。默认情况下,失败尝试次数设置为 1。零值禁用尝试计数。什么被视为失败尝试由 proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, memcached_next_upstreamgrpc_next_upstream 指令定义。
fail_timeout=time
设置
  • 指定次数的失败尝试在多长时间内发生后,服务器将被视为不可用;
  • 以及服务器将被视为不可用的持续时间。
默认情况下,参数设置为 10 秒。
backup
将服务器标记为备份服务器。当主服务器不可用时,请求将被传递给它。
此参数不能与 hash, ip_hashrandom 负载均衡方法一起使用。
down
将服务器标记为永久不可用。
resolve
监视与服务器域名对应的 IP 地址变化,并自动修改 upstream 配置,无需重启 nginx (1.5.12)。服务器组必须位于共享内存中。

为了使此参数生效,必须在 http 块或相应的 upstream 块中指定 resolver 指令。

在版本 1.27.3 之前,此参数仅作为我们的商业订阅的一部分提供。

service=name
启用 DNS SRV 记录的解析并设置服务 name (1.9.13)。为了使此参数生效,需要为服务器指定 resolve 参数,并且指定一个不带端口号的主机名。

如果服务名不包含点号(“.”),则会构造符合 RFC 规范的名称,并将 TCP 协议添加到服务前缀。例如,要查找 _http._tcp.backend.example.com SRV 记录,需要指定指令

server backend.example.com service=http resolve;

如果服务名包含一个或多个点号,则通过连接服务前缀和服务器名来构造名称。例如,要查找 _http._tcp.backend.example.comserver1.backend.example.com SRV 记录,需要指定指令

server backend.example.com service=_http._tcp resolve;
server example.com service=server1.backend resolve;

优先级最高的 SRV 记录(具有相同最低优先级值的记录)被解析为主服务器,其余 SRV 记录被解析为备份服务器。如果为服务器指定了 backup 参数,则高优先级 SRV 记录被解析为备份服务器,其余 SRV 记录被忽略。

在版本 1.27.3 之前,此参数仅作为我们的商业订阅的一部分提供。

此外,以下参数作为我们的商业订阅的一部分提供

route=string
设置服务器路由名称。
slow_start=time
设置服务器从不健康变为健康时,或在一段时间被视为不可用后变为可用时,将其权重从零恢复到标称值所需的时间。默认值为零,即禁用慢启动。
此参数不能与 hash, ip_hashrandom 负载均衡方法一起使用。
drain
将服务器置于“draining”(耗尽)模式(1.13.6)。在此模式下,只有绑定到该服务器的请求才会被代理到它。
在版本 1.13.6 之前,此参数只能通过 API 模块更改。

如果组中只有一个服务器,则忽略 max_fails, fail_timeoutslow_start 参数,并且此类服务器永远不会被视为不可用。

语法 zone name [size];
默认值
上下文 upstream

此指令出现在版本 1.9.0 中。

定义共享内存区域的 namesize,该区域保存组的配置和运行时状态,并在 worker 进程之间共享。多个组可以共享同一区域。在这种情况下,只需指定 size 一次即可。

此外,作为我们的商业订阅的一部分,此类组允许更改组成员或修改特定服务器的设置,而无需重启 nginx。配置可通过 API 模块访问 (1.13.3)。

在版本 1.13.3 之前,配置只能通过由 upstream_conf 处理的特殊位置访问。

语法 state file;
默认值
上下文 upstream

此指令出现在版本 1.9.7 中。

指定一个 file,用于保存动态可配置组的状态。

示例

state /var/lib/nginx/state/servers.conf; # path for Linux
state /var/db/nginx/state/servers.conf;  # path for FreeBSD

当前状态仅限于服务器列表及其参数。配置文件在解析时读取,并在每次 更改 upstream 配置时更新。应避免直接修改文件内容。此指令不能与 server 指令一起使用。

重新加载配置二进制升级期间所做的更改可能会丢失。

此指令作为我们的商业订阅的一部分提供。

语法 hash key [consistent];
默认值
上下文 upstream

此指令出现在版本 1.7.2 中。

指定服务器组的负载均衡方法,其中客户端-服务器映射基于哈希的 key 值。key 可以包含文本、变量及其组合。请注意,从组中添加或删除服务器可能会导致大多数键重新映射到不同的服务器。此方法与 Cache::Memcached Perl 库兼容。

如果指定了 consistent 参数,则将使用 ketama 一致性哈希方法。该方法确保在向组中添加或删除服务器时,只有少数键会被重新映射到不同的服务器。这有助于提高缓存服务器的缓存命中率。此方法与 ketama_points 参数设置为 160 的 Cache::Memcached::Fast Perl 库兼容。

语法 ip_hash;
默认值
上下文 upstream

指定组应使用基于客户端 IP 地址在服务器之间分发请求的负载均衡方法。客户端 IPv4 地址的前三个八位字节,或整个 IPv6 地址,用作哈希键。该方法确保来自同一客户端的请求将始终传递到同一服务器,除非该服务器不可用。在后一种情况下,客户端请求将被传递到另一台服务器。很可能,它也始终是同一台服务器。

自版本 1.3.2 和 1.2.2 起支持 IPv6 地址。

如果需要临时移除某个服务器,应使用 down 参数将其标记为不可用,以保留当前客户端 IP 地址的哈希映射。

示例

upstream backend {
    ip_hash;

    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    server backend4.example.com;
}

直到版本 1.3.1 和 1.2.2,使用 ip_hash 负载均衡方法的服务器无法指定权重。

语法 keepalive connections;
默认值
上下文 upstream

此指令出现在版本 1.1.4 中。

激活到 upstream 服务器连接的缓存。

connections 参数设置每个 worker 进程缓存中保留的到 upstream 服务器的最大空闲 keepalive 连接数。当此数量超出时,将关闭最近最少使用的连接。

特别需要注意的是,keepalive 指令并不限制 nginx worker 进程可以打开的到 upstream 服务器的总连接数。connections 参数应设置为足够小的数字,以便 upstream 服务器也能处理新的传入连接。

使用非默认轮询方法以外的负载均衡方法时,需要在 keepalive 指令之前激活它们。

带有 keepalive 连接的 memcached upstream 配置示例

upstream memcached_backend {
    server 127.0.0.1:11211;
    server 10.0.0.2:11211;

    keepalive 32;
}

server {
    ...

    location /memcached/ {
        set $memcached_key $uri;
        memcached_pass memcached_backend;
    }

}

对于 HTTP,应将 proxy_http_version 指令设置为“1.1”,并且应清除“Connection”头部字段

upstream http_backend {
    server 127.0.0.1:8080;

    keepalive 16;
}

server {
    ...

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        ...
    }
}

或者,可以通过将“Connection: Keep-Alive”头部字段传递给 upstream 服务器来使用 HTTP/1.0 持久连接,但不推荐此方法。

对于 FastCGI 服务器,需要设置 fastcgi_keep_conn 以使 keepalive 连接工作

upstream fastcgi_backend {
    server 127.0.0.1:9000;

    keepalive 8;
}

server {
    ...

    location /fastcgi/ {
        fastcgi_pass fastcgi_backend;
        fastcgi_keep_conn on;
        ...
    }
}

SCGI 和 uwsgi 协议没有 keepalive 连接的概念。

语法 keepalive_requests number;
默认值
keepalive_requests 1000;
上下文 upstream

此指令出现在版本 1.15.3 中。

设置可以通过一个 keepalive 连接服务的最大请求数。达到最大请求数后,连接将关闭。

定期关闭连接对于释放每个连接的内存分配是必需的。因此,使用过高的最大请求数可能导致过多的内存使用,不推荐这样做。

在版本 1.19.10 之前,默认值为 100。

语法 keepalive_time time;
默认值
keepalive_time 1h;
上下文 upstream

此指令出现在版本 1.19.10 中。

限制一个 keepalive 连接处理请求的最长时间。达到此时间后,连接将在后续请求处理完成后关闭。

语法 keepalive_timeout timeout;
默认值
keepalive_timeout 60s;
上下文 upstream

此指令出现在版本 1.15.3 中。

设置到 upstream 服务器的空闲 keepalive 连接保持开放的超时时间。

语法 ntlm;
默认值
上下文 upstream

此指令出现在版本 1.9.2 中。

允许代理使用NTLM 认证的请求。一旦客户端发送的请求的“Authorization”头部字段值以“Negotiate”或“NTLM”开头,upstream 连接就会绑定到客户端连接。后续的客户端请求将通过同一个 upstream 连接代理,保持认证上下文。

为了使 NTLM 认证工作,需要启用到 upstream 服务器的 keepalive 连接。proxy_http_version 指令应设置为“1.1”,并且应清除“Connection”头部字段

upstream http_backend {
    server 127.0.0.1:8080;

    ntlm;
}

server {
    ...

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        ...
    }
}

使用非默认轮询方法以外的负载均衡方法时,需要在 ntlm 指令之前激活它们。

此指令作为我们的商业订阅的一部分提供。

语法 least_conn;
默认值
上下文 upstream

此指令出现在版本 1.3.1 和 1.2.2 中。

指定组应使用负载均衡方法,其中请求被传递到活动连接数最少的服务器,并考虑服务器的权重。如果存在多个这样的服务器,则按顺序使用加权轮询均衡方法尝试它们。

语法 least_time header | last_byte [inflight];
默认值
上下文 upstream

此指令出现在版本 1.7.10 中。

指定组应使用负载均衡方法,其中请求被传递到平均响应时间最短且活动连接数最少的服务器,并考虑服务器的权重。如果存在多个这样的服务器,则按顺序使用加权轮询均衡方法尝试它们。

如果指定了 header 参数,则使用接收响应头部的时间。如果指定了 last_byte 参数,则使用接收完整响应的时间。如果指定了 inflight 参数 (1.11.6),则也会考虑不完整的请求。

在版本 1.11.6 之前,默认情况下会考虑不完整的请求。

此指令作为我们的商业订阅的一部分提供。

语法 queue number [timeout=time];
默认值
上下文 upstream

此指令出现在版本 1.5.12 中。

如果在处理请求时无法立即选择 upstream 服务器,请求将被放入队列。此指令指定队列中可以同时存在的最大请求数 number。如果队列已满,或在 timeout 参数指定的时间内无法选择要将请求传递到的服务器,则会向客户端返回 502 (Bad Gateway) 错误。

timeout 参数的默认值为 60 秒。

使用非默认轮询方法以外的负载均衡方法时,需要在 queue 指令之前激活它们。

此指令作为我们的商业订阅的一部分提供。

语法 random [two [method]];
默认值
上下文 upstream

此指令出现在版本 1.15.1 中。

指定组应使用负载均衡方法,其中请求被传递到随机选择的服务器,并考虑服务器的权重。

可选的 two 参数指示 nginx 随机选择两个服务器,然后使用指定的 method 选择一个服务器。默认方法是 least_conn,它将请求传递给活动连接数最少的服务器。

least_time 方法将请求传递给平均响应时间最短且活动连接数最少的服务器。如果指定了 least_time=header,则使用接收响应头部的时间。如果指定了 least_time=last_byte,则使用接收完整响应的时间。

least_time 方法作为我们的商业订阅的一部分提供。

语法 resolver address ... [valid=time] [ipv4=on|off] [ipv6=on|off] [status_zone=zone];
默认值
上下文 upstream

此指令出现在版本 1.27.3 中。

配置用于将 upstream 服务器名称解析为地址的名称服务器,例如

resolver 127.0.0.1 [::1]:5353;

地址可以指定为域名或 IP 地址(带可选端口)。如果未指定端口,则使用端口 53。名称服务器以轮询方式进行查询。

默认情况下,nginx 在解析时会查找 IPv4 和 IPv6 地址。如果不希望查找 IPv4 或 IPv6 地址,可以指定 ipv4=off (1.23.1) 或 ipv6=off 参数。

默认情况下,nginx 使用响应的 TTL 值缓存答案。可选的 valid 参数允许覆盖它

resolver 127.0.0.1 [::1]:5353 valid=30s;

为了防止 DNS 欺骗,建议在妥善保护的可信本地网络中配置 DNS 服务器。

可选的 status_zone 参数 (1.17.5) 启用在指定 zone收集 DNS 服务器请求和响应的统计信息。此参数作为我们的商业订阅的一部分提供。

自版本 1.17.5 至版本 1.27.3,此指令仅作为我们的商业订阅的一部分提供。

语法 resolver_timeout time;
默认值
resolver_timeout 30s;
上下文 upstream

此指令出现在版本 1.27.3 中。

设置名称解析的超时时间,例如

resolver_timeout 5s;

自版本 1.17.5 至版本 1.27.3,此指令仅作为我们的商业订阅的一部分提供。

语法 sticky cookie name [expires=time] [domain=domain] [httponly] [samesite=strict|lax|none|$variable] [secure] [path=path];
sticky route $variable ...;
sticky learn create=$variable lookup=$variable zone=name:size [timeout=time] [header] [sync];
默认值
上下文 upstream

此指令出现在版本 1.5.7 中。

启用会话粘滞(session affinity),这使得来自同一客户端的请求被传递到服务器组中的同一服务器。有三种方法可用

使用 cookie 方法时,关于指定服务器的信息通过 nginx 生成的 HTTP cookie 传递

upstream backend {
    server backend1.example.com;
    server backend2.example.com;

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

来自尚未绑定到特定服务器的客户端的请求将传递到由配置的均衡方法选择的服务器。带有此 cookie 的后续请求将被传递到指定服务器。如果指定服务器无法处理请求,则选择新服务器,就像客户端尚未绑定一样。

由于负载均衡方法总是尝试在考虑已绑定请求的情况下均匀分配负载,因此活动绑定请求数量较多的服务器获取新未绑定请求的可能性较小。

第一个参数设置要设置或检查的 cookie 名称。cookie 值是 IP 地址和端口,或 UNIX 域套接字路径的 MD5 哈希的十六进制表示。但是,如果指定了 server 指令的“route”参数,则 cookie 值将是“route”参数的值

upstream backend {
    server backend1.example.com route=a;
    server backend2.example.com route=b;

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

在这种情况下,“srv_id”cookie 的值将是 ab

其他参数可能如下

expires=time
设置浏览器应保留 cookie 的时间 time。特殊值 max 将使 cookie 在“31 Dec 2037 23:55:55 GMT”过期。如果未指定参数,则会使 cookie 在浏览器会话结束时过期。
domain=domain
定义设置 cookie 的 domain。参数值可以包含变量 (1.11.5)。
httponly
向 cookie 添加 HttpOnly 属性 (1.7.11)。
samesite=strict | lax | none | $variable
向 cookie 添加 SameSite (1.19.4) 属性,其值可以是以下之一:Strict, Lax, None,或使用变量 (1.23.3)。在后一种情况下,如果变量值为空,则不会向 cookie 添加 SameSite 属性;如果值解析为 Strict, Lax, 或 None,则分配相应的值,否则分配 Strict 值。
secure
向 cookie 添加 Secure 属性 (1.7.11)。
path=path
定义设置 cookie 的 path

如果省略任何参数,则不会设置相应的 cookie 字段。

route

使用 route 方法时,代理服务器在收到第一个请求时为客户端分配一个路由。此客户端的所有后续请求将携带 cookie 或 URI 中的路由信息。此信息与 server 指令的“route”参数进行比较,以确定请求应代理到哪个服务器。如果未指定“route”参数,则路由名称将是 IP 地址和端口,或 UNIX 域套接字路径的 MD5 哈希的十六进制表示。如果指定服务器无法处理请求,则由配置的均衡方法选择新服务器,就像请求中没有路由信息一样。

route 方法的参数指定可能包含路由信息的变量。使用第一个非空变量来查找匹配的服务器。

示例

map $cookie_jsessionid $route_cookie {
    ~.+\.(?P<route>\w+)$ $route;
}

map $request_uri $route_uri {
    ~jsessionid=.+\.(?P<route>\w+)$ $route;
}

upstream backend {
    server backend1.example.com route=a;
    server backend2.example.com route=b;

    sticky route $route_cookie $route_uri;
}

此处,如果请求中存在“JSESSIONID”cookie,则从中获取路由。否则,使用 URI 中的路由。

learn

使用 learn 方法 (1.7.1) 时,nginx 分析 upstream 服务器响应并学习通常在 HTTP cookie 中传递的服务器启动的会话。

upstream backend {
   server backend1.example.com:8080;
   server backend2.example.com:8081;

   sticky learn
          create=$upstream_cookie_examplecookie
          lookup=$cookie_examplecookie
          zone=client_sessions:1m;
}

在示例中,upstream 服务器通过在响应中设置 cookie“EXAMPLECOOKIE”来创建会话。带有此 cookie 的后续请求将传递到同一服务器。如果服务器无法处理请求,则选择新服务器,就像客户端尚未绑定一样。

参数 createlookup 分别指定指示如何创建新会话和搜索现有会话的变量。这两个参数都可以指定多次,在这种情况下,使用第一个非空变量。

会话存储在共享内存区域中,其 namesizezone 参数配置。一兆字节的区域在 64 位平台上可以存储大约 4000 个会话。在 timeout 参数指定的时间内未访问的会话会从区域中移除。默认情况下,timeout 设置为 10 分钟。

header 参数 (1.13.1) 允许在从 upstream 服务器接收到响应头部后立即创建会话。

sync 参数 (1.13.8) 启用共享内存区域的同步

此指令作为我们的商业订阅的一部分提供。

语法 sticky_cookie_insert name [expires=time] [domain=domain] [path=path];
默认值
上下文 upstream

此指令自版本 1.5.7 起已过时。应使用具有新语法的等效 sticky 指令代替

sticky cookie name [expires=time] [domain=domain] [path=path];

内嵌变量

ngx_http_upstream_module 模块支持以下内嵌变量

$upstream_addr
保存 upstream 服务器的 IP 地址和端口,或 UNIX 域套接字路径。如果在请求处理期间联系了多个服务器,则它们的地址用逗号分隔,例如“192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock”。如果发生由“X-Accel-Redirect”或 error_page 引起的从一个服务器组到另一个服务器组的内部重定向,则来自不同组的服务器地址用冒号分隔,例如“192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock : 192.168.10.1:80, 192.168.10.2:80”。如果无法选择服务器,变量将保存服务器组的名称。
$upstream_bytes_received
从 upstream 服务器接收到的字节数 (1.11.4)。来自多个连接的值用逗号和冒号分隔,就像 $upstream_addr 变量中的地址一样。
$upstream_bytes_sent
发送到 upstream 服务器的字节数 (1.15.8)。来自多个连接的值用逗号和冒号分隔,就像 $upstream_addr 变量中的地址一样。
$upstream_cache_status
保存访问响应缓存的状态 (0.8.3)。状态可以是“MISS”, “BYPASS”, “EXPIRED”, “STALE”, “UPDATING”, “REVALIDATED”, 或 “HIT”之一。
$upstream_connect_time
保存与 upstream 服务器建立连接所花费的时间 (1.9.1);时间以秒为单位,精确到毫秒。在 SSL 情况下,包括握手所花费的时间。多个连接的时间用逗号和冒号分隔,就像 $upstream_addr 变量中的地址一样。
upstream 服务器在“Set-Cookie”响应头部字段中发送的指定名称 name 的 cookie (1.7.1)。仅保存最后一个服务器响应中的 cookie。
$upstream_header_time
保存从 upstream 服务器接收响应头部所花费的时间 (1.7.10);时间以秒为单位,精确到毫秒。多个响应的时间用逗号和冒号分隔,就像 $upstream_addr 变量中的地址一样。
$upstream_http_name
保留服务器响应头字段。例如,通过 $upstream_http_server 变量可以获取“Server”响应头字段。将头字段名称转换为变量名称的规则与以“$http_”前缀开头的变量相同。只保存最后一个服务器响应中的头字段。
$upstream_last_server_name
保留最后选择的上游服务器名称 (1.25.3);允许通过 SNI 传递。
proxy_ssl_server_name on;
proxy_ssl_name        $upstream_last_server_name;

此变量作为我们商业订阅的一部分提供。

$upstream_queue_time
保留请求在上游队列中花费的时间 (1.13.9);时间以秒为单位,精度为毫秒。多个响应的时间用逗号和冒号分隔,与 $upstream_addr 变量中的地址格式类似。
$upstream_response_length
保留从上游服务器获得的响应长度 (0.7.27);长度以字节为单位。多个响应的长度用逗号和冒号分隔,与 $upstream_addr 变量中的地址格式类似。
$upstream_response_time
保留接收上游服务器响应所花费的时间;时间以秒为单位,精度为毫秒。多个响应的时间用逗号和冒号分隔,与 $upstream_addr 变量中的地址格式类似。
$upstream_status
保留从上游服务器获得的响应状态码。多个响应的状态码用逗号和冒号分隔,与 $upstream_addr 变量中的地址格式类似。如果无法选择服务器,则该变量保留 502 (Bad Gateway) 状态码。
$upstream_trailer_name
保留从上游服务器获得的响应尾部字段 (1.13.10)。