Skip to content

Nginx负载均衡模块简述

Nginx 负载均衡是由代理模块和上游(upstream)模块共同实现的,Nginx 通过代理模块的反向代理功能将用户请求转发到上游服务器组,上游模块通过指定的负载均衡策略及相关的参数配置将用户请求转发到目标服务器上。上游模块可以与 Nginx 的代理指令(proxy_pass)、FastCGI 协议指令(fastcgi_pass)、uWSGI 协议指令(uwsgi_pass)、SCGI 协议指令(scgi_pass)、memcached 指令(memcached_pass)及 gRPC 协议指令(grpc_pass)实现多种协议后端服务器的负载均衡。

1、服务器配置指令

Nginx 上游模块定义了 upstream 指令域,在该指令域内可设置服务器、负载均衡策略等负载均衡配置,配置样例如下,具体指令说明如下面表格中所示。

upstream backend {
    server backend1.example.com       weight=5;     # 被代理服务器端口号为80,权重为5
    server backend2.example.com:8080;               # 被代理服务器端口号为8080,默认权重为1
    server unix:/tmp/backend3;

    server backup1.example.com:8080   backup;       # 该被代理服务器为备份状态
    server backup2.example.com:8080   backup;       # 该被代理服务器为备份状态
}

server {
    location / {
        proxy_pass http://backend;          # 将客户端请求反向代理到上游服务器组backend
    }
}

表:服务器指令

<tbody>
	<tr>
		<th>名称</th>
		<th>服务器指令</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>server</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>配置格式</td>
		<td>address[parameters];</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>设定上游服务器组的服务器地址及连接参数</td>
	</tr>
</tbody>

关于上表有以下几点需要注意:

  • 服务器地址可以是指定端口的 IP、域名或 Unix 套接字;
  • 如不指定端口,默认端口号为 80。

表:服务器指令参数

<tbody>
	<tr>
		<th>参数</th>
		<th>参数名称</th>
		<th>参数类型</th>
		<th>默认值</th>
		<th>参数说明</th>
	</tr>
	<tr>
		<td>weight</td>
		<td>权重</td>
		<td>int</td>
		<td>1</td>
		<td>设置服务器的权重</td>
	</tr>
	<tr>
		<td>max_fails</td>
		<td>最大失败数</td>
		<td>int</td>
		<td>1</td>
		<td>被代理服务器在 fail timeout 规定时间内的最大请求失败次数,超过设定值后,被代理服务器便被认为不可用。是否失败由 proxy_next_upstream、fastcgi_next_upstream、uwsgi_next_upstream、scgi_next_upstream、memcached_next_upstream 及 grpe_next_upstream 指令定义。0 表示关闭被代理服务器的失败检测功能</td>
	</tr>
	<tr>
		<td>fail_timeout</td>
		<td>失败超时</td>
		<td>time</td>
		<td>10s</td>
		<td>被代理服务器被置为不可用的最长时间及被代理服务器被连续失败检测的最长时间</td>
	</tr>
	<tr>
		<td>backup</td>
		<td>备份服务器</td>
		<td>--</td>
		<td>--</td>
		<td>将被代理服务器标为备份状态,当其他非备份被代理服务器不可用时,会把请求转发给备份被代理服务器</td>
	</tr>
	<tr>
		<td>down</td>
		<td>无效服务器</td>
		<td>--</td>
		<td>--</td>
		<td>将被代理服务器标为不可用状态</td>
	</tr>
	<tr>
		<td>max_conns</td>
		<td>最大连接数</td>
		<td>int</td>
		<td>0</td>
		<td>与被代理服务器建立活动连接的最大数量,默认值 0 表示没有限制</td>
	</tr>
	<tr>
		<td>resolve</td>
		<td>动态解析</td>
		<td>--</td>
		<td>--</td>
		<td>在被代理服务器域名对应的 IP 变化时,自动更新被代理服务器的 IP,该参数依赖 resolver 指令设置的域名解析服务器。仅对商业版本有效</td>
	</tr>
	<tr>
		<td>service</td>
		<td>DNS SRV 记录</td>
		<td>name</td>
		<td>--</td>
		<td>DNS SRV 记录设置。仅对商业版本有效</td>
	</tr>
	<tr>
		<td>slow_start</td>
		<td>慢恢复时间</td>
		<td>time</td>
		<td>0</td>
		<td>不可用服务器在设置时间内检测持续有效后便被恢复正常,默认关闭。仅对商业版本有效</td>
	</tr>
</tbody>

其中,slow_start 参数不能与 Hash 负载均衡方法一同使用;若上游服务器组中只有一台被代理服务器,则 max_fails、fail_timeout 和 slow_start 参数都会被忽略,并且这个服务器将永远不会被置为无效。

表:共享内存区指令

<tbody>
	<tr>
		<th>名称</th>
		<th>共享内存区指令</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>zone</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>配置格式</td>
		<td>name[size];</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>设定共享内存区域的名称及大小,用以在多个工作进程间共享配置及运行时的状态</td>
	</tr>
</tbody>

表:长连接最大请求数指令

<tbody>
	<tr>
		<th>名称</th>
		<th>长连接最大请求数指令</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>keepalive_requests</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>指令格式</td>
		<td>number;</td>
	</tr>
	<tr>
		<td>默认值</td>
		<td>100;</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>设置每个与被代理服务器建立的长连接中传输请求的最大数量,超过这个值后,该连接将被关闭</td>
	</tr>
</tbody>

表:长连接缓存数

<tbody>
	<tr>
		<th>名称</th>
		<th>长连接缓存数</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>keepalive</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>指令格式</td>
		<td>connections;</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>当 Nginx 与被代理服务器建立长连接时,设定每个工作进程可以缓存的与当前上游服务器组中被代理服务器保持长连接的数量。当超过设定值时,将根据最近最少使用算法(LRU)关闭连接</td>
	</tr>
</tbody>

注意:该指令不会对活跃的 TCP 连接数有影响。

表:长连接缓存超时时间

<tbody>
	<tr>
		<th>名称</th>
		<th>长连接缓存超时时间</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>keepalive_timeout</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>指令格式</td>
		<td>timeout;</td>
	</tr>
	<tr>
		<td>默认值</td>
		<td>60;</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>设置长连接缓存中,每个连接的超时时间,被缓存的连接超过这个时间仍未被激活使用时将被关闭</td>
	</tr>
</tbody>

2、负载均衡策略指令

Nginx 支持多种负载均衡策略,如轮询(Round Robin)、一致性哈希(Consistent Hash)、IP 哈希(IP Hash)、最少连接(least_conn)等。Nginx 的默认负载均衡策略为轮询策略,不需要配置指令,轮询策略通过 server 的权重参数可实现手动分配的加权轮询策略。

负载均衡策略配置指令均应编辑在 upstream 指令域的最上方,常见的配置指令如下面表格中所示。

表:哈希策略

<tbody>
	<tr>
		<th>名称</th>
		<th>哈希策略</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>hash</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>指令格式</td>
		<td>key[consistent];</td>
	</tr>
	<tr>
		<td>默认值</td>
		<td>--</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>设置用于哈希策略计算哈希值的键值,并对上游服务器组启用哈希的负载均衡策略。键值可以是文本、变量及其组合,当 consistent 参数被指定时,将启用 Ketama 一致性哈希的负载均衡策略</td>
	</tr>
</tbody>

配置样例如下:

upstream backend {
    hash $request_uri;              # 以客户端请求URI为计算哈希值的key
    ...
}

upstream backend {
    hash $request_uri consistent;   # 以客户端请求URI为计算哈希值的key,采用一致性哈希算法
    ...
}

表:IP 哈希策略

<tbody>
	<tr>
		<th>名称</th>
		<th>IP 哈希策略</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>ip_hash</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>默认值</td>
		<td>--</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>设置启用 IP 哈希负载均衡策略,根据客户端的 IPv4 地址的前三个八位字节或整个 IPv6 地址作为哈希键计算哈希值,该方法确保同一客户端的请求总会被同一被代理服务器处理。当 IP 哈希值对应的被代理服务器不可用时,请求将被分配给其他服务器</td>
	</tr>
</tbody>

配置样例如下:

upstream backend {
    ip_hash;                # 启用IP哈希负载均衡策略
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    server backend4.example.com;
}

当服务器组中一台服务器被临时删除时,可使用 down 参数标记,那么客户端 IP 哈希值将会保留。

表:最少连接策略

<tbody>
	<tr>
		<th>名称 </th>
		<th>最少连接策略</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>least_conn</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>默认值 </td>
		<td>--</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>在考虑上游服务器组中各服务器权重的前提下,将客户端请求分配给拥有最少活跃连接被代理服务器的负载均衡策略</td>
	</tr>
</tbody>

配置样例如下:

upstream backend {
    least_conn;             # 启用最少连接负载均衡策略
    server backend1.example.com;
    server backend2.example.com;
    server backend4.example.com;
}

表:随机负载策略

<tbody>
	<tr>
		<th>名称</th>
		<th>随机负载策略</th>
	</tr>
	<tr>
		<td>指令</td>
		<td>random</td>
	</tr>
	<tr>
		<td>作用域</td>
		<td>upstream</td>
	</tr>
	<tr>
		<td>默认值</td>
		<td>--</td>
	</tr>
	<tr>
		<td>指令说明</td>
		<td>在考虑上游服务器组中各服务器权重的前提下,将客户端请求分配给随机选择的被代理服务器</td>
	</tr>
</tbody>

配置样例如下:

upstream backend {
    random;                 # 每个请求都被随机发送到某个服务器
    server backend1.example.com;
    server backend2.example.com;
    server backend4.example.com;
}

指令值参数 two,该参数表示随机选择两台被代理服务器,然后使用指定的负载策略进行选择,默认方法为 least_conn;可被指定的负载策略为 least_conn、least_time(仅对商业版有效)。