Nginx
一般用于七层负载均衡,其吞吐量有一定限制。为了提升系统整体吞吐量,会在 DNS
与 Nginx
之间引入接入层,比如使用LVS
(软负载均衡器)、F5
(硬负载均衡器)做四层负载均衡。整体的请求流转如下图所示,即首先 DNS
解析到 LVS/F5
,然后 LVS/F5
转发给 Nginx
,再由 Nginx
转发给后端上游服务器。
对于一般开发人员来说,我们只需要关注 Nginx
层面即可,LVS/F5
一般由运维工程师维护。
四层负载均衡:根据 IP 地址 + 端口将报文转发到上游服务器
七层负载均衡:根据 应用层协议(Http协议)的主机名、URL + 端口将报文转发到上游服务器
配置 upstream
上游服务器列表
upstream backend {
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2;
}
通过 proxy_pass
进行使用
location / {
proxy_pass http://backend;
}
轮询,默认负载均衡算法,通过配合 weight
的配置可以实现基于权重的轮询
对客户IP地址使用哈希算法进行负载均衡,会将相同IP的请求转发给相同的上游服务器
upstream backend {
ip_hash;
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2;
}
对某一个 key
使用哈希算法进行负载均衡,consistent
表示使用一致性哈希算法。
使用哈希算法的问题是,当添加/删除一台服务器时,将导致很多 key 被重新负载到不同的服务器,
这可能会导致后端服务器出问题,使用一致性哈希算法,当添加/删除一台服务器时,
只有少数 key 会被重新负载到不同的服务器,影响面会小很多。
upstream backend {
hash $uri;
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2;
}
也可以在 location
段中设置变量作为 key
location / {
set $consistent_key $arg_cat;
if ($consistent_key = "") {
set $consistent_key $request_uri;
}
}
...
upstream backend {
hash $consistent_key consistent;
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2;
}
将请求负载到最少活跃连接的上游服务器,如果配置的服务器较少,则转而使用基于权重的轮询算法
Nginx 商业版还提供了 least_time 算法,即基于最小平均响应时间进行负载
分为 upstream server
和 proxy_pass
两部分配置
upstream backend {
server 192.168.2.1:8080 max_fails=2 fail_timeout=10s weight=1;
server 192.168.2.1:8090 max_fails=2 fail_timeout=10s weight=2;
}
当 fail_timeout
时间内请求失败 max_fails
次,则认为该上游服务器不可用,然后摘掉该服务器,fail_timeout
时间后会再次将该服务器加入到存活服务器列表进行重试。
location / {
proxy_connect_timeout 5s;
proxy_read_timeout 5s;
proxy_sned_timeout 5s;
proxy_next_upstream error timeout;
proxy_next_upstream_timeout 10s;
proxy_next_upstream_tries 2;
proxy_pass http://backend;
}
当请求出错,或者超时,会重试下一台上游服务器。
Nginx
对上游服务器的健康检查默认采用的是惰性策略。Nginx
商业版提供了 health_check
进行主动健康检查,也可以通过集成 nginx_upstream_check_module
模块来进行主动健康检查。
nginx_upstream_check_module
支持 TCP
心跳和 HTTP
心跳来实现健康检查。
upstream backend {
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2;
check interval=3000 rise=1 fail=3 timeout=2 type=tcp;
}
upstream backend {
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2;
check interval=3000 rise=1 fail=3 timeout=2 type=http;
check_http_send "HEAD /status HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
检查间隔时间不能太短,否则可能因为心跳检查包太多造成上游服务器挂掉,同时要设置合理的超时时间
设置该服务器为备份服务器,当所有主服务器都不存活时,请求会转发给备份服务器
upstream backend {
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2 backup;
}
upstream backend {
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2 down;
}
配置每个 worker
进程与上游服务器可缓存的空闲长连接最大数量,当超出这个数量时,最近最少使用的连接将被关闭。
upstream backend {
server 192.168.2.1:8080 weight=1;
server 192.168.2.1:8090 weight=2;
keepalive 100;
}
空闲连接池太小,连接不够用,需要不断新建连接
空闲连接池太大,空闲连接太多,还没使用就超时
建议只对小报文开启长连接