负载均衡
之前的章节内容中【深入浅出学习透析Nginx服务器的基本原理和配置指南「初级实践篇 」】和 【深入浅出学习透析Nginx服务器的基本原理和配置指南「进阶实践篇」】,我们采用的代理仅仅指向一个服务器。但是网站在实际运营过程中,大部分都是以集群的方式运行,这时需要使用负载均衡来分流。Nginx也可以实现简单的负载均衡功能。
Nginx作为HTTP负载均衡器
Nginx是以高并发和内存占用少出名,它是一个http服务器,也是反向代理服务器,它更是负载均衡器。作为负载均衡器,在版本1.9之前,它只能作为http的负载均衡,也就是在网络模型的第七层发挥作用,1.9之后,它可以对tcp进行负载均衡,比如redis,mysql等。
负载均衡跨越多个应用程序实例,在多个应用实例间做负载均衡是一个被广泛使用的技术,其用于优化资源利用率、最大化吞吐量、减少延迟和确保容错配置。可以使用Nginx作为高效的HTTP负载均衡器,将流量分布到多个应用服务器,并通过Nginx 提高 web 应用程序的性能、可扩展性和可靠性。
Nginx的负载均衡方法
Nginx 提供了多种负载均衡策略,常用的支持以下负载均衡机制:
- 轮询(round-robin) - 发送给应用服务器的请求以轮询的方式分发
- 加权轮询(weight-round-robin)
- 最少连接(least-connected) - 下一个请求被分配给具有最少数量活动连接的服务器
- 加权最少连接(weight-least-connected)
- ip 哈希(ip-hash) - 使用哈希函数确定下一个请求应该选择哪一个服务器(基于客户端的 IP 地址)
- 普通 Hash(url-hash)- request_uri,一个简单的负载均衡的示例,把url均衡到不同的服务器,也可以改为均衡到不同的地址上。
Nginx的负载均衡语法
upstream指令
upstream指令用于定义服务器集群。服务器可以监听在不同端口。另外,监听在TCP和UNIX-domain socket的服务器可以混合使用。默认,使用带权重的round-robin平衡算法将请求分派到服务器。
http {
upstream [你的负载均衡机制名称,随便设置一个就好] {
server [ip地址]:[端口值];
server [ip地址]:[端口值];
server [ip地址]:[端口值];
server [ip地址]:[端口值];
}
server {
listen [nginx监听端口];
server_name [head中的host对应的值]
location / {
proxy_pass http:// [你的负载均衡机制名称,对应上面upstream的值];
}
}
}
默认负载均衡配置
使用Nginx进行负载均衡的最简单配置如下所示:
在上述案例中,在 【www.address1.com】、【www.address2.com】、【www.address3.com】,我们需要启动暴漏运行相同的应用的三个实例。当负载均衡方法没有被特别配置时,默认采用轮询(round-robin)。所有请求都被代理到服务器组loadBalanceServer,Nginx应用 HTTP 负载均衡来分发请求。
http {
upstream loadBalanceServer {
server www.address1.com; // 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com;
server www.address3.com;
}
server {
listen 80;
location / {
proxy_pass http://loadBalanceServer;
}
}
}
Nginx中的反向代理实现包括 HTTP、HTTPS、FastCGI、uwsgi、SCGI 和 memcached。要配置 HTTPS 而不是 HTTP 负载均衡,只需要使用 HTTPS 协议。在为 FastCGI、uwsgi、SCGI 或 memcached 设置负载均衡时,分别使用 fastcgi_pass、uwsgi_pass、scgi_pass 和 memcached_pass 指令。
最少连接负载均衡
- 负载均衡的规则是最少连接。在一些请求需要更长的时间才能完成的情况下,最少连接可以更公正地控制应用程序实例的负载。使用最少连接的负载均衡,nginx 将尽量不给过于繁忙的应用服务器负载过多的请求,而是将新的请求分发到不太忙的服务器。
- 当使用 least_conn 指令作为服务组配置的一部分时,将激活 nginx 中的最少连接负载均衡:
http {
upstream leastConnLoadBalanceServer {
least_conn;
server www.address1.com; // 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com;
server www.address3.com;
}
server {
listen 80;
location / {
proxy_pass http://loadBalanceServer;
}
}
}
IP哈希负载均衡
配置 IP 哈希负载均衡,只需要将 ip_hash 指令添加到服务器 upstream 组配置中即可:
http {
upstream ipHashLoadBalanceServer {
ip_hash;
server www.address1.com; // 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com;
server www.address3.com;
}
server {
listen 80;
location / {
proxy_pass http://loadBalanceServer;
}
}
}
普通 Hash
主要根据url进行hash计算处理操作,没啥可讲解的
http {
upstream ipHashLoadBalanceServer {
hash $request_uri;
server www.address1.com; // 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com;
server www.address3.com;
}
server {
listen 80;
location / {
proxy_pass http://loadBalanceServer;
}
}
}
加权负载均衡
可以通过使用服务器权重进一步加强Nginx的负载均衡算法。
-
在上面的示例中,服务器权重没有被配置,这意味对于特定的负载均衡方法来说所有指定的服务器都具有同等资格。
-
特别是使用轮询方式,这也意味着服务器上的请求分配或多或少都是相等的 —— 只要有足够的请求,并且以统一的方式足够快速地完成请求处理。
-
当服务器指定 weight 参数时,权重将作为负载均衡决策的一部分进行核算, weigth参数表示权值,权值越高被分配到的几率越大,默认情况下(轮询)所有服务器权重为 1。
http {
upstream ipHashLoadBalanceServer {
ip_hash;
server www.address1.com weight=3;// 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com; // default weight=1
server www.address3.com;
}
server {
listen 80;
location / {
proxy_pass http://loadBalanceServer;
}
}
}
在 nginx 的最近版本中,可以在最少连接和 IP 哈希负载均衡中使用权重。
最少连接负载均衡(加权)
http {
upstream leastConnLoadBalanceServer {
least_conn;
server www.address1.com; // 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com weight=3;
server www.address3.com;
}
server {
listen 80;
location / {
proxy_pass http://loadBalanceServer;
}
}
}
会话持久化
-
使用轮询或者最少连接的负载均衡,每个后续客户端的请求都可能被分配到不同的服务器。不能保证同一个客户端始终指向同一个服务器。
-
如果需要将客户端绑定到特定的应用服务器,换而言之,使客户端会话「粘滞」或者「永久」,始终尝试选择特定的服务器,IP 哈希负载均衡机制可以做到这点。
-
使用 IP 哈希,客户端的 IP 地址用作为哈希键,以确定应用为客户端请求选择服务器组中的哪个服务器。此方法确保了来自同一个客户端的请求始终被定向到同一台服务器,除非该服务器不可用。
Nginx健康检查
-
Nginx中的反向代理实现包括了带内(或者被动)服务器健康检查。如果特定服务器的响应失败并出现错误,则 nginx 会将此服务器标记为失败,并尝试避免为此后续请求选择此服务器而浪费一段时间。
-
max_fails 用于设置在 fail_timeout 期间与服务器通信失败重新尝试的次数。默认情况下,max_fails 设置为 1。当设置为 0 时,该服务器的健康检查将被禁用。fail_timeout 参数还定义了服务器被标记为失败的时间。在服务器发生故障后的 fail_timeout 间隔后,nginx 开始以实时客户端的请求优雅地探测服务器。如果探测成功,则将服务器标记为活动。
故障下线和备份服务设置
down
假如有一台主机是出了故障,或者下线了,要暂时移出,那可以把它标为down,表示请求是会略过这台主机的。
upstream downServer {
server www.address1.com; // 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com down;
}
backup
backup是指备份的机器,相对于备份的机器来说,其他的机器就相当于主要服务器,只要当主要服务器不可用的时候,才会用到备用服务器。
upstream backupServer {
server www.address1.com; // 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com backup;
}
max_fails和fail_timeout
默认情况下,max_fails的值为1,表示的是请求失败的次数,请求1次失败就换到下台主机。另外还有一个参数是fail_timeout,表示的是请求失败的超时时间,在设定的时间内没有成功,那作为失败处理。
upstream backupServer {
server www.address1.com max_fails=2; // 或者ip+端口 , 不需要加入http/https前缀
server www.address2.com backup;
}
那什么情况才叫请求失败呢?有可能是服务器内部错误,超时,无效的头部,或返回500以上的状态码的时候。
Nginx实际案例配置
nginx.conf 配置如下:
http {
#设定mime类型,类型由mime.type文件定义
include /etc/nginx/mime.types;
default_type application/octet-stream;
#设定日志格式
access_log /var/log/nginx/access.log;
#设定负载均衡的服务器列表
upstream load_balance_server {
#weigth参数表示权值,权值越高被分配到的几率越大
server 192.168.1.11:80 weight=5;
server 192.168.1.12:80 weight=1;
server 192.168.1.13:80 weight=6;
}
#HTTP服务器
server {
#侦听80端口
listen 80;
#定义使用www.xx.com访问
server_name www.helloworld.com;
#对所有请求进行负载均衡请求
location / {
root /root; #定义服务器的默认网站根目录位置
index index.html index.htm; #定义首页索引文件的名称
proxy_pass http://load_balance_server ;#请求转向load_balance_server 定义的服务器列表
#以下是一些反向代理的配置(可选择性配置)
#proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $remote_addr;
proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传
client_max_body_size 10m; #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数
}
}
}