第一步:将HTTP流量代理到一组服务器
首先,我们得有一组服务器。
我的服务器分别是:192.168.98.131
、192.168.98.132
、192.168.98.133
、192.168.98.134
。
(后面的配置内容请把服务器IP或者域名换成你自己的)
首先,将192.168.98.131
作为反向代理服务器,配置工作会在后续完成。
通过如下命令,在反向代理服务器上打开nginx
的配置文件:
sh
vim /usr/local/nginx/conf/nginx.conf
在http
上下文内,添加upstream
块指令,配置服务器组,具体内容如下:
sh
http {
# 服务器组名为 **backend**
upstream backend {
# `weight=5`是用来指定负载均衡算法中各个后端服务器的权重
server 192.168.98.132 weight=5;
server 192.168.98.133;
# `backup` 是用来指定备用服务器的。
# 当其他所有的服务器都无法响应请求时,备用服务器将会被用来处理请求
server 192.168.98.134 backup;
}
}
为了能够将请求转发到服务器组上,我们需要配置反向代理。在同一个http
上下文内,添加server
块指令:
sh
http {
# 同一个http上下文
upstream backend {
# 内容省略
}
server {
location / {
# 配置反向代理到backend服务器组
proxy_pass http://backend;
}
}
}
对于http
(https
)之外其他协议,也可以将proxy_pass
替换为fastcgi_pass
, memcached_pass
, scgi_pass
, 或者 uwsgi_pass
等对应的指令。
至此,我们已经可以成功将HTTP流量代理到backend
服务器组上。该组由三个服务器组成,其中两个运行相同的应用程序实例,而第三个是备用服务器。由于在 upstream
块中未指定负载均衡算法,NGINX
使用默认算法,即循环轮询(Round Robin
)。
第二步: 选择一个负载均衡方法
nginx
有四种方法,下面分别对他们做解释,以及演示如何配置。 nginx plus
有额外的两种,在此则不做解释。
-
轮叫调度(
Round Robin
),依据权重均匀地将请求分配到组中的每个服务器。Round Robin
是默认开启的,因此不需要额外的配置; -
最少链接(
Least Connections
),依据权重,将请求转发给当前最不忙(具有最少活跃连接数)的服务器;通过
least_conn
开启Least Connections
shupstream backend { least_conn; # 省略其他内容 }
-
IP Hash
,使用客户端的 IP 地址作为哈希函数的输入,然后将哈希值映射到一组服务器中的一个,以确定哪台服务器接收请求。这种方法的好处是,相同 IP 地址的客户端将始终被路由到相同的服务器上,这对于某些应用场景(例如会话保持)非常有用。
权重也会影响
IP Hash
。shupstream backend { ip_hash; # 省略其他内容 }
一点个人理解:
IP Hash
就是Round Robin
的特别定制版,他从某个角度来说和Round Robin
差不多,都是无差别的分发请求,即无法和最少链接一样,通过考虑服务器的负载状况,来进行负载均衡。只不过IP Hash
通过哈希映射,保证了会话的一致性,这是IP Hash
相较于Round Robin
的特别之处。他在特定的场景有很大的优势,但普遍性的优势还不如Round Robin
,因为他是特别定制版,继承了Round Robin
的所有优点和缺点,换句话说,他的特别订制之处(会话的一致性)无法发挥出来的话,反而会成为他相较于Round Robin
的新缺点(冗余计算) -
Generic Hash
,使用用户自定义的关键字(可以是ip和端口的组合,或者是URI
)作为哈希函数的输入,然后将哈希值映射到一组服务器中的一个,以确定哪台服务器接收请求。相较于
IP Hash
,Generic Hash
具有更高的灵活性。他可以依据任何应用程序的需求定义灵活的负载均衡策略(不仅仅是ip),例如,可以基于请求的特定业务属性或来源信息来动态地分发请求。shupstream backend { # $request_uri是一个 Nginx 内置变量,用于表示客户端请求的完整 URI,包括查询参数 # 在这里表示使用客户端请求的 URI 作为哈希键来进行负载均衡 # `consistent`参数用于启用`ketama consistent-hash`负载均衡算法。 hash $request_uri consistent; server backend1.example.com; server backend2.example.com; }
关于
ketama consistent-hash
负载均衡算法的个人理解:Generic Hash
可以通过用户定义的关键字来确定将请求发送到哪个服务器,但他无法保证每台服务器应对的用户数量是一样的。当我们需要移除一台服务器时,如果被移除的服务器是应对用户最多的那台,就会产生很大的麻烦。而ketama consistent-hash
则保证了每台服务器应对的用户都大体同样多,保证了每台服务器的可替代性,保证了不会出现某台服务器占用太多的用户,导致替换成本升高。同时,当一台新服务器加入时,也会逐渐增加对这台服务器的流量负载,而不是立即将所有请求都发送到该服务器上。这样可以确保服务器逐渐恢复并处理负载,而不会被过多的连接压垮。当需要移除或添加服务器时,该算法仅重新映射了少量的键值,避免了大规模的负载重新分配,减少了系统的波动性。